diff --git a/README.md b/README.md index 06d2bf399d..d0f64b0eb6 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,7 @@ These scripts can all be run from the root level of the repo: - **Before** running `start` run the `build` command - `yarn storybook` - Starts storybook for easier local development for the core package - - `yarn storybook:healthcare` starts storybook for healthcare stories & styles - - `yarn storybook:medicare` starts storybook for medicare stories & styles + - `yarn storybook:react` starts Storybook with React instead of Preact - `yarn test` - Alias of `yarn test:unit` - `yarn test:unit` diff --git a/examples/create-react-app-typescript/package.json b/examples/create-react-app-typescript/package.json index a1caaa2051..0a4d7d0cef 100644 --- a/examples/create-react-app-typescript/package.json +++ b/examples/create-react-app-typescript/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { - "@cmsgov/design-system": "^8.0.0", + "@cmsgov/design-system": "^9.0.0-beta.1", "@types/jest": "^27.5.2", "@types/node": "^16.18.0", "@types/react": "^18.0.22", diff --git a/examples/create-react-app-typescript/src/components/App.tsx b/examples/create-react-app-typescript/src/components/App.tsx index b206c28468..6d6f1c44c0 100644 --- a/examples/create-react-app-typescript/src/components/App.tsx +++ b/examples/create-react-app-typescript/src/components/App.tsx @@ -6,7 +6,8 @@ import AutocompleteExample from './Examples/AutocompleteExample'; import BadgeExample from './Examples/BadgeExample'; import ButtonExample from './Examples/ButtonExample'; import ChoiceListExample from './Examples/ChoiceListExample'; -import DateFieldExample from './Examples/DateFieldExample'; +import SingleInputDateFieldExample from './Examples/SingleInputDateFieldExample'; +import MultiInputDateFieldExample from './Examples/MultiInputDateFieldExample'; import DropdownExample from './Examples/DropdownExample'; import FilterChipExample from './Examples/FilterChipExample'; import LabelExample from './Examples/LabelExample'; @@ -28,7 +29,7 @@ function App() { return (
-

+

Hello, world!

@@ -46,7 +47,8 @@ function App() { - + + diff --git a/examples/create-react-app-typescript/src/components/Examples/DateFieldExample.tsx b/examples/create-react-app-typescript/src/components/Examples/MultiInputDateFieldExample.tsx similarity index 56% rename from examples/create-react-app-typescript/src/components/Examples/DateFieldExample.tsx rename to examples/create-react-app-typescript/src/components/Examples/MultiInputDateFieldExample.tsx index 9570af74a0..328f9685e5 100644 --- a/examples/create-react-app-typescript/src/components/Examples/DateFieldExample.tsx +++ b/examples/create-react-app-typescript/src/components/Examples/MultiInputDateFieldExample.tsx @@ -1,11 +1,11 @@ -import { DateField } from '@cmsgov/design-system'; +import { MultiInputDateField } from '@cmsgov/design-system'; import React from 'react'; -function DateFieldExample() { +function MultiInputDateFieldExample() { return (
-

DateField Example

- MultiInputDateField Example + +

SingleInputDateField Example

+ +
+ ); +} + +export default SingleInputDateFieldExample; diff --git a/packages/design-system-tokens/src/themes/cmsgov.ts b/packages/design-system-tokens/src/themes/cmsgov.ts index e26d47fbfe..1206dd2633 100644 --- a/packages/design-system-tokens/src/themes/cmsgov.ts +++ b/packages/design-system-tokens/src/themes/cmsgov.ts @@ -97,7 +97,7 @@ export const themeColors: ColorTokens = { 'warn-darker': color['dandelion-700'], 'warn-darkest': color['dandelion-800'], // - 'visited': color['windsor-500'], + 'visited': color['orchid-800'], }; const font: FontTokens = { diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 2d740ce736..82724e2ace 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -59,7 +59,6 @@ "@types/react-dom": "^17.0.10", "@types/react-transition-group": "^4.4.5", "classnames": "^2.2.5", - "core-js": "^3.6.5", "date-fns": "^2.28.0", "ev-emitter": "^1.1.1", "focus-trap-react": "^10.0.0", diff --git a/packages/design-system/src/components/Autocomplete/Autocomplete.stories.tsx b/packages/design-system/src/components/Autocomplete/Autocomplete.stories.tsx index a7db761322..f8ed1f0a7f 100644 --- a/packages/design-system/src/components/Autocomplete/Autocomplete.stories.tsx +++ b/packages/design-system/src/components/Autocomplete/Autocomplete.stories.tsx @@ -56,7 +56,7 @@ function makeItem(name: string, children?: React.ReactNode) { export const Default: Story = { render: Template, args: { - textFieldLabel: 'Enter and select a drug to see its cost under each plan', + textFieldLabel: 'Enter and select a drug to see its cost under each plan.', textFieldHint: 'Type a letter to see results, then use ARROW keys to change options, ENTER key to make a selection, ESC to dismiss.', items: [ @@ -98,7 +98,7 @@ export const Default: Story = { export const LabeledList: Story = { render: Template, args: { - textFieldLabel: 'Search for and select your county', + textFieldLabel: 'Search for and select your county.', textFieldHint: 'Type "C" then use ARROW keys to change options, ENTER key to make a selection, ESC to dismiss.', label: 'Select from the options below:', @@ -118,7 +118,7 @@ export const LabeledList: Story = { export const CustomMarkup: Story = { render: Template, args: { - textFieldLabel: 'Select a snack that starts with "C"', + textFieldLabel: 'Select a snack that starts with "C".', textFieldHint: 'Type "C" to start seeing a list of snacks. Clicking the last item should not change the input value to "Search all snacks"', label: 'Select from the options below:', @@ -168,7 +168,7 @@ export const LoadingMessage: Story = { clearSearchButton: false, loading: true, items: [], - textFieldLabel: 'This will only show a loading message', + textFieldLabel: 'This will only show a loading message.', textFieldHint: 'List should return string Loading to simulate async data call.', } as any, }; @@ -178,7 +178,7 @@ export const NoResults: Story = { args: { items: [], clearSearchButton: false, - textFieldLabel: 'This will show a "no results" message', + textFieldLabel: 'This will show a "no results" message.', textFieldHint: "Start typing, but you'll only get a loading message.", } as any, }; diff --git a/packages/design-system/src/components/ChoiceList/ChoiceList.stories.tsx b/packages/design-system/src/components/ChoiceList/ChoiceList.stories.tsx index 9c093412eb..9ee5a9be93 100644 --- a/packages/design-system/src/components/ChoiceList/ChoiceList.stories.tsx +++ b/packages/design-system/src/components/ChoiceList/ChoiceList.stories.tsx @@ -31,24 +31,24 @@ type Story = StoryObj; export const DefaultCheckbox: Story = { args: { - label: 'Checkbox example', - hint: 'Helpful hint text', - name: 'checkbox_choices', + label: 'Check some boxes.', + hint: 'This is some helpful hint text.', + name: 'checkbox-choices', type: 'checkbox', }, }; export const DefaultRadio: Story = { args: { - label: 'Radio example', - name: 'radio_choices', + label: 'Choose an option.', + name: 'radio-choices', type: 'radio', }, }; export const SmallOption: Story = { args: { - label: 'Small size example', + label: 'Choose a small option.', name: 'size-variants', type: 'radio', size: 'small', @@ -57,19 +57,18 @@ export const SmallOption: Story = { export const WithError: Story = { args: { - errorMessage: 'Example error message', - label: 'Small size example', - name: 'size-variants', + errorMessage: 'This is an example error message.', + label: 'Choose an option.', + name: 'radio-choices', type: 'radio', - size: 'small', }, }; export const InverseOption: Story = { args: { - label: 'Inverse example', - hint: 'Helpful hint text', - name: 'inverse_choices_field', + label: 'Choose an option.', + hint: 'This component is on an inversed background.', + name: 'inverse-choices', type: 'checkbox', inversed: true, }, @@ -82,8 +81,9 @@ export const InverseOption: Story = { export const DisabledCheckbox: Story = { args: { - label: 'Disabled checkbox example', - name: 'checkbox_choices', + label: 'Check some boxes.', + hint: 'These checkboxes are disabled.', + name: 'disabled-checkbox-choices', type: 'checkbox', choices: [ { label: 'Disabled choice A', value: 'A', disabled: true }, @@ -94,8 +94,9 @@ export const DisabledCheckbox: Story = { export const DisabledRadio: Story = { args: { - label: 'Disabled radio example', - name: 'radio_choices', + label: 'Choose an option.', + hint: 'These radio buttons are disabled.', + name: 'disabled-radio-choices', type: 'radio', choices: [ { label: 'Disabled choice A', value: 'A', disabled: true }, @@ -108,7 +109,12 @@ export const ChoiceChildren: Story = { args: { name: 'radio_choices', type: 'radio', - label: 'Example choices with checked children', + label: 'Choose an option.', + hint: ( + <> + This example shows choices with checked children. + + ), choices: [ { label: 'Choice 1', diff --git a/packages/design-system/src/components/ChoiceList/__snapshots__/Choice.test.tsx.snap b/packages/design-system/src/components/ChoiceList/__snapshots__/Choice.test.tsx.snap index 0e73f5a345..e6cfac1e03 100644 --- a/packages/design-system/src/components/ChoiceList/__snapshots__/Choice.test.tsx.snap +++ b/packages/design-system/src/components/ChoiceList/__snapshots__/Choice.test.tsx.snap @@ -49,7 +49,7 @@ exports[`Choice applies errorMessage to label 1`] = ` > George Washington - Hey! You can't do that! - +

@@ -97,12 +97,12 @@ exports[`Choice has a hint and requirementLabel 1`] = ` > George Washington -
Optional. Hello world -
+

diff --git a/packages/design-system/src/components/ChoiceList/__snapshots__/ChoiceList.test.tsx.snap b/packages/design-system/src/components/ChoiceList/__snapshots__/ChoiceList.test.tsx.snap index d5d755c772..a2bb32c172 100644 --- a/packages/design-system/src/components/ChoiceList/__snapshots__/ChoiceList.test.tsx.snap +++ b/packages/design-system/src/components/ChoiceList/__snapshots__/ChoiceList.test.tsx.snap @@ -13,13 +13,13 @@ exports[`ChoiceList Radio buttons and Checkboxes is a radio button group 1`] = ` > Foo -
Psst! I know the answer -
- +

Hey, you have to pick an answer - +

, + keyof BaseCloseButtonProps +> & + BaseCloseButtonProps; + +/** + * + */ +export const CloseButton = ({ className, id: idProp, ...buttonAttributes }: CloseButtonProps) => { + const id = useId('close-button--', idProp); + return ( + + ); +}; + +export default CloseButton; diff --git a/packages/design-system/src/components/CloseButton/index.ts b/packages/design-system/src/components/CloseButton/index.ts new file mode 100644 index 0000000000..8f0f3a0232 --- /dev/null +++ b/packages/design-system/src/components/CloseButton/index.ts @@ -0,0 +1 @@ +export * from './CloseButton'; diff --git a/packages/design-system/src/components/DateField/MultiInputDateField.stories.tsx b/packages/design-system/src/components/DateField/MultiInputDateField.stories.tsx index a20da5cb70..6403961ac9 100644 --- a/packages/design-system/src/components/DateField/MultiInputDateField.stories.tsx +++ b/packages/design-system/src/components/DateField/MultiInputDateField.stories.tsx @@ -11,34 +11,15 @@ const meta: Meta = { hint: { control: 'text' }, requirementLabel: { control: 'text' }, }, + args: { + label: 'Enter your date of birth.', + }, }; export default meta; type Story = StoryObj; -const ControlledTemplate: Story = { - render: function Component(args) { - const [dateState, setDateState] = useState({ month: '10', day: '30', year: '1980' }); - - return ( - - Controlled example using dateFormatter - - } - hint="Try to enter a date with invalid number of digits" - monthValue={dateState.month} - dayValue={dateState.day} - yearValue={dateState.year} - onChange={(e, dateObject) => setDateState(dateObject)} - /> - ); - }, -}; - -export const MultiInputDateFieldDefault: Story = { +export const Default: Story = { args: { monthDefaultValue: '10', dayDefaultValue: '31', @@ -46,7 +27,7 @@ export const MultiInputDateFieldDefault: Story = { }, }; -export const MultiInputDateFieldWithError: Story = { +export const WithError: Story = { args: { errorMessage: 'Please enter a year in the past', monthDefaultValue: '10', @@ -56,11 +37,26 @@ export const MultiInputDateFieldWithError: Story = { }, }; -export const ControlledMultiInputDateField: Story = { - ...ControlledTemplate, +export const Controlled: Story = { + args: { + hint: 'In this example, the month, day, and year values are controlled by the parent component.', + }, + render: function Component(args) { + const [dateState, setDateState] = useState({ month: '10', day: '30', year: '1980' }); + + return ( + setDateState(dateObject)} + /> + ); + }, }; -export const InvertedMultiInputDateField: Story = { +export const Inverted: Story = { args: { errorMessage: 'Please enter a year in the past', monthDefaultValue: '10', diff --git a/packages/design-system/src/components/DateField/SingleInputDateField.stories.tsx b/packages/design-system/src/components/DateField/SingleInputDateField.stories.tsx index 94b4296fc8..e60d23103c 100644 --- a/packages/design-system/src/components/DateField/SingleInputDateField.stories.tsx +++ b/packages/design-system/src/components/DateField/SingleInputDateField.stories.tsx @@ -7,8 +7,8 @@ const meta: Meta = { title: 'Components/SingleInputDateField', component: SingleInputDateField, args: { - hint: 'Please enter your birthday', - label: 'Birthday', + hint: 'If you were born on a leap day, entering the date will either crash our servers or open a portal to an alternate dimension.', + label: 'Enter your date of birth.', name: 'single-input-date-field', }, argTypes: { @@ -48,22 +48,22 @@ export const WithPicker: Story = { ...Default, args: { label: 'What day did you move?', - hint: 'This date should be within the past 60 days in order to qualify', - fromYear: new Date().getFullYear(), + hint: 'This date should be within the past 60 days in order to qualify.', + fromYear: 2023, // TODO: Due to some unknown issue with this story that causes us to lose args // defined with query parameters, we can't supply a specific date in the // browser interaction tests in order to get consistent screenshots. We want // to set this to an arbitrary date in the past so it always takes a screenshot // of the same calendar view every time. If we can solve the root problem, we // can move this setting of the toDate to the `.test.interaction.ts` file. - toDate: new Date(1676498194272), + toDate: new Date('2023-02-15T21:56:34.272Z'), }, }; export const WithError = { ...Default, args: { - errorMessage: 'Example error message', + errorMessage: 'This is an example error message.', ...WithPicker.args, }, }; diff --git a/packages/design-system/src/components/Dialog/Dialog.stories.tsx b/packages/design-system/src/components/Dialog/Dialog.stories.tsx index 536b52242a..dd0658b31e 100644 --- a/packages/design-system/src/components/Dialog/Dialog.stories.tsx +++ b/packages/design-system/src/components/Dialog/Dialog.stories.tsx @@ -9,7 +9,6 @@ const meta: Meta = { component: Dialog as any, args: { alert: false, - closeButtonVariation: 'ghost', children: (
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed accumsan diam vitae metus @@ -75,7 +74,10 @@ export const PreventScrollExample: Story = { render: function Component(args) { const [dialogOpen, updateOpen] = useState(false); const showModal = () => updateOpen(true); - const hideModal = () => updateOpen(false); + const hideModal = (...params) => { + action('onExit')(...params); + updateOpen(false); + }; return (
diff --git a/packages/design-system/src/components/Dialog/Dialog.test.jsx b/packages/design-system/src/components/Dialog/Dialog.test.jsx index aac2602311..e97176dd64 100644 --- a/packages/design-system/src/components/Dialog/Dialog.test.jsx +++ b/packages/design-system/src/components/Dialog/Dialog.test.jsx @@ -35,14 +35,6 @@ describe('Dialog', function () { expect(screen.getByRole('document')).toMatchSnapshot(); }); - it('close button text and variation can be changed', () => { - renderDialog({ - closeButtonVariation: 'ghost', - closeButtonText: "No thank you. I don't like saving money", - }); - expect(screen.getByRole('document')).toMatchSnapshot(); - }); - it('calls onExit when close button is clicked', () => { const onExit = jest.fn(); renderDialog({ onExit }); diff --git a/packages/design-system/src/components/Dialog/Dialog.tsx b/packages/design-system/src/components/Dialog/Dialog.tsx index c2f805a30e..8a101156c8 100644 --- a/packages/design-system/src/components/Dialog/Dialog.tsx +++ b/packages/design-system/src/components/Dialog/Dialog.tsx @@ -1,16 +1,13 @@ import React from 'react'; -import Button, { ButtonVariation } from '../Button/Button'; +import CloseButton from '../CloseButton/CloseButton'; import NativeDialog from '../NativeDialog/NativeDialog'; import classNames from 'classnames'; -import uniqueId from 'lodash/uniqueId'; import useDialogAnalytics from './useDialogAnalytics'; -import { CloseIcon } from '../Icons'; +import useId from '../utilities/useId'; import { useEffect, useLayoutEffect, useRef, DialogHTMLAttributes } from 'react'; import { t } from '../i18n'; import { AnalyticsOverrideProps } from '../analytics'; -import useId from '../utilities/useId'; -export type DialogCloseButtonSize = 'small' | 'big'; export type DialogSize = 'narrow' | 'wide' | 'full'; export interface BaseDialogProps extends AnalyticsOverrideProps { @@ -42,23 +39,6 @@ export interface BaseDialogProps extends AnalyticsOverrideProps { * Additional classes to be added to the root dialog element. */ className?: string; - /** - * Size of the close button. See [Button component](https://design.cms.gov/storybook/?path=/docs/components-button--docs) - */ - closeButtonSize?: DialogCloseButtonSize; - /** - * For internationalization purposes, the text for the "Close" button must be - * passed in as a prop. - */ - closeButtonText?: React.ReactNode; - /** - * Variation string to be applied to close button component. See [Button component](https://design.cms.gov/storybook/?path=/docs/components-button--docs) - */ - closeButtonVariation?: ButtonVariation; - /** - * The icon to display as part of the close button - */ - closeIconComponent?: React.ReactElement | any | ((...args: any[]) => any); /** * Additional classes to be added to the header, which wraps the heading and * close button. @@ -108,10 +88,6 @@ export const Dialog = (props: DialogProps) => { ariaCloseLabel, children, className, - closeButtonSize, - closeButtonText, - closeButtonVariation, - closeIconComponent, headerClassName, heading, id, @@ -131,8 +107,6 @@ export const Dialog = (props: DialogProps) => { const containerRef = useRef(); - const CloseIconComponent = closeIconComponent; - useEffect(() => { if (onEnter) onEnter(); }, []); @@ -177,20 +151,16 @@ export const Dialog = (props: DialogProps) => { >
{heading && ( -

+

{heading}

)} - + />
{children}
@@ -201,9 +171,4 @@ export const Dialog = (props: DialogProps) => { ); }; -Dialog.defaultProps = { - closeButtonVariation: 'ghost', - closeIconComponent: CloseIcon, -}; - export default Dialog; diff --git a/packages/design-system/src/components/Dialog/__snapshots__/Dialog.test.jsx.snap b/packages/design-system/src/components/Dialog/__snapshots__/Dialog.test.jsx.snap index 3fc056b6ce..e2977c5f30 100644 --- a/packages/design-system/src/components/Dialog/__snapshots__/Dialog.test.jsx.snap +++ b/packages/design-system/src/components/Dialog/__snapshots__/Dialog.test.jsx.snap @@ -1,53 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Dialog close button text and variation can be changed 1`] = ` -
-
-

- dialog heading -

- -
-
-
- Foo -
-
-
-`; - exports[`Dialog renders with additional classNames and size 1`] = `

dialog heading

= { title: 'Components/Dropdown', @@ -78,16 +77,16 @@ const htmlOptions = ( export const Default: Story = { args: { options: dropdownOptions, - label: 'Dropdown example', + label: 'Select your tribe name.', }, }; export const WithError: Story = { args: { options: dropdownOptions, - errorMessage: 'Example error message', - hint: 'Helpful hint text', - label: 'Error example', + errorMessage: 'This is an example error message.', + hint: 'This is where you put helpful hint text.', + label: 'Select your tribe name.', }, }; @@ -119,14 +118,16 @@ export const OptionGroups: Story = { ], }, ], - label: 'Option groups example', + label: 'Select an option.', + hint: 'This is an option-group example.', }, }; export const HtmlOptionGroups: Story = { args: { options: undefined, - label: 'Option group example', + label: 'Select an option.', + hint: 'In this example, options and groups are defined as HTML.', children: htmlOptGroups, }, }; @@ -134,7 +135,8 @@ export const HtmlOptionGroups: Story = { export const HtmlOptions: Story = { args: { options: undefined, - label: 'Option group example', + label: 'Select an option.', + hint: 'In this example, options defined as HTML.', children: htmlOptions, }, }; @@ -142,9 +144,9 @@ export const HtmlOptions: Story = { export const InverseOption: Story = { args: { options: dropdownOptions, - errorMessage: 'Example error message', - hint: 'Helpful hint text', - label: 'Inverse example', + errorMessage: 'This is an example error message.', + hint: 'This component is on an inversed background.', + label: 'Select your tribe name.', inversed: true, }, parameters: { @@ -157,7 +159,8 @@ export const InverseOption: Story = { export const Controlled: Story = { args: { options: dropdownOptions, - label: 'Dropdown example', + label: 'Select your tribe name.', + hint: 'In this example, the selected value is controlled by the parent component.', value: '3', }, render: function Component(args) { diff --git a/packages/design-system/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap b/packages/design-system/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap index 56c69a203e..490ebb6b6c 100644 --- a/packages/design-system/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap +++ b/packages/design-system/src/components/Dropdown/__snapshots__/Dropdown.test.tsx.snap @@ -220,7 +220,7 @@ exports[`Dropdown dropdown matches snapshot 1`] = ` `; exports[`Dropdown shows error message 1`] = ` - Error - +

`; diff --git a/packages/design-system/src/components/Hint/Hint.stories.tsx b/packages/design-system/src/components/Hint/Hint.stories.tsx new file mode 100644 index 0000000000..a5b87b43b2 --- /dev/null +++ b/packages/design-system/src/components/Hint/Hint.stories.tsx @@ -0,0 +1,25 @@ +import React from 'react'; +import { Hint } from './Hint'; +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Components/Hint', + component: Hint as any, + args: { + children: + 'If a married couple files a joint return, either spouse may be the primary taxpayer.', + }, + argTypes: { + requirementLabel: { control: 'text' }, + }, + parameters: { + docs: { + underlyingHtmlElements: ['div'], + }, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/packages/design-system/src/components/Hint/Hint.tsx b/packages/design-system/src/components/Hint/Hint.tsx index 2acd66186d..805ec7fa4b 100644 --- a/packages/design-system/src/components/Hint/Hint.tsx +++ b/packages/design-system/src/components/Hint/Hint.tsx @@ -6,6 +6,10 @@ export interface HintProps { * Hint text or HTML */ children?: React.ReactNode; + /** + * Additional classes to be added to the root element. + */ + className?: string; /** * The ID of the hint element. This is required in order to link the element * to a field input via `aria-describedby` @@ -23,8 +27,23 @@ export interface HintProps { requirementLabel?: React.ReactNode; } -export const Hint = ({ children, id, inversed, requirementLabel }: HintProps) => { - const hintClasses = classNames('ds-c-hint', inversed && 'ds-c-hint--inverse'); +/** + * Hints are used in conjunction with a Label to describe individual form fields + * or fieldsets. They are built in to all form fields in the design system, but + * they can also be used on their own to create custom fields. + * + * For information about how and when to use this component, + * [refer to its full documentation page](https://design.cms.gov/components/hint/). + */ +export const Hint = ({ + children, + className, + id, + inversed, + requirementLabel, + ...otherProps +}: HintProps) => { + const hintClasses = classNames('ds-c-hint', inversed && 'ds-c-hint--inverse', className); let hintPadding; if (requirementLabel && children) { @@ -40,10 +59,10 @@ export const Hint = ({ children, id, inversed, requirementLabel }: HintProps) => } return ( -
+

{requirementLabel} {hintPadding} {children} -

+

); }; diff --git a/packages/design-system/src/components/IdleTimeout/IdleTimeout.tsx b/packages/design-system/src/components/IdleTimeout/IdleTimeout.tsx index 91b3c092c3..ba367a62b9 100644 --- a/packages/design-system/src/components/IdleTimeout/IdleTimeout.tsx +++ b/packages/design-system/src/components/IdleTimeout/IdleTimeout.tsx @@ -5,10 +5,6 @@ import IdleTimeoutDialog from './IdleTimeoutDialog'; import { checkPassiveSupport } from './utilities/checkPassive'; export interface IdleTimeoutProps { - /** - * The text for the dialog's 'close' button - */ - closeButtonText?: string; /** * The text for the 'continue session' button in warning dialog. */ @@ -90,7 +86,6 @@ const lastActiveCookieName = 'CMS_DS_IT_LAST_ACTIVE'; * [refer to its full documentation page](https://design.cms.gov/components/idle-timeout/). */ export const IdleTimeout = ({ - closeButtonText = 'Close', continueSessionText = 'Continue session', heading = 'Are you still there?', endSessionButtonText = 'Logout', @@ -235,7 +230,6 @@ export const IdleTimeout = ({ onSessionContinue={handleSessionContinue} onSessionForcedEnd={handleSessionForcedEnd} showSessionEndButton={showSessionEndButton} - closeButtonText={closeButtonText} onClose={handleSessionContinue} /> ) : null; diff --git a/packages/design-system/src/components/IdleTimeout/IdleTimeoutDialog.tsx b/packages/design-system/src/components/IdleTimeout/IdleTimeoutDialog.tsx index 155c1b4992..a9393ba4fd 100644 --- a/packages/design-system/src/components/IdleTimeout/IdleTimeoutDialog.tsx +++ b/packages/design-system/src/components/IdleTimeout/IdleTimeoutDialog.tsx @@ -3,10 +3,6 @@ import { Dialog } from '../Dialog'; import { Button } from '../Button'; export interface IdleTimeoutDialogProps { - /** - * The text for the dialog's 'close' button - */ - closeButtonText?: string; /** * The text for the 'continue session' button in warning dialog. */ @@ -49,7 +45,6 @@ export interface IdleTimeoutDialogProps { } export const IdleTimeoutDialog = ({ - closeButtonText, continueSessionText, heading, endSessionButtonText, @@ -88,7 +83,6 @@ export const IdleTimeoutDialog = ({ heading={heading} actions={renderDialogActions()} onExit={onClose} - closeButtonText={closeButtonText} > {message} diff --git a/packages/design-system/src/components/InlineError/InlineError.stories.tsx b/packages/design-system/src/components/InlineError/InlineError.stories.tsx new file mode 100644 index 0000000000..d5b735108f --- /dev/null +++ b/packages/design-system/src/components/InlineError/InlineError.stories.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import { InlineError } from './InlineError'; +import type { Meta, StoryObj } from '@storybook/react'; + +const meta: Meta = { + title: 'Components/InlineError', + component: InlineError as any, + args: { + children: 'A date of birth cannot be in the future.', + }, + parameters: { + docs: { + underlyingHtmlElements: ['span'], + }, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/packages/design-system/src/components/InlineError/InlineError.tsx b/packages/design-system/src/components/InlineError/InlineError.tsx index 74aa933491..fc6c974443 100644 --- a/packages/design-system/src/components/InlineError/InlineError.tsx +++ b/packages/design-system/src/components/InlineError/InlineError.tsx @@ -5,17 +5,38 @@ import { t } from '../i18n'; import useId from '../utilities/useId'; interface InlineErrorProps { + /** + * Error text or HTML + */ children?: React.ReactNode; + /** + * Additional classes to be added to the root element. + */ className?: string; + /** + * The ID of the error element + */ id?: string; + /** + * Set to `true` to apply the "inverse" theme + */ inversed?: boolean; } +/** + * Inline errors are error messages that are paired directly with form fields. + * They are built in to all form fields in the design system, but they can also + * be used on their own to create custom fields. + * + * For information about how and when to use this component, + * [refer to its full documentation page](https://design.cms.gov/components/inline-error/). + */ export function InlineError({ children, className, id, inversed, + ...otherProps }: InlineErrorProps): React.ReactElement { const classes = classNames( 'ds-c-inline-error', @@ -25,7 +46,8 @@ export function InlineError({ const viewbox = '36 -12 186 186'; return ( - {`${t('inlineError.prefix')}: `} {children} - +

); } diff --git a/packages/design-system/src/components/InlineError/__snapshots__/InlineError.test.tsx.snap b/packages/design-system/src/components/InlineError/__snapshots__/InlineError.test.tsx.snap index 0750347c2f..0805a4bdf8 100644 --- a/packages/design-system/src/components/InlineError/__snapshots__/InlineError.test.tsx.snap +++ b/packages/design-system/src/components/InlineError/__snapshots__/InlineError.test.tsx.snap @@ -1,7 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`InlineError renders inline error 1`] = ` - Error message - +

`; exports[`InlineError renders inverse error 1`] = ` - Error message - +

`; diff --git a/packages/design-system/src/components/Label/Label.stories.tsx b/packages/design-system/src/components/Label/Label.stories.tsx index f195d17e72..1067911b30 100644 --- a/packages/design-system/src/components/Label/Label.stories.tsx +++ b/packages/design-system/src/components/Label/Label.stories.tsx @@ -2,16 +2,25 @@ import React from 'react'; import Label from './Label'; import type { Meta, StoryObj } from '@storybook/react'; +const disabledArg = { + table: { + disable: true, + }, +}; + const meta: Meta = { title: 'Components/Label', component: Label as any, argTypes: { - errorMessage: { control: 'text' }, - hint: { control: 'text' }, - requirementLabel: { control: 'text' }, + errorId: disabledArg, + errorMessage: disabledArg, + hint: disabledArg, + hintId: disabledArg, + requirementLabel: disabledArg, + ref: disabledArg, }, args: { - children: 'Sample Label', + children: 'Enter your date of birth.', }, parameters: { docs: { @@ -23,15 +32,4 @@ export default meta; type Story = StoryObj; -export const LabelDefault: Story = {}; - -export const InverseLabel: Story = { - args: { - inversed: true, - }, - parameters: { - // Must supply `layout: 'fullscreen'` when we use `onDark: true` - onDark: true, - layout: 'fullscreen', - }, -}; +export const Default: Story = {}; diff --git a/packages/design-system/src/components/Label/Label.tsx b/packages/design-system/src/components/Label/Label.tsx index 403cd62716..c143416efb 100644 --- a/packages/design-system/src/components/Label/Label.tsx +++ b/packages/design-system/src/components/Label/Label.tsx @@ -68,8 +68,12 @@ type LabelComponentProps = React.ComponentPropsWithRef<'label'> & LabelProps; /** + * The Label component describes individual form fields (as a `