Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 11 additions & 1 deletion src/components/form/checkbox/checkbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const CheckboxComponent: Story = {
play: async ({ canvasElement, args }) => {
const canvas = within(canvasElement);
const pre = await canvas.findByRole("log");
const input = canvas.getByLabelText(args.children);
const input = canvas.getByLabelText(args.children as string);
let data;

// On
Expand All @@ -46,3 +46,13 @@ export const CheckboxComponent: Story = {
await expect(data.input).toBe(args.value || "on");
},
};

export const InvalidCheckboxComponent: Story = {
args: {
children: "Click me!",
name: "input",
value: "",
invalid: true,
},
argTypes: FORM_TEST_ARG_TYPES,
};
15 changes: 15 additions & 0 deletions src/components/form/checkbox/checkboxgroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,18 @@ export const CheckboxGroupComponent: Story = {
await expect(data.school_year).toEqual(["Freshman", "Junior", "Graduate"]);
},
};

export const InvalidCheckboxGroupComponent: Story = {
args: {
label: "Select school year",
name: "school_year",
options: [
{ label: "Freshman" },
{ label: "Sophomore" },
{ label: "Junior" },
{ label: "Senior" },
{ label: "Graduate" },
],
invalid: true,
},
};
8 changes: 8 additions & 0 deletions src/components/form/checkbox/checkboxgroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ export type CheckboxGroupProps = ChoiceFieldProps<
> & {
/** Whether the items appear horizontally (h) or vertically (v), mobile devices always use vertical. */
direction?: "h" | "v";

/**
* Invalid checkbox groups get additional markup/styling and aria tags to indicate the
* invalid state.
*/
invalid?: boolean;
};

export const CheckboxGroup: React.FC<CheckboxGroupProps> = ({
Expand All @@ -25,6 +31,7 @@ export const CheckboxGroup: React.FC<CheckboxGroupProps> = ({
onChange,
onClick,
disabled,
invalid,
}) => {
const reactId = useId();
const _id = id || reactId;
Expand Down Expand Up @@ -54,6 +61,7 @@ export const CheckboxGroup: React.FC<CheckboxGroupProps> = ({
onChange={onChange}
onClick={onClick}
disabled={disabled}
invalid={invalid}
>
{option.label}
</Checkbox>
Expand Down
6 changes: 6 additions & 0 deletions src/components/form/choicefield/choicefield.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ export type ChoiceFieldProps<

/** Disabled state. */
disabled?: boolean;

/**
* Invalid choicefield fields get additional markup/styling and aria tags to indicate
* the invalid state.
*/
invalid?: boolean;
};
/**
* A single (select) option, can be passed to `Select as array.
Expand Down
8 changes: 8 additions & 0 deletions src/components/form/dateinput/dateinput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ export const DateInputComponent: Story = {
decorators: [FORM_TEST_DECORATOR],
};

export const InvalidDateInputComponent: Story = {
args: {
name: "date",
invalid: true,
},
decorators: [FORM_TEST_DECORATOR],
};

export const SeparatedInputs: Story = {
args: {
name: "date",
Expand Down
8 changes: 8 additions & 0 deletions src/components/form/dateinput/dateinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ export type DateInputProps = {

/** Disabled state. */
disabled?: boolean;

/**
* Invalid dateinput fields get additional markup/styling and aria tags to indicate the
* invalid state.
*/
invalid?: boolean;
};

/**
Expand All @@ -88,6 +94,7 @@ export const DateInput: React.FC<DateInputProps> = ({
value = null,
onChange,
disabled = false,
invalid,
...props
}) => {
type SanitizedValues = { DD: string; MM: string; YY: string };
Expand Down Expand Up @@ -355,6 +362,7 @@ export const DateInput: React.FC<DateInputProps> = ({
pad: pad,
required,
disabled,
"aria-invalid": invalid,
};
}, [props]);

Expand Down
10 changes: 10 additions & 0 deletions src/components/form/datepicker/datepicker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,16 @@ export const DatepickerComponent: Story = {
},
};

export const InvalidDatepickerComponent: Story = {
args: {
type: "datepicker",
name: "date",
value: "2023-09-15",
invalid: true,
},
decorators: [FORM_TEST_DECORATOR],
};

export const DatePickerWithoutValue: Story = {
...DatepickerComponent,
args: {
Expand Down
8 changes: 8 additions & 0 deletions src/components/form/datepicker/datepicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ export type DatePickerProps = Omit<

/** Gets called when the value is changed. */
onChange?: React.ChangeEventHandler<HTMLInputElement>;

/**
* Invalid datepicker fields get additional markup/styling and aria tags to indicate
* the invalid state.
*/
invalid?: boolean;
};

/**
Expand Down Expand Up @@ -85,6 +91,7 @@ export const DatePicker: React.FC<DatePickerProps> = ({
labelWeek,
pad = true,
onChange,
invalid,
...props
}) => {
const fakeInputRef = React.useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -340,6 +347,7 @@ export const DatePicker: React.FC<DatePickerProps> = ({
showIcon
icon={icon || <Outline.CalendarIcon />}
onChange={handleChange}
ariaInvalid={invalid !== undefined ? invalid.toString() : undefined}
{...props}
/>
</>
Expand Down
9 changes: 9 additions & 0 deletions src/components/form/daterangeinput/daterangeinput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ export const DateRangeInputComponent: Story = {
decorators: [FORM_TEST_DECORATOR],
};

export const InvalidDateRangeInputComponent: Story = {
args: {
name: "daterange",
value: "1988-08-02/2023-09-15",
invalid: true,
},
decorators: [FORM_TEST_DECORATOR],
};

export const SeparatedInputs: Story = {
args: {
name: "date",
Expand Down
5 changes: 5 additions & 0 deletions src/components/form/durationinput/durationinput.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ export const Designator: Story = {
},
};

export const InvalidDesignator: Story = {
args: { mode: "designator", invalid: true },
render: (args) => <Controlled {...args} initial="" />,
};

export const DesignatorWithWeeks: Story = {
args: { mode: "designator" },
render: (args) => <Controlled {...args} initial="P8W" />,
Expand Down
8 changes: 8 additions & 0 deletions src/components/form/durationinput/durationinput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ export type DurationInputProps = {

/** Gets called when the value is changed. */
onChange?: React.ChangeEventHandler<HTMLInputElement>;

/**
* Invalid duration fields get additional markup/styling and aria tags to indicate the
* invalid state.
*/
invalid?: boolean;
};

type Key = keyof DurationNoTime;
Expand Down Expand Up @@ -100,6 +106,7 @@ export const DurationInput: React.FC<DurationInputProps> = ({
onChange,
labelOverrides,
placeholderOverrides,
invalid,
...rest
}) => {
const hiddenRef = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -223,6 +230,7 @@ export const DurationInput: React.FC<DurationInputProps> = ({
<Input
id={inputId}
aria-label={placeholder}
aria-invalid={invalid}
pad={pad}
placeholder={placeholder}
{...inputProps}
Expand Down
4 changes: 0 additions & 4 deletions src/components/form/formcontrol/formcontrol.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@
}
}

&--error {
--form-border: var(--form-formcontrol-danger-border);
}

&--justify-stretch {
align-items: stretch;

Expand Down
1 change: 0 additions & 1 deletion src/components/form/formcontrol/formcontrol.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,6 @@ export const FormControl: React.FC<FormControlProps> = ({
`mykn-form-control--justify-${justify}`,
{
[`mykn-form-control--direction-${direction[0]}`]: direction,
"mykn-form-control--error": error,
},
)}
>
Expand Down
25 changes: 24 additions & 1 deletion src/components/form/input/input.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

appearance: none;
align-items: center;
background: var(--form-input-background);
background: var(--form-input-default-background);
border: 1px solid var(--form-border);
border-radius: var(--sizes-border-radius-s);
box-sizing: border-box;
Expand Down Expand Up @@ -64,6 +64,11 @@
color: var(--typography-color-muted);
}

&:invalid,
&[aria-invalid="true"] {
--form-border: var(--form-input-invalid-border);
}

&[maxlength],
&[size] {
width: auto;
Expand Down Expand Up @@ -96,6 +101,15 @@
width: 100%;
height: 100%;
}

&:invalid,
&[aria-invalid="true"] {
background-color: var(--form-checkbox-invalid-background);

&:checked:before {
background-color: var(--form-checkbox-invalid-text);
}
}
}

&[type="radio"] {
Expand All @@ -113,6 +127,15 @@
width: 12px;
height: 12px;
}

&:invalid,
&[aria-invalid="true"] {
background-color: var(--form-radio-invalid-background);

&:checked:before {
background-color: var(--form-radio-invalid-text);
}
}
}

