Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Form + GridForm): Add actual required optional + required form text #2872

Merged
merged 48 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
e8e909c
reorg form elements
dreamwasp Apr 30, 2024
f1455da
start sharing types in fields
dreamwasp Apr 30, 2024
14738c9
more deduplicating
dreamwasp Apr 30, 2024
b7ab50f
start serious work on required
dreamwasp Apr 30, 2024
cdaba56
Merge branch 'main' into cass-gm-620
dreamwasp May 1, 2024
3a02080
more deduplicating
dreamwasp May 1, 2024
f77013e
Merge branch 'cass-gm-620' of ssh://github.com/Codecademy/gamut into …
dreamwasp May 1, 2024
70d5faf
better text and start connectedform
dreamwasp May 1, 2024
ea93422
add formrequiredtext to hook, pending docs changes
dreamwasp May 1, 2024
5d55673
add stories + start fixing test failures
dreamwasp May 1, 2024
86d0ecf
lots of test fixing
dreamwasp May 1, 2024
e3ff897
more test updates
dreamwasp May 1, 2024
150645f
fix stories
dreamwasp May 1, 2024
79614a8
fix blanks
dreamwasp May 1, 2024
4048d99
Merge branch 'main' into cass-gm-620
dreamwasp May 2, 2024
7361b50
add wrapperProps to title
dreamwasp May 2, 2024
2f958b7
Merge branch 'cass-gm-620' of ssh://github.com/Codecademy/gamut into …
dreamwasp May 2, 2024
398475f
add wrapperProps to title
dreamwasp May 2, 2024
675c413
Merge branch 'main' into cass-gm-620
dreamwasp May 2, 2024
bee7c73
auto-import, smh
dreamwasp May 2, 2024
cad5409
prettier issues, go figure
dreamwasp May 2, 2024
5a77ab8
remove confusing story
dreamwasp May 7, 2024
95ce7db
add more docs
dreamwasp May 8, 2024
02e89f3
add required styling
dreamwasp May 8, 2024
ec70213
update conventional commit + stories
dreamwasp May 8, 2024
835dbf2
test convetentional commit
dreamwasp May 8, 2024
76571a2
Merge branch 'main' into cass-gm-620
dreamwasp May 8, 2024
f563ee4
remove asterisk
dreamwasp May 10, 2024
30e4ef2
Merge branch 'main' into cass-gm-620
dreamwasp May 14, 2024
fabe667
fix stories
dreamwasp May 14, 2024
7b92e36
Merge branch 'cass-gm-620' of ssh://github.com/Codecademy/gamut into …
dreamwasp May 14, 2024
d73c506
fix more tests
dreamwasp May 15, 2024
e17858d
format :)
dreamwasp May 17, 2024
f5d3380
try to jumpstart pkg cache
dreamwasp May 17, 2024
eed9352
revert
dreamwasp May 17, 2024
cd9461f
solofield kindof working
dreamwasp May 22, 2024
57ae5c1
fix solo fields
dreamwasp May 22, 2024
a0871c4
fix solo fields
dreamwasp May 22, 2024
787c71a
require fields etc
dreamwasp May 22, 2024
4e833b2
Merge branch 'main' into cass-gm-620
dreamwasp May 22, 2024
68d976f
require fields etc
dreamwasp May 22, 2024
f251689
fix labels + tests
dreamwasp May 22, 2024
3e8efcc
Merge branch 'cass-gm-620' of ssh://github.com/Codecademy/gamut into …
dreamwasp May 22, 2024
8e02040
heading
dreamwasp May 23, 2024
4454feb
kenny feedback
dreamwasp May 28, 2024
19407e0
format stories
dreamwasp May 29, 2024
409950d
kill cache
dreamwasp May 29, 2024
4bbe1ff
kill cache?
dreamwasp May 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/gamut-styles/README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
# Gamut Styles

Base SCSS for Codecademy

## Variables/

This folder houses all shared SCSS style variables.
It also contains a JavaScript file with color variables.

## Core/

This folder contains a base stylesheet for the app.
This should be imported **once** in your application.

## Utils/

This folder contains Sass functions (pure utilities with no stylesheet output values) and mixins (outputs CSS)
to be used as needed both in Gamut and across the Codecademy app.


The `utils.scss` and `core.scss` just import the index files from their respective folders, to make the syntax to import them from elsewhere easier, e.g.:

