From d8b31c0466f7739d0073b52ba708d60571fe3ef9 Mon Sep 17 00:00:00 2001 From: Arpit Jain Date: Wed, 17 Jun 2026 15:55:56 +0900 Subject: [PATCH 1/8] Fix slug heading styles and regression coverage Signed-off-by: Arpit Jain --- src/components/Headings/heading.test.tsx | 4 ++-- src/components/Headings/heading.tsx | 1 + src/components/Headings/headings.stories.tsx | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/components/Headings/heading.test.tsx b/src/components/Headings/heading.test.tsx index 603c31520f..30e0cb8d5a 100644 --- a/src/components/Headings/heading.test.tsx +++ b/src/components/Headings/heading.test.tsx @@ -89,10 +89,10 @@ describe('', () => { expect(wrapper).toBeInTheDocument(); expect(wrapper.tagName.toLowerCase()).toBe('header'); - expect(wrapper.classList.contains('m-slug-header')); + expect(wrapper.classList.contains('m-slug-header')).toBeTruthy(); const content = screen.getByText(text); expect(content.tagName.toLowerCase()).toBe('h2'); - expect(content.classList.contains('a-heading')); + expect(content.classList.contains('m-slug-header__heading')).toBeTruthy(); }); }); diff --git a/src/components/Headings/heading.tsx b/src/components/Headings/heading.tsx index 259f6fef55..3ce4274907 100644 --- a/src/components/Headings/heading.tsx +++ b/src/components/Headings/heading.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-typography/slug-header.scss'; import classnames from 'classnames'; import { JSX } from 'react'; import type { HTMLProps } from 'react'; diff --git a/src/components/Headings/headings.stories.tsx b/src/components/Headings/headings.stories.tsx index 1a54e83e33..912a51abe6 100644 --- a/src/components/Headings/headings.stories.tsx +++ b/src/components/Headings/headings.stories.tsx @@ -97,4 +97,18 @@ export const Slug: Story = { type: 'slug', children: 'Slug', }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + const slugHeading = canvas.getByRole('heading', { + level: 2, + name: /slug/i, + }); + + await expect(slugHeading.classList.contains('m-slug-header__heading')).toBe( + true, + ); + await expect( + slugHeading.closest('header')?.classList.contains('m-slug-header'), + ).toBe(true); + }, }; From 3d039cd78827c84c907ca1f7fa1f5d56bbee212f Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Thu, 25 Jun 2026 13:57:13 -0700 Subject: [PATCH 2/8] button link fix --- src/components/Buttons/button.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/Buttons/button.tsx b/src/components/Buttons/button.tsx index 4fd4739b6b..1e4cd9ad92 100644 --- a/src/components/Buttons/button.tsx +++ b/src/components/Buttons/button.tsx @@ -1,3 +1,5 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link.scss'; import { forwardRef, JSX, From 004feb0052343ec2cf3c1b09801083b153108fe1 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:53:01 -0700 Subject: [PATCH 3/8] update readme --- README.md | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 28cc4e4e50..edcf88bf75 100644 --- a/README.md +++ b/README.md @@ -12,16 +12,28 @@ Current components: https://cfpb.github.io/design-system-react The `@cfpb/design-system-react` library is released as an [NPM package](https://www.npmjs.com/package/@cfpb/design-system-react). -To install the package and its peer dependencies: +Install the library and its peer dependencies: ``` -yarn add @cfpb/design-system-react @cfpb/cfpb-design-system lit react react-dom react-router +yarn add @cfpb/design-system-react @cfpb/cfpb-design-system lit react react-dom ``` -`lit` is required because `@cfpb/cfpb-design-system` web components (for example `` in `Banner`) are built with [Lit](https://lit.dev/). +Add `react-router` if you use `Link` with `isRouterLink`: + +``` +yarn add react-router +``` + +| Peer | When you need it | +| --- | --- | +| `@cfpb/cfpb-design-system` | Always install it. Required for DS web components and for importing DS styles directly (see [Styles](#styles)). | +| `lit` | Components that render DS web components (for example `Banner` / ``). | +| `react-router` | `Link` with `isRouterLink` only. | ## Usage +Import components from the package: + ```ts import { Alert, Button } from '@cfpb/design-system-react'; import type { ReactElement } from 'react'; @@ -43,6 +55,129 @@ export default function SomePage(): ReactElement { } ``` +**You must also load styles** — see [Styles](#styles). Component imports alone do not apply CFPB styling. + +## Styles + +`@cfpb/design-system-react` ships precompiled CSS at `@cfpb/design-system-react/index.css`. Styles from `@cfpb/cfpb-design-system` are folded into that file when each React component imports the matching DS stylesheet during the library build. + +You do **not** need Sass in your app for the default setup. Pick an approach based on how many components you use and whether you already compile SCSS. + +### Option 1: Library CSS only (recommended default) + +Import once at your app entry (for example `main.tsx`): + +```ts +import '@cfpb/design-system-react/index.css'; +``` + +| Pros | Cons | +| --- | --- | +| One import; no Sass toolchain required | Bundle includes CSS for components the library bundles today — not necessarily every DS module yet | +| Matches how the React package is meant to be consumed | If a component’s DS styles are not yet in the library build, that component may look unstyled until the library adds the import | +| Includes Source Sans 3 (embedded in the built CSS) | | + +Use this when you want the simplest Vite/CRA-style setup and are mostly using `@cfpb/design-system-react` components. + +### Option 2: Full Design System CSS (JavaScript import) + +Install `@cfpb/cfpb-design-system`, then in your app entry: + +```ts +import '@cfpb/cfpb-design-system/dist/index.css'; +// Optionally also import the React library CSS if you need its component-specific overrides: +// import '@cfpb/design-system-react/index.css'; +``` + +| Pros | Cons | +| --- | --- | +| All DS component styles (buttons, forms, tables, alerts, layout, …) | ~90KB+ of CSS even if you only use a few components | +| Works even when the React library has not yet bundled a component’s SCSS | Duplicates rules if you **also** import `@cfpb/design-system-react/index.css` — prefer one or the other, or drop the React CSS if DS CSS alone is enough | +| No Sass required | Keep `@cfpb/cfpb-design-system` on a compatible version with your React library peer range | + +Use this when you mix React components with plain HTML/DS class names, or when you hit a component that is not fully styled via Option 1 yet. + +### Option 3: Full Design System via Sass (cf.gov-style apps) + +If your app already compiles SCSS, you can load the entire DS from source: + +```scss +@use '@cfpb/cfpb-design-system/src/index' as *; +``` + +That resolves to the package’s `src/index.scss`, which forwards **base**, **abstracts**, **components**, and **utilities** — the same coverage as `dist/index.css`, but compiled into your app’s stylesheet so you can use DS variables and mixins (for example `$bp-sm-min`, `@include respond-to-min`). + +| Pros | Cons | +| --- | --- | +| Full DS styling + Sass API for your own SCSS | Requires a Sass build step | +| Same pattern used on many CFPB properties | Easy to overlap with `@cfpb/design-system-react/index.css` — usually pick DS **or** React library CSS, not both | +| Versioned with your lockfile, not a second prebuilt CSS file | Slightly more setup (load paths / bundler config) | + +**Note:** `@use '@cfpb/cfpb-design-system/src/abstracts'` and `@use '…/src/base'` only give you tokens and global typography — **not** button, form, or alert rules. For component CSS you need `src/index`, `src/components`, or `dist/index.css`. + +### Option 4: Minimal / à la carte DS styles + +If you only need styling for a few patterns (for example **buttons and links**), importing the whole DS (Option 2 or 3) is heavier than necessary. Instead, import only what those components use. + +**No Sass** — import specific built CSS is not split in the DS package; the practical minimal JS approach is still `dist/index.css` **or** rely on `@cfpb/design-system-react/index.css` once those components are bundled in the library. + +**With Sass** — import only the DS modules you need, plus base tokens: + +```scss +@use '@cfpb/cfpb-design-system/src/base' as base; +@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button'; +@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link'; +@use '@cfpb/cfpb-design-system/src/components/cfpb-typography/link'; +``` + +Also load Source Sans 3 in your app (the React library’s `index.css` embeds it; with à la carte DS SCSS you may need `@fontsource-variable/source-sans-3` or your own font setup). + +| Pros | Cons | +| --- | --- | +| Smallest CSS footprint for targeted use | You must know which DS SCSS files match each React component | +| Good for apps that already use Sass and only use a slice of the system | More maintenance when you add components (new imports per component type) | +| Avoids shipping form/table/hero CSS you never use | Not documented per-component in this repo yet — follow DS class names in each component’s source | + +Examples of DS stylesheets some React components pull in (or may require until bundled in the library): + +| React area | DS stylesheet (under `@cfpb/cfpb-design-system/src/components/…`) | +| --- | --- | +| `Button` | `cfpb-buttons/button`, `cfpb-buttons/button-link` | +| `Link` | Base link styles in `cfpb-typography/link` (library also adds small icon spacing overrides) | +| `Heading` (`type="slug"`) | `cfpb-typography/slug-header` | +| `Pagination` | `cfpb-pagination/pagination` | +| Forms (`TextInput`, `Checkbox`, `Select`, …) | `cfpb-forms/text-input`, `form-field`, `label`, `select`, `form-alert`, … | +| `Alert` | `cfpb-notifications/notification` (+ library-specific overrides in the package) | +| `Table` | `cfpb-tables/table` | + +### Choosing an approach + +| Your situation | Suggested setup | +| --- | --- | +| New React app, Vite/CRA, few dependencies | **Option 1** — `import '@cfpb/design-system-react/index.css'` | +| Something looks unstyled | Check [Option 4](#option-4-minimal--à-la-carte-ds-styles) for that component’s DS file, or temporarily use **Option 2** | +| Existing CFPB app with global `@use '…/src/index'` | Keep your DS Sass; import React components for markup/behavior. Avoid duplicating **Option 1** unless you need React-only overrides | +| Only buttons + links, Sass already in the stack | **Option 4** (à la carte SCSS) or **Option 1** if the library CSS is enough | +| Full cf.gov parity, many DS patterns | **Option 3** or **Option 2** | + +### Quick start (Vite + React) + +```ts +// main.tsx +import '@cfpb/design-system-react/index.css'; +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.tsx'; + +createRoot(document.getElementById('root')!).render( + + + , +); +``` + +Ensure `@cfpb/cfpb-design-system` and `lit` are installed even if you only use Option 1, so peer dependencies and any web components resolve correctly. + ## Development To edit components or add new ones, install dependencies and run Storybook: From 6325fea080d009fd714ca49c86853654b1076061 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Fri, 26 Jun 2026 09:28:28 -0700 Subject: [PATCH 4/8] commit --- src/components/Alert/alert-field-level.tsx | 1 + src/components/Alert/alert.tsx | 1 + src/components/Checkbox/checkbox.tsx | 1 + src/components/Divider/divider.tsx | 1 + src/components/Fieldset/fieldset.tsx | 1 + src/components/Label/label.tsx | 1 + src/components/RadioButton/radio-button.tsx | 1 + src/components/Select/select-multi.tsx | 1 + src/components/Select/select-single.tsx | 1 + src/components/Table/table.tsx | 1 + src/components/TextInput/text-area.tsx | 1 + src/components/TextInput/text-input.tsx | 1 + src/components/Well/well.tsx | 1 + 13 files changed, 13 insertions(+) diff --git a/src/components/Alert/alert-field-level.tsx b/src/components/Alert/alert-field-level.tsx index 7a086fd507..f4214254f8 100644 --- a/src/components/Alert/alert-field-level.tsx +++ b/src/components/Alert/alert-field-level.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-alert.scss'; import classNames from 'classnames'; import type { HTMLAttributes, ReactNode } from 'react'; import type { JSXElement } from '../../types/jsx-element'; diff --git a/src/components/Alert/alert.tsx b/src/components/Alert/alert.tsx index d995b5b8e8..200d453f97 100644 --- a/src/components/Alert/alert.tsx +++ b/src/components/Alert/alert.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-notifications/notification.scss'; import classNames from 'classnames'; import type { HTMLAttributes, ReactNode } from 'react'; import type { HeadingLevel } from '../../types/heading-level'; diff --git a/src/components/Checkbox/checkbox.tsx b/src/components/Checkbox/checkbox.tsx index 201d77c0a1..0d6a07a839 100644 --- a/src/components/Checkbox/checkbox.tsx +++ b/src/components/Checkbox/checkbox.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-field.scss'; import classnames from 'classnames'; import type { ChangeEvent, ReactElement, ReactNode, RefObject } from 'react'; import { JSX, useCallback } from 'react'; diff --git a/src/components/Divider/divider.tsx b/src/components/Divider/divider.tsx index 888f34ebed..59ecbb5deb 100644 --- a/src/components/Divider/divider.tsx +++ b/src/components/Divider/divider.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-layout/layout.scss'; import type { HTMLProps, ReactElement } from 'react'; export const Divider = ({ diff --git a/src/components/Fieldset/fieldset.tsx b/src/components/Fieldset/fieldset.tsx index abb678c55a..70ea9e0565 100644 --- a/src/components/Fieldset/fieldset.tsx +++ b/src/components/Fieldset/fieldset.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form.scss'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import { JSX } from 'react'; diff --git a/src/components/Label/label.tsx b/src/components/Label/label.tsx index df94ab89a5..8129a543a9 100644 --- a/src/components/Label/label.tsx +++ b/src/components/Label/label.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/label.scss'; import classnames from 'classnames'; import { JSX } from 'react'; import type { ReactNode } from 'react'; diff --git a/src/components/RadioButton/radio-button.tsx b/src/components/RadioButton/radio-button.tsx index be77909c66..832ceee01b 100644 --- a/src/components/RadioButton/radio-button.tsx +++ b/src/components/RadioButton/radio-button.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-field.scss'; import type { ReactElement, ReactNode, RefObject } from 'react'; import { JSX } from 'react'; import { HelperText } from '../HelperText/helper-text'; diff --git a/src/components/Select/select-multi.tsx b/src/components/Select/select-multi.tsx index e38eaf8f1c..b71118047e 100644 --- a/src/components/Select/select-multi.tsx +++ b/src/components/Select/select-multi.tsx @@ -3,6 +3,7 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/multiselect.scss'; import { Multiselect } from '@cfpb/cfpb-design-system/src/components/cfpb-forms'; import { JSX, useEffect, useRef, useState } from 'react'; import { noOp } from '../../utils/no-op'; diff --git a/src/components/Select/select-single.tsx b/src/components/Select/select-single.tsx index 1e85d3288d..0c46abedc1 100644 --- a/src/components/Select/select-single.tsx +++ b/src/components/Select/select-single.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/select.scss'; import type { ChangeEvent } from 'react'; import { JSX } from 'react'; import { noOp } from '../../utils/no-op'; diff --git a/src/components/Table/table.tsx b/src/components/Table/table.tsx index 838093ecd0..f0688f64e5 100644 --- a/src/components/Table/table.tsx +++ b/src/components/Table/table.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-tables/table.scss'; import classNames from 'classnames'; import { forwardRef, diff --git a/src/components/TextInput/text-area.tsx b/src/components/TextInput/text-area.tsx index 445d1ba896..760ca4c7f5 100644 --- a/src/components/TextInput/text-area.tsx +++ b/src/components/TextInput/text-area.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; import classNames from 'classnames'; import { forwardRef, diff --git a/src/components/TextInput/text-input.tsx b/src/components/TextInput/text-input.tsx index a17a8fedc5..212421e2a3 100644 --- a/src/components/TextInput/text-input.tsx +++ b/src/components/TextInput/text-input.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; import classnames from 'classnames'; import { forwardRef, diff --git a/src/components/Well/well.tsx b/src/components/Well/well.tsx index 706f47545e..d515f970ca 100644 --- a/src/components/Well/well.tsx +++ b/src/components/Well/well.tsx @@ -1,3 +1,4 @@ +import '@cfpb/cfpb-design-system/src/components/cfpb-layout/well.scss'; import { isValidElement, JSX } from 'react'; import type { HeadingLevel } from '../../types/heading-level'; import { ListLink } from '../Link/link'; From 19cbd74af17548703a1b55d203891146ce00fe03 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:11:16 -0700 Subject: [PATCH 5/8] ts barrel import --- README.md | 14 ++++---- src/assets/styles/ds-components.ts | 39 +++++++++++++++++++++ src/components/Alert/alert-field-level.tsx | 1 - src/components/Alert/alert.tsx | 1 - src/components/Buttons/button.tsx | 2 -- src/components/Checkbox/checkbox.tsx | 1 - src/components/Divider/divider.tsx | 1 - src/components/Fieldset/fieldset.tsx | 1 - src/components/Headings/heading.tsx | 1 - src/components/Label/label.tsx | 1 - src/components/Pagination/pagination.tsx | 1 - src/components/RadioButton/radio-button.tsx | 1 - src/components/Select/select-multi.tsx | 1 - src/components/Select/select-single.tsx | 1 - src/components/Table/table.tsx | 1 - src/components/TextInput/text-area.tsx | 1 - src/components/TextInput/text-input.tsx | 1 - src/components/Well/well.tsx | 1 - src/index.ts | 1 + 19 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 src/assets/styles/ds-components.ts diff --git a/README.md b/README.md index edcf88bf75..ce2f41c45b 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ export default function SomePage(): ReactElement { ## Styles -`@cfpb/design-system-react` ships precompiled CSS at `@cfpb/design-system-react/index.css`. Styles from `@cfpb/cfpb-design-system` are folded into that file when each React component imports the matching DS stylesheet during the library build. +`@cfpb/design-system-react` ships precompiled CSS at `@cfpb/design-system-react/index.css`. Matching DS styles from `@cfpb/cfpb-design-system` are listed in [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts) and bundled during the library build. You do **not** need Sass in your app for the default setup. Pick an approach based on how many components you use and whether you already compile SCSS. @@ -73,8 +73,8 @@ import '@cfpb/design-system-react/index.css'; | Pros | Cons | | --- | --- | -| One import; no Sass toolchain required | Bundle includes CSS for components the library bundles today — not necessarily every DS module yet | -| Matches how the React package is meant to be consumed | If a component’s DS styles are not yet in the library build, that component may look unstyled until the library adds the import | +| One import; no Sass toolchain required | `index.css` includes styles listed in `ds-components.ts`, not every DS module | +| Matches how the React package is meant to be consumed | New React components need a matching DS import added to `ds-components.ts` | | Includes Source Sans 3 (embedded in the built CSS) | | Use this when you want the simplest Vite/CRA-style setup and are mostly using `@cfpb/design-system-react` components. @@ -135,10 +135,10 @@ Also load Source Sans 3 in your app (the React library’s `index.css` embeds it | Pros | Cons | | --- | --- | | Smallest CSS footprint for targeted use | You must know which DS SCSS files match each React component | -| Good for apps that already use Sass and only use a slice of the system | More maintenance when you add components (new imports per component type) | -| Avoids shipping form/table/hero CSS you never use | Not documented per-component in this repo yet — follow DS class names in each component’s source | +| Good for apps that already use Sass and only use a slice of the system | More maintenance when you add components (new imports in `ds-components.ts` or your own SCSS) | +| Avoids shipping form/table/hero CSS you never use | See [`ds-components.ts`](src/assets/styles/ds-components.ts) for what the library bundles today | -Examples of DS stylesheets some React components pull in (or may require until bundled in the library): +Examples of DS stylesheets mapped in [`ds-components.ts`](src/assets/styles/ds-components.ts): | React area | DS stylesheet (under `@cfpb/cfpb-design-system/src/components/…`) | | --- | --- | @@ -191,6 +191,8 @@ This project uses Yarn 4 with the `node-modules` linker (see `.yarnrc.yml`). Edit the files in `src/components/` and your browser should hot reload your changes. +When a component uses Design System class names (for example `.a-btn`, `.m-form-field`), add the matching DS SCSS import to [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts). Do not import DS styles from individual component files — the barrel keeps the list in one place and feeds `dist/index.css`. + Add tests to files called `.test.tsx`. See [`Buttons.test.tsx`](/src/components/Buttons/Button.test.tsx) for an example. Run `yarn test` to watch for changes and run tests automatically. diff --git a/src/assets/styles/ds-components.ts b/src/assets/styles/ds-components.ts new file mode 100644 index 0000000000..dd827c6388 --- /dev/null +++ b/src/assets/styles/ds-components.ts @@ -0,0 +1,39 @@ +/** + * Curated Design System component styles bundled into `dist/index.css`. + * + * When adding a React component that uses DS class names, add the matching DS + * SCSS import here (once per file — duplicates are unnecessary). Component + * `.tsx` files should not import DS styles directly. + * + * @see https://github.com/cfpb/design-system-react#styles + */ + +// Buttons — Button +import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link.scss'; + +// Forms — Checkbox, RadioButton, Fieldset, Label, HelperText, TextInput, +// TextArea, SelectSingle, SelectMulti, AlertFieldLevel +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-field.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-alert.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/label.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/select.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-forms/multiselect.scss'; + +// Typography — Heading (type="slug") +import '@cfpb/cfpb-design-system/src/components/cfpb-typography/slug-header.scss'; + +// Layout — Divider (.content__line), Well +import '@cfpb/cfpb-design-system/src/components/cfpb-layout/layout.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-layout/well.scss'; + +// Notifications — Alert (page-level) +import '@cfpb/cfpb-design-system/src/components/cfpb-notifications/notification.scss'; + +// Pagination — Pagination +import '@cfpb/cfpb-design-system/src/components/cfpb-pagination/pagination.scss'; + +// Tables — Table +import '@cfpb/cfpb-design-system/src/components/cfpb-tables/table.scss'; diff --git a/src/components/Alert/alert-field-level.tsx b/src/components/Alert/alert-field-level.tsx index f4214254f8..7a086fd507 100644 --- a/src/components/Alert/alert-field-level.tsx +++ b/src/components/Alert/alert-field-level.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-alert.scss'; import classNames from 'classnames'; import type { HTMLAttributes, ReactNode } from 'react'; import type { JSXElement } from '../../types/jsx-element'; diff --git a/src/components/Alert/alert.tsx b/src/components/Alert/alert.tsx index 200d453f97..d995b5b8e8 100644 --- a/src/components/Alert/alert.tsx +++ b/src/components/Alert/alert.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-notifications/notification.scss'; import classNames from 'classnames'; import type { HTMLAttributes, ReactNode } from 'react'; import type { HeadingLevel } from '../../types/heading-level'; diff --git a/src/components/Buttons/button.tsx b/src/components/Buttons/button.tsx index 1e4cd9ad92..4fd4739b6b 100644 --- a/src/components/Buttons/button.tsx +++ b/src/components/Buttons/button.tsx @@ -1,5 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button.scss'; -import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link.scss'; import { forwardRef, JSX, diff --git a/src/components/Checkbox/checkbox.tsx b/src/components/Checkbox/checkbox.tsx index 0d6a07a839..201d77c0a1 100644 --- a/src/components/Checkbox/checkbox.tsx +++ b/src/components/Checkbox/checkbox.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-field.scss'; import classnames from 'classnames'; import type { ChangeEvent, ReactElement, ReactNode, RefObject } from 'react'; import { JSX, useCallback } from 'react'; diff --git a/src/components/Divider/divider.tsx b/src/components/Divider/divider.tsx index 59ecbb5deb..888f34ebed 100644 --- a/src/components/Divider/divider.tsx +++ b/src/components/Divider/divider.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-layout/layout.scss'; import type { HTMLProps, ReactElement } from 'react'; export const Divider = ({ diff --git a/src/components/Fieldset/fieldset.tsx b/src/components/Fieldset/fieldset.tsx index 70ea9e0565..abb678c55a 100644 --- a/src/components/Fieldset/fieldset.tsx +++ b/src/components/Fieldset/fieldset.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form.scss'; import classNames from 'classnames'; import type { ReactNode } from 'react'; import { JSX } from 'react'; diff --git a/src/components/Headings/heading.tsx b/src/components/Headings/heading.tsx index 3ce4274907..259f6fef55 100644 --- a/src/components/Headings/heading.tsx +++ b/src/components/Headings/heading.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-typography/slug-header.scss'; import classnames from 'classnames'; import { JSX } from 'react'; import type { HTMLProps } from 'react'; diff --git a/src/components/Label/label.tsx b/src/components/Label/label.tsx index 8129a543a9..df94ab89a5 100644 --- a/src/components/Label/label.tsx +++ b/src/components/Label/label.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/label.scss'; import classnames from 'classnames'; import { JSX } from 'react'; import type { ReactNode } from 'react'; diff --git a/src/components/Pagination/pagination.tsx b/src/components/Pagination/pagination.tsx index 7746c6ff98..01965e0147 100644 --- a/src/components/Pagination/pagination.tsx +++ b/src/components/Pagination/pagination.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-pagination/pagination.scss'; import type { ChangeEvent, FormEvent, ReactElement } from 'react'; import { JSX, useEffect, useId, useState } from 'react'; import { Button } from '../Buttons/button'; diff --git a/src/components/RadioButton/radio-button.tsx b/src/components/RadioButton/radio-button.tsx index 832ceee01b..be77909c66 100644 --- a/src/components/RadioButton/radio-button.tsx +++ b/src/components/RadioButton/radio-button.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/form-field.scss'; import type { ReactElement, ReactNode, RefObject } from 'react'; import { JSX } from 'react'; import { HelperText } from '../HelperText/helper-text'; diff --git a/src/components/Select/select-multi.tsx b/src/components/Select/select-multi.tsx index b71118047e..e38eaf8f1c 100644 --- a/src/components/Select/select-multi.tsx +++ b/src/components/Select/select-multi.tsx @@ -3,7 +3,6 @@ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ /* eslint-disable @typescript-eslint/no-unsafe-call */ /* eslint-disable @typescript-eslint/no-unsafe-assignment */ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/multiselect.scss'; import { Multiselect } from '@cfpb/cfpb-design-system/src/components/cfpb-forms'; import { JSX, useEffect, useRef, useState } from 'react'; import { noOp } from '../../utils/no-op'; diff --git a/src/components/Select/select-single.tsx b/src/components/Select/select-single.tsx index 0c46abedc1..1e85d3288d 100644 --- a/src/components/Select/select-single.tsx +++ b/src/components/Select/select-single.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/select.scss'; import type { ChangeEvent } from 'react'; import { JSX } from 'react'; import { noOp } from '../../utils/no-op'; diff --git a/src/components/Table/table.tsx b/src/components/Table/table.tsx index f0688f64e5..838093ecd0 100644 --- a/src/components/Table/table.tsx +++ b/src/components/Table/table.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-tables/table.scss'; import classNames from 'classnames'; import { forwardRef, diff --git a/src/components/TextInput/text-area.tsx b/src/components/TextInput/text-area.tsx index 760ca4c7f5..445d1ba896 100644 --- a/src/components/TextInput/text-area.tsx +++ b/src/components/TextInput/text-area.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; import classNames from 'classnames'; import { forwardRef, diff --git a/src/components/TextInput/text-input.tsx b/src/components/TextInput/text-input.tsx index 212421e2a3..a17a8fedc5 100644 --- a/src/components/TextInput/text-input.tsx +++ b/src/components/TextInput/text-input.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; import classnames from 'classnames'; import { forwardRef, diff --git a/src/components/Well/well.tsx b/src/components/Well/well.tsx index d515f970ca..706f47545e 100644 --- a/src/components/Well/well.tsx +++ b/src/components/Well/well.tsx @@ -1,4 +1,3 @@ -import '@cfpb/cfpb-design-system/src/components/cfpb-layout/well.scss'; import { isValidElement, JSX } from 'react'; import type { HeadingLevel } from '../../types/heading-level'; import { ListLink } from '../Link/link'; diff --git a/src/index.ts b/src/index.ts index 9a7d7dec82..8d2cb0cc09 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import '@fontsource-variable/source-sans-3'; import './assets/styles/_shared.scss'; +import './assets/styles/ds-components'; export { Alert } from './components/Alert/alert'; export { AlertFieldLevel } from './components/Alert/alert-field-level'; From 5867cf29fc646e2b9591dd536fc19474704dbdf4 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:53:37 -0700 Subject: [PATCH 6/8] save work --- README.md | 147 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 85 insertions(+), 62 deletions(-) diff --git a/README.md b/README.md index ce2f41c45b..d183b90a67 100644 --- a/README.md +++ b/README.md @@ -59,108 +59,115 @@ export default function SomePage(): ReactElement { ## Styles -`@cfpb/design-system-react` ships precompiled CSS at `@cfpb/design-system-react/index.css`. Matching DS styles from `@cfpb/cfpb-design-system` are listed in [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts) and bundled during the library build. +DSR components render the same CSS class names as `@cfpb/cfpb-design-system` (for example `.a-btn`, `.m-form-field`). **Styles must be loaded separately** — importing React components alone does not apply CFPB styling. -You do **not** need Sass in your app for the default setup. Pick an approach based on how many components you use and whether you already compile SCSS. +There are **two supported patterns**. Pick one global CSS source for your app — **do not load both**. -### Option 1: Library CSS only (recommended default) +### Pattern A: DSR CSS only (new React apps) -Import once at your app entry (for example `main.tsx`): +For Vite/CRA-style apps with no Sass pipeline. Import the library’s prebuilt stylesheet once: ```ts +// main.tsx or App.tsx import '@cfpb/design-system-react/index.css'; ``` -| Pros | Cons | +| | | | --- | --- | -| One import; no Sass toolchain required | `index.css` includes styles listed in `ds-components.ts`, not every DS module | -| Matches how the React package is meant to be consumed | New React components need a matching DS import added to `ds-components.ts` | -| Includes Source Sans 3 (embedded in the built CSS) | | +| **You get** | DS styles for components listed in [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts), plus Source Sans 3 (embedded), plus DSR-specific overrides | +| **You still install** | `@cfpb/cfpb-design-system` (peer dependency — web components, version alignment) | +| **You do not import** | `@cfpb/cfpb-design-system/dist/index.css` or `@use '…/src/index'` in your app | +| **Best for** | Greenfield React apps that mostly use DSR components (`dsr-test`, new internal tools) | -Use this when you want the simplest Vite/CRA-style setup and are mostly using `@cfpb/design-system-react` components. +The [`ds-components.ts`](src/assets/styles/ds-components.ts) barrel is the **library-maintained list** of DS SCSS files that feed `dist/index.css`. DSR contributors add to it when new React components need DS styles. App developers using Pattern A do not touch that file. -### Option 2: Full Design System CSS (JavaScript import) +### Pattern B: Full DS CSS + DSR components (existing CFPB apps) -Install `@cfpb/cfpb-design-system`, then in your app entry: +For apps that already load the full Design System — Sass-based properties, hand-rolled DS markup, cf.gov-style setups (for example apps that use `.o-expandable`, `.m-list`, `.m-btn-group` outside DSR components). -```ts -import '@cfpb/cfpb-design-system/dist/index.css'; -// Optionally also import the React library CSS if you need its component-specific overrides: -// import '@cfpb/design-system-react/index.css'; -``` +Import **DSR components only**. Do **not** import `@cfpb/design-system-react/index.css`. -| Pros | Cons | -| --- | --- | -| All DS component styles (buttons, forms, tables, alerts, layout, …) | ~90KB+ of CSS even if you only use a few components | -| Works even when the React library has not yet bundled a component’s SCSS | Duplicates rules if you **also** import `@cfpb/design-system-react/index.css` — prefer one or the other, or drop the React CSS if DS CSS alone is enough | -| No Sass required | Keep `@cfpb/cfpb-design-system` on a compatible version with your React library peer range | +**JavaScript / prebuilt CSS:** -Use this when you mix React components with plain HTML/DS class names, or when you hit a component that is not fully styled via Option 1 yet. +```ts +// App entry — components from DSR, styles from DS +import { Button, Heading } from '@cfpb/design-system-react'; +// No: import '@cfpb/design-system-react/index.css'; +``` -### Option 3: Full Design System via Sass (cf.gov-style apps) +```scss +// base.scss or global styles entry +@use '@cfpb/cfpb-design-system/src/abstracts' as *; +@use '@cfpb/cfpb-design-system/src/base' as *; +@use '@cfpb/cfpb-design-system/dist/index.css' as *; +``` -If your app already compiles SCSS, you can load the entire DS from source: +**Or Sass source (same coverage as `dist/index.css`):** ```scss @use '@cfpb/cfpb-design-system/src/index' as *; ``` -That resolves to the package’s `src/index.scss`, which forwards **base**, **abstracts**, **components**, and **utilities** — the same coverage as `dist/index.css`, but compiled into your app’s stylesheet so you can use DS variables and mixins (for example `$bp-sm-min`, `@include respond-to-min`). - -| Pros | Cons | +| | | | --- | --- | -| Full DS styling + Sass API for your own SCSS | Requires a Sass build step | -| Same pattern used on many CFPB properties | Easy to overlap with `@cfpb/design-system-react/index.css` — usually pick DS **or** React library CSS, not both | -| Versioned with your lockfile, not a second prebuilt CSS file | Slightly more setup (load paths / bundler config) | +| **You get** | Full DS component CSS (expandables, lists, button groups, cards, …) and your existing Sass mixins/variables via `@use '…/abstracts'` | +| **You still install** | Both `@cfpb/design-system-react` and `@cfpb/cfpb-design-system` | +| **You do not import** | `@cfpb/design-system-react/index.css` — it duplicates DS rules and embeds fonts a second time | +| **Fonts** | Load Source Sans yourself (for example `@fontsource-variable/source-sans-3` + DS `licensed-font` mixin). DS `dist/index.css` does not include fonts | +| **Best for** | Legacy apps mixing DSR React components with plain DS class names in JSX/SCSS | -**Note:** `@use '@cfpb/cfpb-design-system/src/abstracts'` and `@use '…/src/base'` only give you tokens and global typography — **not** button, form, or alert rules. For component CSS you need `src/index`, `src/components`, or `dist/index.css`. +Per-component `@use '@cfpb/cfpb-design-system/src/abstracts'` in your app SCSS is fine — that is Sass API (breakpoints, mixins), not duplicate component CSS. -### Option 4: Minimal / à la carte DS styles +### Do not combine Pattern A and Pattern B -If you only need styling for a few patterns (for example **buttons and links**), importing the whole DS (Option 2 or 3) is heavier than necessary. Instead, import only what those components use. +| If you import… | Also import… | Result | +| --- | --- | --- | +| `@cfpb/design-system-react/index.css` | `@cfpb/cfpb-design-system/dist/index.css` | Duplicate button/form/alert rules; fonts loaded twice | +| `@cfpb/design-system-react/index.css` | `@use '…/src/index'` in Sass | Same duplication | -**No Sass** — import specific built CSS is not split in the DS package; the practical minimal JS approach is still `dist/index.css` **or** rely on `@cfpb/design-system-react/index.css` once those components are bundled in the library. +DSR React components work with either pattern — they emit standard DS classes. Pattern B apps rely on the app’s global DS stylesheet; Pattern A apps rely on the library’s `index.css`. -**With Sass** — import only the DS modules you need, plus base tokens: +### Choosing a pattern -```scss -@use '@cfpb/cfpb-design-system/src/base' as base; -@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button'; -@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link'; -@use '@cfpb/cfpb-design-system/src/components/cfpb-typography/link'; -``` - -Also load Source Sans 3 in your app (the React library’s `index.css` embeds it; with à la carte DS SCSS you may need `@fontsource-variable/source-sans-3` or your own font setup). - -| Pros | Cons | +| Your situation | Use | | --- | --- | -| Smallest CSS footprint for targeted use | You must know which DS SCSS files match each React component | -| Good for apps that already use Sass and only use a slice of the system | More maintenance when you add components (new imports in `ds-components.ts` or your own SCSS) | -| Avoids shipping form/table/hero CSS you never use | See [`ds-components.ts`](src/assets/styles/ds-components.ts) for what the library bundles today | +| New React app, Vite/CRA, mostly DSR components | **Pattern A** | +| Existing app with `dist/index.css` or `@use '…/src/index'` in global SCSS | **Pattern B** | +| App uses hand-rolled `.o-expandable`, `.m-list`, `.m-btn-group`, etc. | **Pattern B** (DSR barrel does not include every DS module) | +| Something looks unstyled on Pattern A | Add the DS file to [`ds-components.ts`](src/assets/styles/ds-components.ts) in DSR, or temporarily switch to Pattern B until the barrel is updated | + +### What `ds-components.ts` covers today -Examples of DS stylesheets mapped in [`ds-components.ts`](src/assets/styles/ds-components.ts): +Styles bundled into `@cfpb/design-system-react/index.css` (Pattern A only): | React area | DS stylesheet (under `@cfpb/cfpb-design-system/src/components/…`) | | --- | --- | | `Button` | `cfpb-buttons/button`, `cfpb-buttons/button-link` | -| `Link` | Base link styles in `cfpb-typography/link` (library also adds small icon spacing overrides) | | `Heading` (`type="slug"`) | `cfpb-typography/slug-header` | | `Pagination` | `cfpb-pagination/pagination` | -| Forms (`TextInput`, `Checkbox`, `Select`, …) | `cfpb-forms/text-input`, `form-field`, `label`, `select`, `form-alert`, … | -| `Alert` | `cfpb-notifications/notification` (+ library-specific overrides in the package) | +| Forms (`TextInput`, `Checkbox`, `Select`, …) | `cfpb-forms/form`, `form-field`, `label`, `text-input`, `select`, `multiselect`, `form-alert` | +| `Alert` | `cfpb-notifications/notification` (+ DSR overrides in `alert.scss`) | | `Table` | `cfpb-tables/table` | +| `Well`, `Divider` | `cfpb-layout/well`, `cfpb-layout/layout` | -### Choosing an approach +Not in the barrel (Pattern B or future DSR work): expandables, lists, button groups, link typography, hero, cards, and other DS modules. Pattern B apps get these from full DS CSS automatically. -| Your situation | Suggested setup | -| --- | --- | -| New React app, Vite/CRA, few dependencies | **Option 1** — `import '@cfpb/design-system-react/index.css'` | -| Something looks unstyled | Check [Option 4](#option-4-minimal--à-la-carte-ds-styles) for that component’s DS file, or temporarily use **Option 2** | -| Existing CFPB app with global `@use '…/src/index'` | Keep your DS Sass; import React components for markup/behavior. Avoid duplicating **Option 1** unless you need React-only overrides | -| Only buttons + links, Sass already in the stack | **Option 4** (à la carte SCSS) or **Option 1** if the library CSS is enough | -| Full cf.gov parity, many DS patterns | **Option 3** or **Option 2** | +### Other options (advanced) + +**À la carte Sass** — if you only need buttons and links and already compile SCSS, import specific DS modules instead of full `dist/index.css`: + +```scss +@use '@cfpb/cfpb-design-system/src/base' as base; +@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button'; +@use '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link'; +@use '@cfpb/cfpb-design-system/src/components/cfpb-typography/link'; +``` -### Quick start (Vite + React) +Load fonts yourself. This is a slimmer alternative to Pattern B when you control exactly which DS patterns you use. See [`ds-components.ts`](src/assets/styles/ds-components.ts) for the library’s curated equivalent on Pattern A. + +**Abstracts/base only** — `@use '…/src/abstracts'` and `@use '…/src/base'` give tokens and global typography, **not** component rules (no `.a-btn`). You still need Pattern A, Pattern B, or à la carte component imports. + +### Quick start (Pattern A — Vite + React) ```ts // main.tsx @@ -176,7 +183,23 @@ createRoot(document.getElementById('root')!).render( ); ``` -Ensure `@cfpb/cfpb-design-system` and `lit` are installed even if you only use Option 1, so peer dependencies and any web components resolve correctly. +Ensure `@cfpb/cfpb-design-system` and `lit` are installed even on Pattern A, so peer dependencies and web components resolve correctly. + +### Quick start (Pattern B — existing DS app) + +```js +// App.js — global SCSS already loads DS via base.scss +import './css/App.scss'; +import { Button, Heading } from '@cfpb/design-system-react'; +// Do not import '@cfpb/design-system-react/index.css' +``` + +```scss +// base.scss +@use '@cfpb/cfpb-design-system/src/abstracts' as *; +@use '@cfpb/cfpb-design-system/src/base' as *; +@use '@cfpb/cfpb-design-system/dist/index.css' as *; +``` ## Development From 194f2495194da91288e02cbb0a428584d07f2204 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Fri, 26 Jun 2026 16:20:26 -0700 Subject: [PATCH 7/8] adding info regarding how to update storybook --- .storybook/preview.js | 1 + README.md | 24 +++++++++++++++++++++++- src/assets/styles/_shared.scss | 5 ++++- src/assets/styles/ds-components.ts | 3 ++- 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/.storybook/preview.js b/.storybook/preview.js index a709f1a0da..787df709fa 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -3,6 +3,7 @@ import { buildArgsParam } from 'storybook/internal/router'; import { useArgs, useGlobals } from 'storybook/preview-api'; import '@fontsource-variable/source-sans-3'; import '../src/assets/styles/_shared.scss'; +import '../src/assets/styles/ds-components'; import themeCFPB from './themeCFPB'; const responsivePreviewQueryParameter = 'responsivePreview'; diff --git a/README.md b/README.md index d183b90a67..285c6fd5ee 100644 --- a/README.md +++ b/README.md @@ -185,6 +185,28 @@ createRoot(document.getElementById('root')!).render( Ensure `@cfpb/cfpb-design-system` and `lit` are installed even on Pattern A, so peer dependencies and web components resolve correctly. +### Storybook (contributors) + +Storybook does **not** load prebuilt `dist/index.css`. It compiles the same source stack as Pattern A apps, wired in [`.storybook/preview.js`](.storybook/preview.js): + +```js +import '@fontsource-variable/source-sans-3'; +import '../src/assets/styles/_shared.scss'; +import '../src/assets/styles/ds-components'; +``` + +| Layer | Purpose | +| --- | --- | +| `@fontsource-variable/source-sans-3` | Registers `@font-face` in the preview bundle — required for nested “All viewports” iframes (each iframe is a separate document) | +| `_shared.scss` | DS tokens/normalize plus DSR overrides (font stack, `.wrapper--match-content`, docs-tab prose in `#storybook-docs`) | +| `ds-components.ts` | DS component rules that feed `dist/index.css` for npm consumers | + +Import **`ds-components` in `preview.js`**, not only via `~/src/index` in individual stories. Otherwise stories that import a component directly (for example `./checkbox`) may render without form/button/alert styles depending on load order. + +Stories may import from `~/src/index` or from a local component file — global styles come from `preview.js`. Per-component `.scss` files (for example `banner.scss`, `link.scss`) still load when that component is imported. + +Storybook-only extras (not in published `index.css`): [`.storybook/preview-head.html`](.storybook/preview-head.html) canvas padding and nested-iframe focus tweaks. + ### Quick start (Pattern B — existing DS app) ```js @@ -214,7 +236,7 @@ This project uses Yarn 4 with the `node-modules` linker (see `.yarnrc.yml`). Edit the files in `src/components/` and your browser should hot reload your changes. -When a component uses Design System class names (for example `.a-btn`, `.m-form-field`), add the matching DS SCSS import to [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts). Do not import DS styles from individual component files — the barrel keeps the list in one place and feeds `dist/index.css`. +When a component uses Design System class names (for example `.a-btn`, `.m-form-field`), add the matching DS SCSS import to [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts). Do not import DS styles from individual component files — the barrel keeps the list in one place and feeds `dist/index.css` and Storybook (via `.storybook/preview.js`). See [Storybook (contributors)](#storybook-contributors) under [Styles](#styles). Add tests to files called `.test.tsx`. See [`Buttons.test.tsx`](/src/components/Buttons/Button.test.tsx) for an example. diff --git a/src/assets/styles/_shared.scss b/src/assets/styles/_shared.scss index 6e458e8808..43ebfe1027 100644 --- a/src/assets/styles/_shared.scss +++ b/src/assets/styles/_shared.scss @@ -13,7 +13,10 @@ /** * Source Sans 3 is loaded via `@fontsource-variable/source-sans-3` in **`src/index.ts`** (apps) * and **`.storybook/preview.js`** (Storybook, including nested “All viewports” iframes) before - * `_shared.scss` so `@font-face` is always registered. + * this file so `@font-face` is always registered. + * + * DS component styles are in **`ds-components.ts`**, imported from **`src/index.ts`** and + * **`.storybook/preview.js`** alongside this file. * * DS `custom-props` sets `--font-stack-branded: initial`, so `var(--font-stack)` falls back to * `system-ui`. Other DS chunks can repeat that `:root` block when code-split; in dev the last diff --git a/src/assets/styles/ds-components.ts b/src/assets/styles/ds-components.ts index dd827c6388..ee13d05866 100644 --- a/src/assets/styles/ds-components.ts +++ b/src/assets/styles/ds-components.ts @@ -5,7 +5,8 @@ * SCSS import here (once per file — duplicates are unnecessary). Component * `.tsx` files should not import DS styles directly. * - * @see https://github.com/cfpb/design-system-react#styles + * Styles listed here are bundled into `dist/index.css` and loaded in Storybook via + * `.storybook/preview.js` (alongside `_shared.scss` and Fontsource). */ // Buttons — Button From 17a189a960072b17aeedbd2049f8b7cad85809e7 Mon Sep 17 00:00:00 2001 From: Richard Dinh <1038306+flacoman91@users.noreply.github.com> Date: Fri, 26 Jun 2026 18:21:22 -0700 Subject: [PATCH 8/8] clean up storybook references, --- .storybook/preview.js | 4 +- README.md | 92 +++++++++---------- eslint.config.js | 28 ++++++ src/assets/styles/_shared.scss | 11 +-- src/assets/styles/ds-components.ts | 10 +- src/assets/styles/entry-styles.ts | 8 ++ src/components/Alert/alert.stories.tsx | 4 +- src/components/Banner/banner.stories.tsx | 2 +- .../Breadcrumb/breadcrumb.stories.tsx | 2 +- src/components/Buttons/buttons.stories.tsx | 3 +- src/components/Checkbox/checkbox-overview.mdx | 5 +- src/components/Divider/divider.stories.tsx | 2 +- .../Expandable/expandable.stories.tsx | 2 +- src/components/Fieldset/fieldset.stories.tsx | 4 +- src/components/Grid/grid.stories.tsx | 2 +- src/components/Header/header.stories.tsx | 2 +- src/components/Header/responsive-menu.scss | 1 + src/components/Headings/headings.stories.tsx | 2 +- src/components/Hero/hero.stories.tsx | 2 +- src/components/Icon/icon.stories.tsx | 3 +- src/components/Label/label.stories.tsx | 2 +- .../Layout/layout-content.stories.tsx | 2 +- src/components/Layout/layout-main.stories.tsx | 2 +- .../Layout/layout-sidebar.stories.tsx | 2 +- .../Layout/layout-wrapper.stories.tsx | 2 +- src/components/Link/link.stories.tsx | 4 +- src/components/List/list.stories.tsx | 4 +- .../Pagination/pagination.stories.tsx | 3 +- .../RadioButton/radio-button.stories.tsx | 2 +- .../Select/select-multi.stories.tsx | 2 +- src/components/Select/select-overview.mdx | 5 +- src/components/Select/select.stories.tsx | 3 +- src/components/Table/table.stories.tsx | 2 +- .../TextInput/text-input-overview.mdx | 5 +- .../TextInput/text-input.stories.tsx | 4 +- .../text-introduction.stories.tsx | 3 +- src/index.ts | 4 +- src/stories/Introduction.mdx | 3 +- 38 files changed, 149 insertions(+), 94 deletions(-) create mode 100644 src/assets/styles/entry-styles.ts diff --git a/.storybook/preview.js b/.storybook/preview.js index 787df709fa..8a1a1ef0ff 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,9 +1,7 @@ import React from 'react'; import { buildArgsParam } from 'storybook/internal/router'; import { useArgs, useGlobals } from 'storybook/preview-api'; -import '@fontsource-variable/source-sans-3'; -import '../src/assets/styles/_shared.scss'; -import '../src/assets/styles/ds-components'; +import '../src/assets/styles/entry-styles'; import themeCFPB from './themeCFPB'; const responsivePreviewQueryParameter = 'responsivePreview'; diff --git a/README.md b/README.md index 285c6fd5ee..540bf1aed0 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ Add `react-router` if you use `Link` with `isRouterLink`: yarn add react-router ``` -| Peer | When you need it | -| --- | --- | +| Peer | When you need it | +| -------------------------- | --------------------------------------------------------------------------------------------------------------- | | `@cfpb/cfpb-design-system` | Always install it. Required for DS web components and for importing DS styles directly (see [Styles](#styles)). | -| `lit` | Components that render DS web components (for example `Banner` / ``). | -| `react-router` | `Link` with `isRouterLink` only. | +| `lit` | Components that render DS web components (for example `Banner` / ``). | +| `react-router` | `Link` with `isRouterLink` only. | ## Usage @@ -72,12 +72,12 @@ For Vite/CRA-style apps with no Sass pipeline. Import the library’s prebuilt s import '@cfpb/design-system-react/index.css'; ``` -| | | -| --- | --- | -| **You get** | DS styles for components listed in [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts), plus Source Sans 3 (embedded), plus DSR-specific overrides | -| **You still install** | `@cfpb/cfpb-design-system` (peer dependency — web components, version alignment) | -| **You do not import** | `@cfpb/cfpb-design-system/dist/index.css` or `@use '…/src/index'` in your app | -| **Best for** | Greenfield React apps that mostly use DSR components (`dsr-test`, new internal tools) | +| | | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **You get** | DS styles for components listed in [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts), plus Source Sans 3 (embedded), plus DSR-specific overrides | +| **You still install** | `@cfpb/cfpb-design-system` (peer dependency — web components, version alignment) | +| **You do not import** | `@cfpb/cfpb-design-system/dist/index.css` or `@use '…/src/index'` in your app | +| **Best for** | Greenfield React apps that mostly use DSR components (`dsr-test`, new internal tools) | The [`ds-components.ts`](src/assets/styles/ds-components.ts) barrel is the **library-maintained list** of DS SCSS files that feed `dist/index.css`. DSR contributors add to it when new React components need DS styles. App developers using Pattern A do not touch that file. @@ -108,47 +108,47 @@ import { Button, Heading } from '@cfpb/design-system-react'; @use '@cfpb/cfpb-design-system/src/index' as *; ``` -| | | -| --- | --- | -| **You get** | Full DS component CSS (expandables, lists, button groups, cards, …) and your existing Sass mixins/variables via `@use '…/abstracts'` | -| **You still install** | Both `@cfpb/design-system-react` and `@cfpb/cfpb-design-system` | -| **You do not import** | `@cfpb/design-system-react/index.css` — it duplicates DS rules and embeds fonts a second time | -| **Fonts** | Load Source Sans yourself (for example `@fontsource-variable/source-sans-3` + DS `licensed-font` mixin). DS `dist/index.css` does not include fonts | -| **Best for** | Legacy apps mixing DSR React components with plain DS class names in JSX/SCSS | +| | | +| --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | +| **You get** | Full DS component CSS (expandables, lists, button groups, cards, …) and your existing Sass mixins/variables via `@use '…/abstracts'` | +| **You still install** | Both `@cfpb/design-system-react` and `@cfpb/cfpb-design-system` | +| **You do not import** | `@cfpb/design-system-react/index.css` — it duplicates DS rules and embeds fonts a second time | +| **Fonts** | Load Source Sans yourself (for example `@fontsource-variable/source-sans-3` + DS `licensed-font` mixin). DS `dist/index.css` does not include fonts | +| **Best for** | Legacy apps mixing DSR React components with plain DS class names in JSX/SCSS | Per-component `@use '@cfpb/cfpb-design-system/src/abstracts'` in your app SCSS is fine — that is Sass API (breakpoints, mixins), not duplicate component CSS. ### Do not combine Pattern A and Pattern B -| If you import… | Also import… | Result | -| --- | --- | --- | +| If you import… | Also import… | Result | +| ------------------------------------- | ----------------------------------------- | ----------------------------------------------------- | | `@cfpb/design-system-react/index.css` | `@cfpb/cfpb-design-system/dist/index.css` | Duplicate button/form/alert rules; fonts loaded twice | -| `@cfpb/design-system-react/index.css` | `@use '…/src/index'` in Sass | Same duplication | +| `@cfpb/design-system-react/index.css` | `@use '…/src/index'` in Sass | Same duplication | DSR React components work with either pattern — they emit standard DS classes. Pattern B apps rely on the app’s global DS stylesheet; Pattern A apps rely on the library’s `index.css`. ### Choosing a pattern -| Your situation | Use | -| --- | --- | -| New React app, Vite/CRA, mostly DSR components | **Pattern A** | -| Existing app with `dist/index.css` or `@use '…/src/index'` in global SCSS | **Pattern B** | -| App uses hand-rolled `.o-expandable`, `.m-list`, `.m-btn-group`, etc. | **Pattern B** (DSR barrel does not include every DS module) | -| Something looks unstyled on Pattern A | Add the DS file to [`ds-components.ts`](src/assets/styles/ds-components.ts) in DSR, or temporarily switch to Pattern B until the barrel is updated | +| Your situation | Use | +| ------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| New React app, Vite/CRA, mostly DSR components | **Pattern A** | +| Existing app with `dist/index.css` or `@use '…/src/index'` in global SCSS | **Pattern B** | +| App uses hand-rolled `.o-expandable`, `.m-list`, `.m-btn-group`, etc. | **Pattern B** (DSR barrel does not include every DS module) | +| Something looks unstyled on Pattern A | Add the DS file to [`ds-components.ts`](src/assets/styles/ds-components.ts) in DSR, or temporarily switch to Pattern B until the barrel is updated | ### What `ds-components.ts` covers today Styles bundled into `@cfpb/design-system-react/index.css` (Pattern A only): -| React area | DS stylesheet (under `@cfpb/cfpb-design-system/src/components/…`) | -| --- | --- | -| `Button` | `cfpb-buttons/button`, `cfpb-buttons/button-link` | -| `Heading` (`type="slug"`) | `cfpb-typography/slug-header` | -| `Pagination` | `cfpb-pagination/pagination` | +| React area | DS stylesheet (under `@cfpb/cfpb-design-system/src/components/…`) | +| -------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `Button` | `cfpb-buttons/button`, `cfpb-buttons/button-link` | +| `Heading` (`type="slug"`) | `cfpb-typography/slug-header` | +| `Pagination` | `cfpb-pagination/pagination` | | Forms (`TextInput`, `Checkbox`, `Select`, …) | `cfpb-forms/form`, `form-field`, `label`, `text-input`, `select`, `multiselect`, `form-alert` | -| `Alert` | `cfpb-notifications/notification` (+ DSR overrides in `alert.scss`) | -| `Table` | `cfpb-tables/table` | -| `Well`, `Divider` | `cfpb-layout/well`, `cfpb-layout/layout` | +| `Alert` | `cfpb-notifications/notification` (+ DSR overrides in `alert.scss`) | +| `Table` | `cfpb-tables/table` | +| `Well`, `Divider` | `cfpb-layout/well`, `cfpb-layout/layout` | Not in the barrel (Pattern B or future DSR work): expandables, lists, button groups, link typography, hero, cards, and other DS modules. Pattern B apps get these from full DS CSS automatically. @@ -187,25 +187,23 @@ Ensure `@cfpb/cfpb-design-system` and `lit` are installed even on Pattern A, so ### Storybook (contributors) -Storybook does **not** load prebuilt `dist/index.css`. It compiles the same source stack as Pattern A apps, wired in [`.storybook/preview.js`](.storybook/preview.js): +Storybook does **not** load prebuilt `dist/index.css`. It compiles the same source stack as Pattern A apps via [`src/assets/styles/entry-styles.ts`](src/assets/styles/entry-styles.ts), imported from [`.storybook/preview.js`](.storybook/preview.js): ```js -import '@fontsource-variable/source-sans-3'; -import '../src/assets/styles/_shared.scss'; -import '../src/assets/styles/ds-components'; +import '../src/assets/styles/entry-styles'; ``` -| Layer | Purpose | -| --- | --- | -| `@fontsource-variable/source-sans-3` | Registers `@font-face` in the preview bundle — required for nested “All viewports” iframes (each iframe is a separate document) | -| `_shared.scss` | DS tokens/normalize plus DSR overrides (font stack, `.wrapper--match-content`, docs-tab prose in `#storybook-docs`) | -| `ds-components.ts` | DS component rules that feed `dist/index.css` for npm consumers | +| Layer | File | Purpose | +| ------------------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | +| Fonts | `@fontsource-variable/source-sans-3` | Registers `@font-face` in the preview bundle — required for nested “All viewports” iframes (each iframe is a separate document) | +| Tokens + overrides | `_shared.scss` | DS tokens/normalize plus DSR overrides (font stack, `.wrapper--match-content`, docs-tab prose in `#storybook-docs`) | +| Component rules | `ds-components.ts` | DS styles bundled into `dist/index.css` for npm consumers | -Import **`ds-components` in `preview.js`**, not only via `~/src/index` in individual stories. Otherwise stories that import a component directly (for example `./checkbox`) may render without form/button/alert styles depending on load order. +When a component uses Design System class names (for example `.a-btn`, `.m-form-field`), add the matching DS SCSS import to [`ds-components.ts`](src/assets/styles/ds-components.ts). Do not import DS styles from individual component files — the barrel keeps the list in one place. -Stories may import from `~/src/index` or from a local component file — global styles come from `preview.js`. Per-component `.scss` files (for example `banner.scss`, `link.scss`) still load when that component is imported. +**Stories** should import components from their source files (for example `./button`, `../Link/link`), not from `~/src/index`. ESLint enforces this on `*.stories.*` (`no-restricted-imports`). **MDX** overview pages should follow the same rule (not linted — our ESLint setup does not parse MDX reliably). -Storybook-only extras (not in published `index.css`): [`.storybook/preview-head.html`](.storybook/preview-head.html) canvas padding and nested-iframe focus tweaks. +Per-component `.scss` files (for example `banner.scss`, `link.scss`) still load when that component is imported. Storybook-only canvas tweaks live in [`.storybook/preview-head.html`](.storybook/preview-head.html). ### Quick start (Pattern B — existing DS app) @@ -236,8 +234,6 @@ This project uses Yarn 4 with the `node-modules` linker (see `.yarnrc.yml`). Edit the files in `src/components/` and your browser should hot reload your changes. -When a component uses Design System class names (for example `.a-btn`, `.m-form-field`), add the matching DS SCSS import to [`src/assets/styles/ds-components.ts`](src/assets/styles/ds-components.ts). Do not import DS styles from individual component files — the barrel keeps the list in one place and feeds `dist/index.css` and Storybook (via `.storybook/preview.js`). See [Storybook (contributors)](#storybook-contributors) under [Styles](#styles). - Add tests to files called `.test.tsx`. See [`Buttons.test.tsx`](/src/components/Buttons/Button.test.tsx) for an example. Run `yarn test` to watch for changes and run tests automatically. diff --git a/eslint.config.js b/eslint.config.js index f897c1fa0b..b12a242925 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -10,6 +10,29 @@ import unicorn from 'eslint-plugin-unicorn'; import globals from 'globals'; import tseslint from 'typescript-eslint'; +/** Stories must not import the library barrel — see README “Storybook styles”. */ +const noLibraryBarrelInStories = { + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: '~/src/index', + message: + 'Import the component from its source file (e.g. ./button). Global styles load via .storybook/preview.js → entry-styles.ts.', + }, + ], + patterns: [ + { + group: ['~/src/index', '~/src/index.ts'], + message: + 'Import the component from its source file (e.g. ./button). Global styles load via .storybook/preview.js → entry-styles.ts.', + }, + ], + }, + ], +}; + export default tseslint.config( { ignores: [ @@ -97,4 +120,9 @@ export default tseslint.config( '@typescript-eslint/no-explicit-any': 'off', }, }, + // Stories: import components from source, not the library barrel (MDX: same convention; see README). + { + files: ['**/*.stories.ts?(x)'], + rules: noLibraryBarrelInStories, + }, ); diff --git a/src/assets/styles/_shared.scss b/src/assets/styles/_shared.scss index 43ebfe1027..48107c9acb 100644 --- a/src/assets/styles/_shared.scss +++ b/src/assets/styles/_shared.scss @@ -11,13 +11,10 @@ */ /** - * Source Sans 3 is loaded via `@fontsource-variable/source-sans-3` in **`src/index.ts`** (apps) - * and **`.storybook/preview.js`** (Storybook, including nested “All viewports” iframes) before - * this file so `@font-face` is always registered. - * - * DS component styles are in **`ds-components.ts`**, imported from **`src/index.ts`** and - * **`.storybook/preview.js`** alongside this file. - * + * Source Sans 3 and this file are loaded via **`entry-styles.ts`**, imported from + * **`src/index.ts`** and **`.storybook/preview.js`**, so `@font-face` is always registered + * (including nested “All viewports” Storybook iframes). + * DS component rules load from **`ds-components.ts`** via the same entry. * DS `custom-props` sets `--font-stack-branded: initial`, so `var(--font-stack)` falls back to * `system-ui`. Other DS chunks can repeat that `:root` block when code-split; in dev the last * chunk can win and wipe a non-`!important` override. Pin both tokens with `!important` so inputs, diff --git a/src/assets/styles/ds-components.ts b/src/assets/styles/ds-components.ts index ee13d05866..42939a4c3c 100644 --- a/src/assets/styles/ds-components.ts +++ b/src/assets/styles/ds-components.ts @@ -5,10 +5,13 @@ * SCSS import here (once per file — duplicates are unnecessary). Component * `.tsx` files should not import DS styles directly. * - * Styles listed here are bundled into `dist/index.css` and loaded in Storybook via - * `.storybook/preview.js` (alongside `_shared.scss` and Fontsource). + * Styles listed here are bundled into `dist/index.css` via `entry-styles.ts` and + * loaded in Storybook the same way. */ +// Icons — Icon (and any component with .cf-icon-svg) +import '@cfpb/cfpb-design-system/src/components/cfpb-icons/icon.scss'; + // Buttons — Button import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button.scss'; import '@cfpb/cfpb-design-system/src/components/cfpb-buttons/button-link.scss'; @@ -23,8 +26,9 @@ import '@cfpb/cfpb-design-system/src/components/cfpb-forms/text-input.scss'; import '@cfpb/cfpb-design-system/src/components/cfpb-forms/select.scss'; import '@cfpb/cfpb-design-system/src/components/cfpb-forms/multiselect.scss'; -// Typography — Heading (type="slug") +// Typography — Heading (type="slug"), Link import '@cfpb/cfpb-design-system/src/components/cfpb-typography/slug-header.scss'; +import '@cfpb/cfpb-design-system/src/components/cfpb-typography/link.scss'; // Layout — Divider (.content__line), Well import '@cfpb/cfpb-design-system/src/components/cfpb-layout/layout.scss'; diff --git a/src/assets/styles/entry-styles.ts b/src/assets/styles/entry-styles.ts new file mode 100644 index 0000000000..aa4888e68c --- /dev/null +++ b/src/assets/styles/entry-styles.ts @@ -0,0 +1,8 @@ +/** + * Global style entry for library consumers and Storybook. + * + * Imported from `src/index.ts` and `.storybook/preview.js`. Keep both in sync. + */ +import '@fontsource-variable/source-sans-3'; +import './_shared.scss'; +import './ds-components'; diff --git a/src/components/Alert/alert.stories.tsx b/src/components/Alert/alert.stories.tsx index d1f834ec37..4aa03e3819 100644 --- a/src/components/Alert/alert.stories.tsx +++ b/src/components/Alert/alert.stories.tsx @@ -1,6 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import type { ReactNode } from 'react'; -import { Alert, AlertFieldLevel, TextInput } from '~/src/index'; +import { Alert } from './alert'; +import { AlertFieldLevel } from './alert-field-level'; +import { TextInput } from '../TextInput/text-input'; const meta: Meta = { title: 'Components (Draft)/Alerts', diff --git a/src/components/Banner/banner.stories.tsx b/src/components/Banner/banner.stories.tsx index d1cd9fe011..49966bd433 100644 --- a/src/components/Banner/banner.stories.tsx +++ b/src/components/Banner/banner.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import type { ReactNode, SyntheticEvent } from 'react'; -import { Banner } from '~/src/index'; +import { Banner } from './banner'; import { AllLanguageCodes, LanguageLink } from './banner-language-link'; const meta: Meta = { diff --git a/src/components/Breadcrumb/breadcrumb.stories.tsx b/src/components/Breadcrumb/breadcrumb.stories.tsx index 699479cf91..3159901a16 100644 --- a/src/components/Breadcrumb/breadcrumb.stories.tsx +++ b/src/components/Breadcrumb/breadcrumb.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Breadcrumb } from '~/src/index'; +import { Breadcrumb } from './breadcrumb'; const meta: Meta = { title: 'Components (Draft)/Breadcrumbs', diff --git a/src/components/Buttons/buttons.stories.tsx b/src/components/Buttons/buttons.stories.tsx index 62e2cc842f..0097e526f4 100644 --- a/src/components/Buttons/buttons.stories.tsx +++ b/src/components/Buttons/buttons.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { expect, fn, userEvent, within } from 'storybook/test'; -import { Button, Link } from '~/src/index'; +import { Button } from './button'; +import Link from '../Link/link'; import { ButtonGroup } from './button-group'; /** diff --git a/src/components/Checkbox/checkbox-overview.mdx b/src/components/Checkbox/checkbox-overview.mdx index 618257cbe9..f18c157b68 100644 --- a/src/components/Checkbox/checkbox-overview.mdx +++ b/src/components/Checkbox/checkbox-overview.mdx @@ -1,6 +1,9 @@ {/* NOTE: Do NOT use auto-formatting on this MDX's. Otherwise MDX creates extra

elements per line */} import { Meta } from '@storybook/addon-docs/blocks'; -import { List, Link, ListLink, Heading, Paragraph } from '~/src/index'; +import { Heading } from '../Headings/heading'; +import Link, { ListLink } from '../Link/link'; +import List from '../List/list'; +import { Paragraph } from '../Paragraph/paragraph'; diff --git a/src/components/Divider/divider.stories.tsx b/src/components/Divider/divider.stories.tsx index 2131227d19..1c6f2a0739 100644 --- a/src/components/Divider/divider.stories.tsx +++ b/src/components/Divider/divider.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Divider } from '~/src/index'; +import { Divider } from './divider'; const meta: Meta = { title: 'Components (Draft)/Dividers', diff --git a/src/components/Expandable/expandable.stories.tsx b/src/components/Expandable/expandable.stories.tsx index 7f324f06ea..c5d103b7a4 100644 --- a/src/components/Expandable/expandable.stories.tsx +++ b/src/components/Expandable/expandable.stories.tsx @@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import type { ComponentProps } from 'react'; import { JSX } from 'react'; import { expect, userEvent, waitFor, within } from 'storybook/test'; -import { Expandable } from '~/src/index'; +import { Expandable } from './expandable'; import { sleep } from '../../utils/sleep'; // This is the expandable group diff --git a/src/components/Fieldset/fieldset.stories.tsx b/src/components/Fieldset/fieldset.stories.tsx index 87ecf52e36..ba580ae81a 100644 --- a/src/components/Fieldset/fieldset.stories.tsx +++ b/src/components/Fieldset/fieldset.stories.tsx @@ -1,6 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { expect, userEvent, waitFor, within } from 'storybook/test'; -import { Checkbox, Fieldset, RadioButton } from '~/src/index'; +import { Checkbox } from '../Checkbox/checkbox'; +import { Fieldset } from './fieldset'; +import { RadioButton } from '../RadioButton/radio-button'; /** * diff --git a/src/components/Grid/grid.stories.tsx b/src/components/Grid/grid.stories.tsx index 5bc7f63e1a..03b14d0f7a 100644 --- a/src/components/Grid/grid.stories.tsx +++ b/src/components/Grid/grid.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Grid } from '~/src/index'; +import Grid from './index'; const meta: Meta = { title: 'Components (Draft)/Grids', diff --git a/src/components/Header/header.stories.tsx b/src/components/Header/header.stories.tsx index 717432e302..746f1de955 100644 --- a/src/components/Header/header.stories.tsx +++ b/src/components/Header/header.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Header } from '~/src/index'; +import { Header } from './header'; import { ExampleLinks } from './responsive-menu'; const meta: Meta = { diff --git a/src/components/Header/responsive-menu.scss b/src/components/Header/responsive-menu.scss index 0814864f38..c6d574d2c0 100644 --- a/src/components/Header/responsive-menu.scss +++ b/src/components/Header/responsive-menu.scss @@ -154,6 +154,7 @@ $max-width: $bp-sm-max; margin-right: 0; padding: 10px 0; text-align: left; + // no underline when in menu .a-link__text { text-decoration: none; diff --git a/src/components/Headings/headings.stories.tsx b/src/components/Headings/headings.stories.tsx index 912a51abe6..a25ae983c4 100644 --- a/src/components/Headings/headings.stories.tsx +++ b/src/components/Headings/headings.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Heading } from '~/src/index'; +import { Heading } from './heading'; import { expect, within } from 'storybook/test'; /** * A successful type hierarchy establishes the order of importance of elements on a page. Consistent scaling, weights, and capitalization are used to create distinction between headings and provide users with familiar focus points when scanning text. diff --git a/src/components/Hero/hero.stories.tsx b/src/components/Hero/hero.stories.tsx index 3d7b235357..73d0df48ac 100644 --- a/src/components/Hero/hero.stories.tsx +++ b/src/components/Hero/hero.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Hero } from '~/src/index'; +import Hero from './hero'; const meta: Meta = { title: 'Components (Draft)/Heroes', diff --git a/src/components/Icon/icon.stories.tsx b/src/components/Icon/icon.stories.tsx index bf13d4829d..edc6985cda 100644 --- a/src/components/Icon/icon.stories.tsx +++ b/src/components/Icon/icon.stories.tsx @@ -1,7 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { JSX } from 'react'; import type { ReactElement } from 'react'; -import { Heading, Icon } from '~/src/index'; +import { Heading } from '../Headings/heading'; +import { Icon } from './icon'; import type { HeadingType } from '../Headings/heading'; import { communicationIcons, diff --git a/src/components/Label/label.stories.tsx b/src/components/Label/label.stories.tsx index f24f2d8799..0b4eada1d8 100644 --- a/src/components/Label/label.stories.tsx +++ b/src/components/Label/label.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Label } from '~/src/index'; +import { Label } from './label'; import { TextInput } from '../TextInput/text-input'; const meta: Meta = { diff --git a/src/components/Layout/layout-content.stories.tsx b/src/components/Layout/layout-content.stories.tsx index 48f42abed0..7220485dc2 100644 --- a/src/components/Layout/layout-content.stories.tsx +++ b/src/components/Layout/layout-content.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Layout } from '~/src/index'; +import Layout from './layout'; const meta: Meta = { title: 'Components (Draft)/Layout/Content', diff --git a/src/components/Layout/layout-main.stories.tsx b/src/components/Layout/layout-main.stories.tsx index b570597409..9846db3172 100644 --- a/src/components/Layout/layout-main.stories.tsx +++ b/src/components/Layout/layout-main.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Layout } from '~/src/index'; +import Layout from './layout'; const meta: Meta = { title: 'Components (Draft)/Layout/Main', diff --git a/src/components/Layout/layout-sidebar.stories.tsx b/src/components/Layout/layout-sidebar.stories.tsx index c17026ab43..4c1474be70 100644 --- a/src/components/Layout/layout-sidebar.stories.tsx +++ b/src/components/Layout/layout-sidebar.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Layout } from '~/src/index'; +import Layout from './layout'; const meta: Meta = { title: 'Components (Draft)/Layout/Sidebar', diff --git a/src/components/Layout/layout-wrapper.stories.tsx b/src/components/Layout/layout-wrapper.stories.tsx index bfbd58278d..a16357aa30 100644 --- a/src/components/Layout/layout-wrapper.stories.tsx +++ b/src/components/Layout/layout-wrapper.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Layout } from '~/src/index'; +import Layout from './layout'; const meta: Meta = { title: 'Components (Draft)/Layout/Wrapper', diff --git a/src/components/Link/link.stories.tsx b/src/components/Link/link.stories.tsx index f819e26ac6..8a1b56bffe 100644 --- a/src/components/Link/link.stories.tsx +++ b/src/components/Link/link.stories.tsx @@ -1,7 +1,9 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { BrowserRouter } from 'react-router'; import { expect, within } from 'storybook/test'; -import { Heading, Link, List, ListLink } from '~/src/index'; +import { Heading } from '../Headings/heading'; +import Link, { ListLink } from './link'; +import List from '../List/list'; const meta: Meta = { title: 'Components (Verified)/Links', diff --git a/src/components/List/list.stories.tsx b/src/components/List/list.stories.tsx index 4dbeaee49a..334335a763 100644 --- a/src/components/List/list.stories.tsx +++ b/src/components/List/list.stories.tsx @@ -1,5 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Link, List, ListItem } from '~/src/index'; +import Link from '../Link/link'; +import List from './list'; +import ListItem from './list-item'; const meta: Meta = { title: 'Components (Draft)/Lists', diff --git a/src/components/Pagination/pagination.stories.tsx b/src/components/Pagination/pagination.stories.tsx index 6cec95faa9..4938e23d40 100644 --- a/src/components/Pagination/pagination.stories.tsx +++ b/src/components/Pagination/pagination.stories.tsx @@ -1,7 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { JSX } from 'react'; import { expect, fn, userEvent, within } from 'storybook/test'; -import { Pagination, usePagination } from '~/src/index'; +import { Pagination } from './pagination'; +import { usePagination } from './use-pagination'; import { generateTestRows, stringify } from './pagination.story-utils'; const meta: Meta = { diff --git a/src/components/RadioButton/radio-button.stories.tsx b/src/components/RadioButton/radio-button.stories.tsx index d7f83ec6a4..2f0c13ff33 100644 --- a/src/components/RadioButton/radio-button.stories.tsx +++ b/src/components/RadioButton/radio-button.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { expect, userEvent, waitFor, within } from 'storybook/test'; -import { RadioButton } from '~/src/index'; +import { RadioButton } from './radio-button'; /** * Use radio buttons when the user can select exactly one option from a group. Avoid long lists of radio buttons (usually no more than 6-8 options). When there are more than two options, stack radio buttons vertically. Use [checkboxes](https://cfpb.github.io/design-system/components/checkboxes) when the user can select more than one option from a group. diff --git a/src/components/Select/select-multi.stories.tsx b/src/components/Select/select-multi.stories.tsx index 22eafa39c4..ecce1cdb12 100644 --- a/src/components/Select/select-multi.stories.tsx +++ b/src/components/Select/select-multi.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Select } from '~/src/index'; +import Select from './select'; import { MultipleSelectOptions } from './test-utils'; const meta: Meta = { diff --git a/src/components/Select/select-overview.mdx b/src/components/Select/select-overview.mdx index 6c4006c470..23235f95f4 100644 --- a/src/components/Select/select-overview.mdx +++ b/src/components/Select/select-overview.mdx @@ -1,5 +1,8 @@ import { Meta } from '@storybook/addon-docs/blocks'; -import { Heading, Link, List, ListLink, Paragraph } from '~/src/index'; +import { Heading } from '../Headings/heading'; +import Link, { ListLink } from '../Link/link'; +import List from '../List/list'; +import { Paragraph } from '../Paragraph/paragraph'; diff --git a/src/components/Select/select.stories.tsx b/src/components/Select/select.stories.tsx index 9abdde407b..ac3104bcf4 100644 --- a/src/components/Select/select.stories.tsx +++ b/src/components/Select/select.stories.tsx @@ -1,6 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { JSX, useState } from 'react'; -import { Select, SelectSingle } from '~/src/index'; +import Select from './select'; +import { SelectSingle } from './select-single'; import type { SelectOption, SelectProperties } from './select'; import { SingleSelectOptions } from './test-utils'; diff --git a/src/components/Table/table.stories.tsx b/src/components/Table/table.stories.tsx index ed74c26905..679a52ec85 100644 --- a/src/components/Table/table.stories.tsx +++ b/src/components/Table/table.stories.tsx @@ -1,5 +1,5 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { Table } from '~/src/index'; +import { Table } from './table'; import { ONE } from '../Pagination/use-pagination'; const meta: Meta = { diff --git a/src/components/TextInput/text-input-overview.mdx b/src/components/TextInput/text-input-overview.mdx index edee6a094d..32f27a9684 100644 --- a/src/components/TextInput/text-input-overview.mdx +++ b/src/components/TextInput/text-input-overview.mdx @@ -1,5 +1,8 @@ import { Meta } from '@storybook/addon-docs/blocks'; -import { List, Link, ListLink, Heading, Paragraph } from '~/src/index'; +import { Heading } from '../Headings/heading'; +import Link, { ListLink } from '../Link/link'; +import List from '../List/list'; +import { Paragraph } from '../Paragraph/paragraph'; Text inputs diff --git a/src/components/TextInput/text-input.stories.tsx b/src/components/TextInput/text-input.stories.tsx index 8c9b56e988..6d71e2fee5 100644 --- a/src/components/TextInput/text-input.stories.tsx +++ b/src/components/TextInput/text-input.stories.tsx @@ -1,7 +1,9 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { useState } from 'react'; import { expect, userEvent, within } from 'storybook/test'; -import { Button, Icon, TextInput } from '~/src/index'; +import { Button } from '../Buttons/button'; +import { Icon } from '../Icon/icon'; +import { TextInput } from './text-input'; import type { TextInputProperties } from './text-input'; const meta: Meta = { diff --git a/src/components/TextIntroduction/text-introduction.stories.tsx b/src/components/TextIntroduction/text-introduction.stories.tsx index ad6e996101..3d48cf95b5 100644 --- a/src/components/TextIntroduction/text-introduction.stories.tsx +++ b/src/components/TextIntroduction/text-introduction.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; -import { List, TextIntroduction } from '~/src/index'; +import List from '../List/list'; +import TextIntroduction from './text-introduction'; import { callToAction, description, diff --git a/src/index.ts b/src/index.ts index 8d2cb0cc09..9bf5efb15b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ -import '@fontsource-variable/source-sans-3'; -import './assets/styles/_shared.scss'; -import './assets/styles/ds-components'; +import './assets/styles/entry-styles'; export { Alert } from './components/Alert/alert'; export { AlertFieldLevel } from './components/Alert/alert-field-level'; diff --git a/src/stories/Introduction.mdx b/src/stories/Introduction.mdx index 74b43bb85e..c6ac648243 100644 --- a/src/stories/Introduction.mdx +++ b/src/stories/Introduction.mdx @@ -1,5 +1,6 @@ import { Meta } from '@storybook/addon-docs/blocks'; -import { Icon, Heading } from '~/src/index'; +import { Icon } from '../components/Icon/icon'; +import { Heading } from '../components/Headings/heading'; import Code from './assets/code-brackets.svg'; import Colors from './assets/colors.svg'; import Comments from './assets/comments.svg';