&[type="color"] {
Expand Down
12 changes: 12 additions & 0 deletions src/components/form/input/input.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ export const InputComponent: Story = {
decorators: [FORM_TEST_DECORATOR],
};

export const InvalidInputComponent: Story = {
args: {
name: "input",
placeholder: "e.g. John Doe",
type: "text",
invalid: true,
},
argTypes: FORM_TEST_ARG_TYPES,
decorators: [FORM_TEST_DECORATOR],
play: () => undefined,
};

export const InputTypeCheckbox: Story = {
args: {
name: "input",
Expand Down
8 changes: 8 additions & 0 deletions src/components/form/input/input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ export type InputProps = Omit<

/** Gets called when the value is changed */
onChange?: React.ChangeEventHandler<HTMLInputElement>;

/**
* Invalid input fields get additional markup/styling and aria tags to indicate the
* invalid state.
*/
invalid?: boolean;
};

/**
Expand All @@ -50,6 +56,7 @@ export const Input: React.FC<InputProps> = ({
value,
variant = "normal",
onChange,
invalid,
...props
}) => {
const inputRef = React.useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -112,6 +119,7 @@ export const Input: React.FC<InputProps> = ({
type={inputType}
onChange={_onChange}
aria-label={label || undefined}
aria-invalid={invalid}
{...valueProps}
{...props}
/>
Expand Down
10 changes: 10 additions & 0 deletions src/components/form/radio/radio.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,13 @@ export const RadioComponent: Story = {
await expect(data.input).toBe(args.value || "on");
},
};

export const InvalidRadioComponent: Story = {
args: {
children: "Click me!",
name: "input",
value: "",
invalid: true,
},
argTypes: FORM_TEST_ARG_TYPES,
};
15 changes: 15 additions & 0 deletions src/components/form/radio/radiogroup.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,18 @@ export const RadioGroupComponent: Story = {
await expect(data.school_year).toEqual("Senior");
},
};

export const InvalidRadioGroupComponent: Story = {
args: {
name: "school_year",
options: [
{ label: "Freshman", selected: true },
{ label: "Sophomore" },
{ label: "Junior" },
{ label: "Senior" },
{ label: "Graduate" },
],
invalid: true,
},
argTypes: FORM_TEST_ARG_TYPES,
};
Loading
Loading