diff --git a/packages/odyssey-react-mui/src/Autocomplete.tsx b/packages/odyssey-react-mui/src/Autocomplete.tsx index 7f42773c69..97459dd2c3 100644 --- a/packages/odyssey-react-mui/src/Autocomplete.tsx +++ b/packages/odyssey-react-mui/src/Autocomplete.tsx @@ -194,6 +194,7 @@ export type AutocompleteProps< FieldComponentProps, | "errorMessage" | "errorMessageList" + | "hasVisibleLabel" | "hint" | "HintLinkComponent" | "id" @@ -218,6 +219,7 @@ const Autocomplete = < errorMessage, errorMessageList, hasMultipleChoices, + hasVisibleLabel, id: idOverride, inputValue, isCustomValueAllowed, @@ -299,7 +301,7 @@ const Autocomplete = < errorMessage={errorMessage} errorMessageList={errorMessageList} fieldType="single" - hasVisibleLabel + hasVisibleLabel={hasVisibleLabel} //@ts-expect-error htmlFor does not exist ont he InputLabelProps for autocomplete id={InputLabelProps.htmlFor} isFullWidth={isFullWidth} @@ -334,6 +336,7 @@ const Autocomplete = < ariaDescribedBy, errorMessage, errorMessageList, + hasVisibleLabel, hint, HintLinkComponent, isFullWidth, diff --git a/packages/odyssey-react-mui/src/Field.tsx b/packages/odyssey-react-mui/src/Field.tsx index 293ad560d5..85c7af47a1 100644 --- a/packages/odyssey-react-mui/src/Field.tsx +++ b/packages/odyssey-react-mui/src/Field.tsx @@ -45,10 +45,6 @@ export type FieldProps = { * The field type determines how ARIA components are setup. It's important to use this to denote if you expect only one component (like a text field) or multiple (like a radio group). */ fieldType: (typeof fieldTypeValues)[number]; - /** - * If `true`, the Field label will be shown - */ - hasVisibleLabel: boolean; /** * Important for narrowing down the `fieldset` role to "radiogroup". */ @@ -76,14 +72,14 @@ export type FieldProps = { labelElementId, isReadOnly, }: RenderFieldComponentProps) => ReactElement; -}; +} & Pick; const Field = ({ ariaDescribedBy, errorMessage, errorMessageList, fieldType, - hasVisibleLabel, + hasVisibleLabel = true, hint, HintLinkComponent, id: idOverride, @@ -99,6 +95,7 @@ const Field = ({ FieldComponentProps, | "errorMessage" | "errorMessageList" + | "hasVisibleLabel" | "hint" | "HintLinkComponent" | "id" @@ -160,7 +157,7 @@ const Field = ({ /> )} - {hint && ( + {hint && hasVisibleLabel && ( )} diff --git a/packages/odyssey-react-mui/src/FieldComponentProps.ts b/packages/odyssey-react-mui/src/FieldComponentProps.ts index 417def01b8..8a25f789dd 100644 --- a/packages/odyssey-react-mui/src/FieldComponentProps.ts +++ b/packages/odyssey-react-mui/src/FieldComponentProps.ts @@ -24,13 +24,11 @@ export type FieldComponentProps = { */ errorMessageList?: string[]; /** - * The helper text content. + * If `false` no visible label is shown. + * + * NOTE: the `label` prop is still required for accessibility purposes */ - hint?: string; - /** - * A `Link` component to provide greater context that is rendered at the end of the `hint` text - */ - HintLinkComponent?: ReactElement; + hasVisibleLabel?: boolean; /** * The id of the `input` element. */ @@ -55,7 +53,30 @@ export type FieldComponentProps = { * The name of the `input` element. Defaults to the `id` if not set. */ name?: string; -}; +} & ( + | { + /** + * If `hasVisibleLabel` is `false` it will also hide any `hint` text and `HintLinkComponent` that is passed in + */ + hasVisibleLabel?: false; + hint: never; + HintLinkComponent: never; + } + | { + /** + * defaults to `true` if `false` along with hiding the label it will also hide any `hint` text and `HintLinkComponent` that is passed in + */ + hasVisibleLabel?: true; + /** + * The helper text content. + */ + hint?: string; + /** + * A `Link` component to provide greater context that is rendered at the end of the `hint` text + */ + HintLinkComponent?: ReactElement; + } +); export type FieldComponentRenderProps = { ariaDescribedBy: string; @@ -64,3 +85,15 @@ export type FieldComponentRenderProps = { id: string; labelElementId: string; }; + +export type ConditionalLabelProps = + | { + hasVisibleLabel: false; + hint?: never; + placeholder: string; + } + | { + hasVisibleLabel?: true; + hint?: string; + placeholder?: string; + }; diff --git a/packages/odyssey-react-mui/src/NativeSelect.tsx b/packages/odyssey-react-mui/src/NativeSelect.tsx index 9d645ef3e6..41c273a143 100644 --- a/packages/odyssey-react-mui/src/NativeSelect.tsx +++ b/packages/odyssey-react-mui/src/NativeSelect.tsx @@ -97,6 +97,7 @@ export type NativeSelectProps< FieldComponentProps, | "errorMessage" | "errorMessageList" + | "hasVisibleLabel" | "hint" | "HintLinkComponent" | "id" @@ -123,6 +124,7 @@ const NativeSelect = forwardRef( errorMessage, errorMessageList, hasMultipleChoices: hasMultipleChoicesProp, + hasVisibleLabel = true, hint, HintLinkComponent, id: idOverride, @@ -233,7 +235,7 @@ const NativeSelect = forwardRef( errorMessage={errorMessage} errorMessageList={errorMessageList} fieldType="single" - hasVisibleLabel + hasVisibleLabel={hasVisibleLabel} hint={hint} HintLinkComponent={HintLinkComponent} id={idOverride} diff --git a/packages/odyssey-react-mui/src/Select.tsx b/packages/odyssey-react-mui/src/Select.tsx index 7e542e33d8..3c0d69c6a0 100644 --- a/packages/odyssey-react-mui/src/Select.tsx +++ b/packages/odyssey-react-mui/src/Select.tsx @@ -163,6 +163,7 @@ export type SelectProps< FieldComponentProps, | "errorMessage" | "errorMessageList" + | "hasVisibleLabel" | "hint" | "HintLinkComponent" | "id" @@ -204,6 +205,7 @@ const Select = < errorMessage, errorMessageList, hasMultipleChoices: hasMultipleChoicesProp, + hasVisibleLabel, hint, HintLinkComponent, id: idOverride, @@ -515,7 +517,7 @@ const Select = < errorMessage={errorMessage} errorMessageList={errorMessageList} fieldType="single" - hasVisibleLabel + hasVisibleLabel={hasVisibleLabel} hint={hint} HintLinkComponent={HintLinkComponent} id={idOverride} diff --git a/packages/odyssey-react-mui/src/TextField.tsx b/packages/odyssey-react-mui/src/TextField.tsx index c3ff2f110d..69069a999e 100644 --- a/packages/odyssey-react-mui/src/TextField.tsx +++ b/packages/odyssey-react-mui/src/TextField.tsx @@ -24,6 +24,7 @@ import { import { InputAdornment, InputBase } from "@mui/material"; import { + ConditionalLabelProps, FieldComponentProps, FieldComponentRenderProps, } from "./FieldComponentProps"; @@ -154,7 +155,8 @@ export type TextFieldProps = { */ value?: string; } & FieldComponentProps & - Pick; + Pick & + ConditionalLabelProps; type FieldRenderProps = Partial< Pick @@ -171,6 +173,7 @@ const TextField = forwardRef( endAdornment, errorMessage, errorMessageList, + hasVisibleLabel = true, hint, HintLinkComponent, id: idOverride, @@ -305,7 +308,7 @@ const TextField = forwardRef( errorMessage={errorMessage} errorMessageList={errorMessageList} fieldType="single" - hasVisibleLabel + hasVisibleLabel={hasVisibleLabel} hint={hint} HintLinkComponent={HintLinkComponent} id={idOverride} diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Autocomplete/Autocomplete.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Autocomplete/Autocomplete.stories.tsx index ccebb23580..70533434e2 100644 --- a/packages/odyssey-storybook/src/components/odyssey-mui/Autocomplete/Autocomplete.stories.tsx +++ b/packages/odyssey-storybook/src/components/odyssey-mui/Autocomplete/Autocomplete.stories.tsx @@ -64,6 +64,7 @@ const storybookMeta: Meta = { }, }, }, + hasVisibleLabel: fieldComponentPropsMetaData.hasVisibleLabel, hint: fieldComponentPropsMetaData.hint, HintLinkComponent: fieldComponentPropsMetaData.HintLinkComponent, id: fieldComponentPropsMetaData.id, @@ -448,6 +449,20 @@ const jupiterGalileanMoons: MoonMeta[] = [ }, ]; +export const NoVisibleLabel: StoryObj = { + parameters: { + docs: { + description: { + story: + "TextFields with `hasVisibleLabel` set to false will not render a visible label. Although, the `label` prop is still required for accessibility purposes", + }, + }, + }, + args: { + hasVisibleLabel: false, + }, +}; + export const ControlledMultipleAutocomplete: StoryObj = { parameters: { diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/NativeSelect/NativeSelect.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/NativeSelect/NativeSelect.stories.tsx index 30b31d77fc..f86c46a36a 100644 --- a/packages/odyssey-storybook/src/components/odyssey-mui/NativeSelect/NativeSelect.stories.tsx +++ b/packages/odyssey-storybook/src/components/odyssey-mui/NativeSelect/NativeSelect.stories.tsx @@ -45,6 +45,7 @@ const storybookMeta: Meta = { }, errorMessage: fieldComponentPropsMetaData.errorMessage, errorMessageList: fieldComponentPropsMetaData.errorMessageList, + hasVisibleLabel: fieldComponentPropsMetaData.hasVisibleLabel, hint: fieldComponentPropsMetaData.hint, HintLinkComponent: fieldComponentPropsMetaData.HintLinkComponent, id: fieldComponentPropsMetaData.id, @@ -203,6 +204,13 @@ export const DefaultDisabled: StoryObj = { }, }; +export const NoVisibleLabel: StoryObj = { + ...Template, + args: { + hasVisibleLabel: false, + }, +}; + export const DefaultError: StoryObj = { ...Template, args: { diff --git a/packages/odyssey-storybook/src/components/odyssey-mui/Select/Select.stories.tsx b/packages/odyssey-storybook/src/components/odyssey-mui/Select/Select.stories.tsx index 6c1963e82a..0e5100abb2 100644 --- a/packages/odyssey-storybook/src/components/odyssey-mui/Select/Select.stories.tsx +++ b/packages/odyssey-storybook/src/components/odyssey-mui/Select/Select.stories.tsx @@ -137,6 +137,7 @@ const storybookMeta: Meta> = { }, }, }, + hasVisibleLabel: fieldComponentPropsMetaData.hasVisibleLabel, hint: fieldComponentPropsMetaData.hint, HintLinkComponent: fieldComponentPropsMetaData.HintLinkComponent, id: fieldComponentPropsMetaData.id, @@ -476,3 +477,17 @@ export const ControlledPreselectedMultipleSelect: StoryObj = { return