`@import "~@codecademy/gamut-styles/utils";`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ exports[`Gamut Exported Keys 1`] = `
"FormGroupDescription",
"FormGroupLabel",
"FormPropsContext",
"FormRequiredText",
"generateResponsiveClassnames",
"GridBox",
"GridForm",
Expand Down
9 changes: 1 addition & 8 deletions packages/gamut/src/ConnectedForm/ConnectedForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
} from 'react-hook-form';

import { Form } from '../Form';
import { FormProps } from '../Form/Form';
import { FormProps } from '../Form/elements/Form';
import { FormValues } from '../Form/types';
import { submitSuccessStatus } from './utils';

Expand All @@ -27,10 +27,6 @@ export interface FormContextProps {
* If fields should be reset after successful submission.
*/
resetOnSubmit?: boolean;
/**
* If required field should show asterisks in labels.
*/
showRequired?: boolean;
/**
* Validation rules form fields. Fields with validation rules must have a defaultValue listed in the defaultValue prop.
*/
Expand Down Expand Up @@ -99,7 +95,6 @@ export const ConnectedForm = forwardRef(
validation = 'onChange',
disableFieldsOnSubmit = false,
resetOnSubmit = false,
showRequired = false,
validationRules,
wasSubmitSuccessful = undefined,
watchedFields,
Expand Down Expand Up @@ -147,14 +142,12 @@ export const ConnectedForm = forwardRef(
return {
disableFieldsOnSubmit,
resetOnSubmit,
showRequired,
validationRules,
wasSubmitSuccessful,
};
}, [
disableFieldsOnSubmit,
resetOnSubmit,
showRequired,
validationRules,
wasSubmitSuccessful,
]);
Expand Down
15 changes: 5 additions & 10 deletions packages/gamut/src/ConnectedForm/ConnectedFormGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ export interface ConnectedFormGroupBaseProps
name: string;
label: React.ReactNode;
required?: boolean;
showRequired?: boolean;
infotip?: InfoTipProps;
}

Expand All @@ -60,14 +59,10 @@ export function ConnectedFormGroup<T extends ConnectedField>({
spacing = 'fit',
infotip,
}: ConnectedFormGroupProps<T>) {
const {
error,
isFirstError,
isDisabled,
showRequired,
setError,
validation,
} = useField({ name, disabled });
const { error, isFirstError, isDisabled, setError, validation } = useField({
name,
disabled,
});
const { component: Component, ...rest } = field;

useEffect(() => {
Expand All @@ -84,7 +79,7 @@ export function ConnectedFormGroup<T extends ConnectedField>({
disabled={isDisabled}
htmlFor={id || name}
infotip={infotip}
showRequired={showRequired && !!validation}
required={!!validation?.required}
size={labelSize}
>
{label}
Expand Down
7 changes: 3 additions & 4 deletions packages/gamut/src/ConnectedForm/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
useFormContext,
} from 'react-hook-form';

import { FormRequiredText } from '../Form';
import {
ConnectedForm,
ConnectedFormGroup,
Expand Down Expand Up @@ -74,7 +75,9 @@ export const useConnectedForm = <
validationRules,
watchedFields,
},
FormRequiredText,
}),

// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
Expand Down Expand Up @@ -109,7 +112,6 @@ export const useFormState = () => {

const {
disableFieldsOnSubmit,
showRequired,
validationRules,
wasSubmitSuccessful,
} = useContext(FormPropsContext);
Expand All @@ -132,7 +134,6 @@ export const useFormState = () => {
setFocus,
setError,
setValue,
showRequired,
useFieldArray,
validationRules,
watch,
Expand All @@ -156,7 +157,6 @@ export const useField = ({ name, disabled, loading }: useFieldProps) => {
isDisabled: formStateDisabled,
setError,
setValue,
showRequired,
validationRules,
} = useFormState();

Expand Down Expand Up @@ -190,7 +190,6 @@ export const useField = ({ name, disabled, loading }: useFieldProps) => {
ref,
setValue,
setError,
showRequired,
};
};

Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/DataList/Controls/SelectControl.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';

import { Checkbox } from '../../Form/Checkbox';
import { Checkbox } from '../../Form/inputs/Checkbox';
import { Text } from '../../Typography/Text';
import { RowChange } from '..';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
import * as React from 'react';
import { Options as OptionsType, StylesConfig } from 'react-select';

import { getMemoizedStyles } from '../styles';
import { parseOptions } from '../utils';
import {
CustomContainer,
Expand All @@ -26,6 +25,7 @@ import {
SelectDropdownContext,
TypedReactSelect,
} from './elements';
import { getMemoizedStyles } from './styles';
import { ExtendedOption, OptionStrict, SelectDropdownProps } from './types';
import {
filterValueFromOptions,
Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/Form/SelectDropdown/types.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
Props as NamedProps,
} from 'react-select';

import { SelectComponentProps, SelectOptions } from '../Select';
import { SelectComponentProps, SelectOptions } from '../inputs/Select';
import { SelectOptionBase } from '../utils';
import { conditionalBorderStates } from './styles';

Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/Form/__tests__/Checkbox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupRtl } from '@codecademy/gamut-tests';
import { fireEvent } from '@testing-library/dom';

import { Checkbox } from '../Checkbox';
import { Checkbox } from '../inputs/Checkbox';

const onChange = jest.fn();

Expand Down
43 changes: 30 additions & 13 deletions packages/gamut/src/Form/__tests__/FormGroup.test.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,48 @@
import { setupRtl } from '@codecademy/gamut-tests';

import { FormGroup } from '../FormGroup';
import { Input } from '../Input';
import { FormGroup } from '../elements/FormGroup';
import { Input } from '../inputs/Input';

const renderView = setupRtl(FormGroup, {
children: <Input id="up-dog" />,
});

const label = 'up dog';
const htmlFor = 'up-dog';
const optional = '(optional)';
const optionalLabelText = `${label} (optional)`;

describe('FormGroup', () => {
it('renders Label as a label when htmlFor is provided', () => {
const { view } = renderView({ label: 'up dog', htmlFor: 'up-dog' });
describe('when htmlFor is provided', () => {
it('renders Label as a label', () => {
const { view } = renderView({ label, htmlFor });

view.getByLabelText('up dog');
view.getByLabelText(optionalLabelText);
});
it('render (optional) as aria-hidden', async () => {
const { view } = renderView({ label, htmlFor });
expect(view.getByText(optional)).toHaveAttribute('aria-hidden', 'true');
});
});
describe('when htmlFor is not provided', () => {
it('renders Label as a div', () => {
const { view } = renderView({ label });

it('renders Label as a div when no htmlFor is provided', () => {
const { view } = renderView({ label: 'up dog' });
expect(view.queryByLabelText(optionalLabelText)).toBeNull();
view.getByText(label);
});

expect(view.queryByLabelText('up dog')).toBeNull();
view.getByText('up dog');
it('render (optional) as aria-hidden', () => {
const { view } = renderView({ label });
expect(view.getByText(optional)).toHaveAttribute('aria-hidden', 'true');
});
});

it('adds an asterisk to showRequired labels', () => {
it('adds an asterisk to required labels', () => {
const { view } = renderView({
label: 'up dog',
htmlFor: 'up-dog',
showRequired: true,
label,
htmlFor,
required: true,
});

view.getByLabelText('up dog *');
Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/Form/__tests__/Input.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { StreakIcon } from '@codecademy/gamut-icons';
import { setupRtl } from '@codecademy/gamut-tests';

import { Input } from '../Input';
import { Input } from '../inputs/Input';

jest.mock('@codecademy/gamut-icons', () => ({
AlertIcon: () => (
Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/Form/__tests__/Radio.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { setupRtl } from '@codecademy/gamut-tests';
import { fireEvent } from '@testing-library/dom';

import { Radio } from '../Radio';
import { Radio } from '../inputs/Radio';

const onChangeCallback = jest.fn();
const testid = 'my-test-id';
Expand Down
4 changes: 2 additions & 2 deletions packages/gamut/src/Form/__tests__/RadioGroup.test.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { setupRtl } from '@codecademy/gamut-tests';
import { fireEvent } from '@testing-library/dom';

import { Radio } from '../Radio';
import { RadioGroup } from '../RadioGroup';
import { Radio } from '../inputs/Radio';
import { RadioGroup } from '../inputs/RadioGroup';

const renderView = setupRtl(RadioGroup, {
htmlForPrefix: 'what-salad-maker-do-you-prefer',
Expand Down
2 changes: 1 addition & 1 deletion packages/gamut/src/Form/__tests__/Select.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { setupRtl } from '@codecademy/gamut-tests';

import { Select } from '../Select';
import { Select } from '../inputs/Select';

const selectOptions = ['red', 'yellow', 'green'];
const defaultProps = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,21 @@ import styled from '@emotion/styled';
import { ComponentProps } from 'react';
import * as React from 'react';

import { Box } from '../Box';
import { InfoTipProps } from '../Tip';
import { Box } from '../../Box';
import { InfoTipProps } from '../../Tip';
import { BaseInputProps } from '../types';
import { FormError } from './FormError';
import { FormGroupDescription } from './FormGroupDescription';
import { FormGroupLabel } from './FormGroupLabel';

export interface FormGroupProps
extends ComponentProps<typeof FormGroupContainer> {
label?: string;
extends ComponentProps<typeof FormGroupContainer>,
Omit<BaseInputProps, 'name' | 'error'> {
/**
* [The for/id string of a label or labelable form-related element](https://developer.mozilla.org/en-US/docs/Web/API/HTMLLabelElement/htmlFor). The outer FormGroup or FormLabel should have an identical string as the inner FormElement for accessibility purposes.
*/
htmlFor?: string;
description?: string;
showRequired?: boolean;
error?: string;
description?: string;
disabled?: boolean;
labelSize?: 'small' | 'large';
infotip?: InfoTipProps;
Expand Down Expand Up @@ -73,13 +72,13 @@ export const FormGroup: React.FC<FormGroupProps> = ({
infotip,
label,
labelSize,
showRequired,
required,
...rest
}) => {
const labelComponent = label ? (
<FormGroupLabel
htmlFor={htmlFor}
showRequired={showRequired}
required={required}
size={labelSize}
disabled={disabled}
infotip={infotip}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { css } from '@codecademy/gamut-styles';
import styled from '@emotion/styled';

import { formBaseStyles } from './styles';
import { formBaseStyles } from '../styles';

export const FormGroupDescription = styled.div(css(formBaseStyles));
Loading
Loading