From da628642cfe439b7a6b8f5560e6647948c1748b0 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Jun 2026 11:40:57 -0500 Subject: [PATCH 1/7] docs: add initial modular design system draft --- contributor-docs/adrs/adr-024-modular-ds.md | 56 +++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 contributor-docs/adrs/adr-024-modular-ds.md diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md new file mode 100644 index 00000000000..1c38c2fd3ef --- /dev/null +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -0,0 +1,56 @@ +# Modular Design System + +📆 Date: 2026-05-17 + +## Status + +| Stage | State | +| -------------- | ----------- | +| Status | Proposed ⚠️ | +| Implementation | Pending ⚠️ | + +## Context + +There is a proposal for enabling better pattern creation via modular building +blocks in: https://github.com/github/core-ux/issues/2238. In this proposal, it +details several layers that Primer could be structured into: + +- Layer 3: Ready-made, props-based components that are ready to use +- Layer 2: Parts, presentiontational-style components that one combines with hooks to + create components +- Layer 1: Foundations, unstyled primitives to allow for full markup and style + control +- Layer 0: Hooks, state management, and other logic that can be used to build components + +We took this proposal into a Modular design System Workshop: +https://github.com/github/primer/discussions/6703. In this workshop, we +identified several scenarios that team run into challenges when building with +Primer: + +- It can be difficult to extend or add new functionality to a component +- It can be difficult to customize the appearance, content, or semantics of a + component +- It can be difficult to build new experiences using established patterns (like accessibility primitives) + +These challenges lead to custom implementations, forks, or overrides of Primer +components that reuslt in adoption challenges and ecosystem fragmentation. + +As a result, we applied the layer model to several situations in a +[FigJam](https://www.figma.com/board/mgApQG7vL3imdUIhgyhG2n/Modular-DS-Workshop?node-id=84-152&t=dBKm8jx1UsKRXyzu-1). From this work, we pulled out insights about this model that we want to adopt in Primer today. + +## Decision + +From the Modular Design System workshop, we identified several key areas that we +want to focus on in order to improve Primer: + +- Embrace layer 2 from the layer model, offering parts for our components that + can be combined with hooks for improved flexibility +- Provide low-level components and hooks to make it easier to build + quality, accessible experience +- Create a model for upstreaming work where people build on top of Primer + +### Embracing layer 2 + +### Low-level components and hooks + +### Model for upstreaming work From 8a3230fe2c7d7cda78c12a5f206fad1db7b85578 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Jun 2026 11:56:22 -0500 Subject: [PATCH 2/7] docs: add initial support tables --- contributor-docs/adrs/adr-024-modular-ds.md | 119 ++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index 1c38c2fd3ef..e2540a2f05c 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -51,6 +51,125 @@ want to focus on in order to improve Primer: ### Embracing layer 2 +| Entrypoint | Component | Props | Parts | Hooks | Notes | +| :------------- | :------------------ | :---- | :---- | :---- | :---- | +| . | ActionBar | | | | | +| | ActionList | | | | | +| | ActionMenu | | | | | +| | AnchoredOverlay | | | | | +| | Autocomplete | | | | | +| | Avatar | | | | | +| | AvatarStack | | | | | +| | Banner | | | | | +| | BaseStyles | | | | | +| | BranchName | | | | | +| | Breadcrumb | | | | | +| | Breadcrumbs | | | | | +| | Button | | | | | +| | ButtonGroup | | | | | +| | Checkbox | | | | | +| | CheckboxGroup | | | | | +| | CircleBadge | | | | | +| | ConfirmationDialog | | | | | +| | CounterLabel | | | | | +| | Details | | | | | +| | Dialog | | | | | +| | Flash | | | | | +| | FocusKeys | | | | | +| | FormControl | | | | | +| | Header | | | | | +| | Heading | | | | | +| | IconButton | | | | | +| | IssueLabelToken | | | | | +| | Label | | | | | +| | LabelGroup | | | | | +| | Link | | | | | +| | LinkButton | | | | | +| | NavList | | | | | +| | Overlay | | | | | +| | PageHeader | | | | | +| | PageLayout | | | | | +| | Pagination | | | | | +| | Popover | | | | | +| | Portal | | | | | +| | PortalContext | | | | | +| | ProgressBar | | | | | +| | Radio | | | | | +| | RadioGroup | | | | | +| | RelativeTime | | | | | +| | ResponsiveValue | | | | | +| | SegmentedControl | | | | | +| | Select | | | | | +| | SelectPanel | | | | | +| | SideNav | | | | | +| | SkeletonBox | | | | | +| | Spinner | | | | | +| | SplitPageLayout | | | | | +| | Stack | | | | | +| | StateLabel | | | | | +| | SubNav | | | | | +| | Text | | | | | +| | Textarea | | | | | +| | TextInput | | | | | +| | TextInputWithTokens | | | | | +| | ThemeProvider | | | | | +| | Timeline | | | | | +| | ToggleSwitch | | | | | +| | Token | | | | | +| | Tooltip | | | | | +| | TreeView | | | | | +| | Truncate | | | | | +| | UnderlineNav | | | | | +| | VisuallyHidden | | | | | +| ./experimental | ActionBar | | | | | +| | Announce | | | | | +| | AriaAlert | | | | | +| | AriaStatus | | | | | +| | Blankslate | | | | | +| | Card | | | | | +| | DataTable | | | | | +| | Dialog | | | | | +| | FilteredActionList | | | | | +| | Hidden | | | | | +| | InlineMessage | | | | | +| | IssueLabel | | | | | +| | KeybindingHint | | | | | +| | NavList | | | | | +| | PageHeader | | | | | +| | ScrollableRegion | | | | | +| | SelectPanel | | | | | +| | SkeletonAvatar | | | | | +| | SkeletonText | | | | | +| | Stack | | | | | +| | Table | | | | | +| | Tabs | | | | | +| | Tooltip | | | | | +| | TopicTag | | | | | +| | UnderlinePanels | | | | | + ### Low-level components and hooks +We want to offer more low-level components and hooks, in particular with a focus +on accessibility. Providing these low-level abstractions allows for quickly creating +robust experiences instead of having to re-invent them from scratch. + +In particular, we would like to offer the following primitives: + +| Type | Name | Supported | Description | Notes | +| :--------- | :---------------- | :-------- | :---------- | :---- | +| Components | Accordion | | | | +| | Combobox | | | | +| | Disclosure | | | | +| | Dialog | | | | +| | Listbox | | | | +| | Menu | | | | +| | Menubar | | | | +| | Popover | | | | +| | Tabs | | | | +| | Tree | | | | +| Hooks | useFocusTrap | | | | +| | useMergedRefs | | | | +| | useRovingTabIndex | | | | +| | useTabs | | | | + ### Model for upstreaming work From ef931ea5b39fb08bed9495ba60a07d2047465e16 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Wed, 17 Jun 2026 12:11:20 -0500 Subject: [PATCH 3/7] docs: begin filling out tables --- contributor-docs/adrs/adr-024-modular-ds.md | 308 +++++++++++++------- 1 file changed, 197 insertions(+), 111 deletions(-) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index e2540a2f05c..0039f4dfaab 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -49,103 +49,112 @@ want to focus on in order to improve Primer: quality, accessible experience - Create a model for upstreaming work where people build on top of Primer +In addition, when authoring components we will offer presentational components +and behavioral hooks that can then be used for higher-level, props-based +components. + ### Embracing layer 2 -| Entrypoint | Component | Props | Parts | Hooks | Notes | -| :------------- | :------------------ | :---- | :---- | :---- | :---- | -| . | ActionBar | | | | | -| | ActionList | | | | | -| | ActionMenu | | | | | -| | AnchoredOverlay | | | | | -| | Autocomplete | | | | | -| | Avatar | | | | | -| | AvatarStack | | | | | -| | Banner | | | | | -| | BaseStyles | | | | | -| | BranchName | | | | | -| | Breadcrumb | | | | | -| | Breadcrumbs | | | | | -| | Button | | | | | -| | ButtonGroup | | | | | -| | Checkbox | | | | | -| | CheckboxGroup | | | | | -| | CircleBadge | | | | | -| | ConfirmationDialog | | | | | -| | CounterLabel | | | | | -| | Details | | | | | -| | Dialog | | | | | -| | Flash | | | | | -| | FocusKeys | | | | | -| | FormControl | | | | | -| | Header | | | | | -| | Heading | | | | | -| | IconButton | | | | | -| | IssueLabelToken | | | | | -| | Label | | | | | -| | LabelGroup | | | | | -| | Link | | | | | -| | LinkButton | | | | | -| | NavList | | | | | -| | Overlay | | | | | -| | PageHeader | | | | | -| | PageLayout | | | | | -| | Pagination | | | | | -| | Popover | | | | | -| | Portal | | | | | -| | PortalContext | | | | | -| | ProgressBar | | | | | -| | Radio | | | | | -| | RadioGroup | | | | | -| | RelativeTime | | | | | -| | ResponsiveValue | | | | | -| | SegmentedControl | | | | | -| | Select | | | | | -| | SelectPanel | | | | | -| | SideNav | | | | | -| | SkeletonBox | | | | | -| | Spinner | | | | | -| | SplitPageLayout | | | | | -| | Stack | | | | | -| | StateLabel | | | | | -| | SubNav | | | | | -| | Text | | | | | -| | Textarea | | | | | -| | TextInput | | | | | -| | TextInputWithTokens | | | | | -| | ThemeProvider | | | | | -| | Timeline | | | | | -| | ToggleSwitch | | | | | -| | Token | | | | | -| | Tooltip | | | | | -| | TreeView | | | | | -| | Truncate | | | | | -| | UnderlineNav | | | | | -| | VisuallyHidden | | | | | -| ./experimental | ActionBar | | | | | -| | Announce | | | | | -| | AriaAlert | | | | | -| | AriaStatus | | | | | -| | Blankslate | | | | | -| | Card | | | | | -| | DataTable | | | | | -| | Dialog | | | | | -| | FilteredActionList | | | | | -| | Hidden | | | | | -| | InlineMessage | | | | | -| | IssueLabel | | | | | -| | KeybindingHint | | | | | -| | NavList | | | | | -| | PageHeader | | | | | -| | ScrollableRegion | | | | | -| | SelectPanel | | | | | -| | SkeletonAvatar | | | | | -| | SkeletonText | | | | | -| | Stack | | | | | -| | Table | | | | | -| | Tabs | | | | | -| | Tooltip | | | | | -| | TopicTag | | | | | -| | UnderlinePanels | | | | | +- Parts provide a clear way for teams to layer on functionality that does not + exist +- It provides a clear path for upstreaming +- The biggest gap is providing behavioral/state hooks for components (if needed) + +`N/A` means that layer is not a useful fit for the component's API shape. + +| Entrypoint | Component | Props | Parts | Hooks | Notes | +| :------------- | :------------------ | :---- | :---- | :---- | :---------------------------------------------------------------------------------------------------------------- | +| . | ActionBar | N/A | Yes | No | Parts include `IconButton`, `Divider`, `Group`, and `Menu`; no public ActionBar behavior hook. | +| | ActionList | N/A | Yes | No | Compound list API with item, group, divider, visual, description, and action parts. | +| | ActionMenu | No | Yes | No | Parts include `Button`, `Anchor`, `Overlay`, and `Divider`; menu contents use `ActionList`. | +| | AnchoredOverlay | Yes | N/A | Yes | Props-driven overlay; behavior can be recreated with `useAnchoredPosition` and `useOverlay`. | +| | Autocomplete | No | Yes | No | Slot API exposes `Input`, `Menu`, and `Overlay`; no public autocomplete hook. | +| | Avatar | Yes | N/A | N/A | Leaf visual component. | +| | AvatarStack | Yes | N/A | No | Props-driven wrapper around `Avatar` children; no public stack behavior hook. | +| | Banner | Yes | Yes | N/A | Supports title, description, and action props plus matching parts. | +| | BaseStyles | Yes | N/A | N/A | Props-driven application wrapper. | +| | BranchName | Yes | N/A | N/A | Leaf display component. | +| | Breadcrumb | N/A | Yes | N/A | Deprecated alias of `Breadcrumbs` with `Item`. | +| | Breadcrumbs | N/A | Yes | N/A | Uses `Breadcrumbs.Item`; no props-only item list API. | +| | Button | Yes | N/A | N/A | Leaf action component. | +| | ButtonGroup | Yes | N/A | N/A | Props-driven grouping wrapper for button children. | +| | Checkbox | Yes | N/A | N/A | Native input wrapper. | +| | CheckboxGroup | N/A | Yes | No | Uses label, caption, and validation parts through the shared choice-group implementation. | +| | ConfirmationDialog | Yes | N/A | Yes | Props-driven dialog with `useConfirm` behavior hook. | +| | CounterLabel | Yes | N/A | N/A | Leaf count display component. | +| | Details | N/A | Yes | Yes | Exposes `Summary` plus `useDetails`. | +| | Dialog | Yes | Yes | No | Props-driven dialog also exposes parts for custom renderers; `useDialog` is internal. | +| | Flash | Yes | N/A | N/A | Props-driven message component. | +| | FocusKeys | N/A | N/A | Yes | Not a component; exported behavior constant used with `useFocusZone`. | +| | FormControl | N/A | Yes | Yes | Parts include `Label`, `Caption`, `LeadingVisual`, and `Validation`; hook forwards form-control props. | +| | Header | N/A | Yes | N/A | Structural API exposes `Item` and `Link`. | +| | Heading | Yes | N/A | N/A | Leaf typography component. | +| | IconButton | Yes | N/A | N/A | Leaf action component. | +| | IssueLabelToken | Yes | N/A | N/A | Props-driven token variant. | +| | Label | Yes | N/A | N/A | Leaf display component. | +| | LabelGroup | Yes | N/A | N/A | Props-driven grouping wrapper for labels. | +| | Link | Yes | N/A | N/A | Leaf navigation component. | +| | LinkButton | Yes | N/A | N/A | Leaf action/navigation component. | +| | NavList | N/A | Yes | No | Compound navigation API with item, group, visual, divider, and subnav parts. | +| | Overlay | Yes | N/A | Yes | Props-driven floating surface backed by `useOverlay`. | +| | PageHeader | N/A | Yes | N/A | Structural API exposes title, context, action, visual, description, and navigation parts. | +| | PageLayout | N/A | Yes | No | Layout parts include `Header`, `Content`, `Pane`, `Sidebar`, and `Footer`; no public layout hook. | +| | Pagination | Yes | N/A | No | Props-driven pagination model; no public pagination hook. | +| | Popover | Yes | Yes | N/A | Props-driven wrapper with `Content` part. | +| | Portal | Yes | N/A | N/A | Low-level rendering utility. | +| | PortalContext | N/A | N/A | N/A | Context export rather than a component API. | +| | ProgressBar | Yes | Yes | N/A | Props-driven bar with `Item` for segmented progress. | +| | Radio | Yes | N/A | N/A | Native input wrapper. | +| | RadioGroup | N/A | Yes | No | Uses label, caption, and validation parts through the shared choice-group implementation. | +| | RelativeTime | Yes | N/A | N/A | Props-driven time display. | +| | ResponsiveValue | N/A | N/A | Yes | Type-level API paired with `useResponsiveValue`. | +| | SegmentedControl | N/A | Yes | No | Compound control with `Button` and `IconButton` parts; no public segmented-control hook. | +| | Select | Yes | Yes | N/A | Native select wrapper with `Option` and `OptGroup` parts. | +| | SelectPanel | Yes | Yes | No | Props-driven selection panel; parts cover messages and secondary actions, not the full behavior. | +| | SideNav | N/A | Yes | N/A | Deprecated structural nav with `Link` part. | +| | SkeletonBox | Yes | N/A | N/A | Leaf skeleton component. | +| | Spinner | Yes | N/A | N/A | Leaf loading component. | +| | SplitPageLayout | N/A | Yes | No | Layout parts mirror `PageLayout`; no public layout hook. | +| | Stack | Yes | Yes | N/A | Props-driven layout primitive with optional `Item` part. | +| | StateLabel | Yes | N/A | N/A | Leaf display component. | +| | SubNav | N/A | Yes | N/A | Structural nav with `Link` and `Links` parts. | +| | Text | Yes | N/A | N/A | Leaf typography component. | +| | Textarea | Yes | N/A | N/A | Native input wrapper. | +| | TextInput | Yes | Yes | N/A | Props-driven input with `Action` as an optional part. | +| | TextInputWithTokens | Yes | N/A | No | Props-driven tokenized input; no public token-input behavior hook. | +| | ThemeProvider | Yes | N/A | Yes | Provider component plus `useTheme` and `useColorSchemeVar`. | +| | Timeline | N/A | Yes | N/A | Structural timeline with item, avatar, badge, body, break, and action parts. | +| | ToggleSwitch | Yes | N/A | N/A | Props-driven switch component. | +| | Token | Yes | N/A | N/A | Leaf token component. | +| | Tooltip | Yes | N/A | No | Props-driven tooltip; no public tooltip behavior hook. | +| | TreeView | N/A | Yes | Yes | Compound tree API with item/subtree/visual parts and `useRovingTabIndex`. | +| | Truncate | Yes | N/A | N/A | Props-driven text utility. | +| | UnderlineNav | N/A | Yes | N/A | Structural nav with `Item` part. | +| | VisuallyHidden | Yes | N/A | N/A | Leaf accessibility utility. | +| ./experimental | Announce | Yes | N/A | N/A | Props-driven live-region primitive; no public announcement hook (available through `@primer/live-region-element` | +| | AriaAlert | Yes | N/A | N/A | Props-driven assertive live-region wrapper. | +| | AriaStatus | Yes | N/A | N/A | Props-driven polite live-region wrapper. | +| | Blankslate | N/A | Yes | N/A | Parts-first API with visual, heading, description, and action parts. | +| | Card | N/A | Yes | N/A | Parts-first card with icon, image, heading, description, action, and metadata parts. | +| | DataTable | Yes | Yes | Yes | Props-driven data grid; presentational table parts are exposed through `Table`. Hook is `useTable` | +| | Dialog | Yes | Yes | No | Same public API shape as the root export. | +| | FilteredActionList | Yes | Yes | No | Props-driven filtered list with `Input` and `BodyLoader` parts. | +| | Hidden | N/A | Yes | N/A | Props-driven responsive visibility utility. | +| | InlineMessage | N/A | Yes | N/A | Leaf message component. | +| | IssueLabel | N/A | Yes | N/A | Props-driven issue label component. | +| | KeybindingHint | Yes | N/A | N/A | Props-driven text utility for keybindings. | +| | NavList | N/A | Yes | No | Same public API shape as the root export. | +| | PageHeader | N/A | Yes | N/A | Same public API shape as the root export. | +| | ScrollableRegion | Yes | N/A | N/A | Props-driven accessibility wrapper. | +| | SelectPanel | N/A | Yes | No | Experimental parts-first panel with button, header, search, footer, loading, message, and secondary action parts. | +| | SkeletonAvatar | Yes | N/A | N/A | Leaf skeleton component. | +| | SkeletonText | Yes | N/A | N/A | Leaf skeleton component. | +| | Stack | Yes | Yes | N/A | Same public API shape as the root export. | +| | Table | N/A | Yes | N/A | Presentational table parts for `DataTable`. | +| | Tabs | N/A | Yes | Yes | Experimental primitive exposes `TabList`, `Tab`, `TabPanel`, and related hooks. | +| | Tooltip | Yes | N/A | No | Same public API shape as the root export. | +| | TopicTag | Yes | Yes | N/A | Props-driven tag with `Group` part. | +| | UnderlinePanels | N/A | Yes | No | Parts-first tab panel API with `Tab` and `Panel`; no public hook. | ### Low-level components and hooks @@ -155,21 +164,98 @@ robust experiences instead of having to re-invent them from scratch. In particular, we would like to offer the following primitives: -| Type | Name | Supported | Description | Notes | -| :--------- | :---------------- | :-------- | :---------- | :---- | -| Components | Accordion | | | | -| | Combobox | | | | -| | Disclosure | | | | -| | Dialog | | | | -| | Listbox | | | | -| | Menu | | | | -| | Menubar | | | | -| | Popover | | | | -| | Tabs | | | | -| | Tree | | | | -| Hooks | useFocusTrap | | | | -| | useMergedRefs | | | | -| | useRovingTabIndex | | | | -| | useTabs | | | | +| Type | Name | Supported | Description | Notes | +| :--------- | :---------------- | :-------- | :----------------------------------------- | :-------------------------------------------------------------------------------------------------- | +| Components | Accordion | No | Disclosure group primitive. | Not exposed today. | +| | Combobox | No | Text input plus listbox popup primitive. | Autocomplete and SelectPanel cover product use cases, but no generic combobox primitive is exposed. | +| | Disclosure | No | Show/hide primitive. | `Details` and `useDetails` exist, but there is no named `Disclosure` primitive. | +| | Dialog | Yes | Modal dialog primitive. | `Dialog` exposes props and custom-renderer parts. | +| | Listbox | No | Option list primitive. | ActionList and SelectPanel cover product use cases, but no generic listbox primitive is exposed. | +| | Menu | No | Menu button and popup primitive. | ActionMenu covers product use cases, but no generic menu primitive is exposed. | +| | Menubar | No | Horizontal menu primitive. | Not exposed today. | +| | Popover | Yes | Anchored floating content primitive. | Covered by `Popover`, `Overlay`, and `AnchoredOverlay`. | +| | Tabs | Yes | Tab state and tab/panel primitive. | Available from `./experimental` with parts and hooks. | +| | Tree | Yes | Tree navigation primitive. | Covered by `TreeView`; no separate unstyled `Tree` primitive is exposed. | +| Hooks | useFocusTrap | Yes | Trap focus within a container. | Exported from the root entrypoint. | +| | useMergedRefs | Yes | Merge multiple refs into one ref callback. | Exported from the root entrypoint. | +| | useRovingTabIndex | Yes | Manage roving tab index behavior. | Exported from the root entrypoint via `TreeView`. | +| | useTabs | Yes | Manage tab state and ARIA wiring. | Available from `./experimental` alongside `useTab`, `useTabList`, and `useTabPanel`. | ### Model for upstreaming work + +### Authoring components + +#### Config components + +These components are "all-in-one"; they provide a high level of abstraction that +support common use-cases making it simple to quickly build out established +patterns and experiences. However, they are often inflexible and difficult to +extend. + +````tsx + { + /* ... */ + }} + onFilter={query => { + /* ... */ + }} +/> + +#### Presentational components + +These components provide a lower level of abstraction and are more flexible and extensible, but require more work to build out common patterns and experiences. + +```tsx +function Example({items}) { + const [state, actions] = useList({ + defaultSelected: [], + }) + + return ( + + { + actions.updateQuery(query) + }} + /> + {items + .filter(item => item.label.includes(state.query)) + .map(item => { + return ( + { + actions.toggleSelect(item.label) + }} + > + + + + {item.label} + + ) + })} + + ) +} +```` + +Presentational components are accompanied by behavior or state hooks for a +component's core functionality. Often times, config components are built by +combining presentational components and the corresponding behavior and state +hooks needed for a feature. + +## Consequences + +TODO + +## Alternatives + +TODO + +## Questions + +TODO From a74d0a57db93b31050cba0e42cbfaff8f2a3f72d Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 19 Jun 2026 10:44:16 -0500 Subject: [PATCH 4/7] docs: begin audit --- contributor-docs/adrs/adr-024-modular-ds.md | 292 +++++++------------- 1 file changed, 93 insertions(+), 199 deletions(-) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index 0039f4dfaab..cbb9fcdb008 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -49,213 +49,107 @@ want to focus on in order to improve Primer: quality, accessible experience - Create a model for upstreaming work where people build on top of Primer -In addition, when authoring components we will offer presentational components -and behavioral hooks that can then be used for higher-level, props-based -components. +To do this, we will: -### Embracing layer 2 +- Identify and deliver components to break down into parts that can be used to create more + flexible and extensible components +- Identify and deliver low-level components, hooks, and utilities that can be used to quickly build out accessible experiences +- Embrace the spectrum of abstraction model, authoring presentation components + that combine with hooks to provide flexible patterns and opinionated defaults. -- Parts provide a clear way for teams to layer on functionality that does not - exist -- It provides a clear path for upstreaming -- The biggest gap is providing behavioral/state hooks for components (if needed) +### Breaking components down into parts -`N/A` means that layer is not a useful fit for the component's API shape. +### Delivering low-level components, hooks, and utilities -| Entrypoint | Component | Props | Parts | Hooks | Notes | -| :------------- | :------------------ | :---- | :---- | :---- | :---------------------------------------------------------------------------------------------------------------- | -| . | ActionBar | N/A | Yes | No | Parts include `IconButton`, `Divider`, `Group`, and `Menu`; no public ActionBar behavior hook. | -| | ActionList | N/A | Yes | No | Compound list API with item, group, divider, visual, description, and action parts. | -| | ActionMenu | No | Yes | No | Parts include `Button`, `Anchor`, `Overlay`, and `Divider`; menu contents use `ActionList`. | -| | AnchoredOverlay | Yes | N/A | Yes | Props-driven overlay; behavior can be recreated with `useAnchoredPosition` and `useOverlay`. | -| | Autocomplete | No | Yes | No | Slot API exposes `Input`, `Menu`, and `Overlay`; no public autocomplete hook. | -| | Avatar | Yes | N/A | N/A | Leaf visual component. | -| | AvatarStack | Yes | N/A | No | Props-driven wrapper around `Avatar` children; no public stack behavior hook. | -| | Banner | Yes | Yes | N/A | Supports title, description, and action props plus matching parts. | -| | BaseStyles | Yes | N/A | N/A | Props-driven application wrapper. | -| | BranchName | Yes | N/A | N/A | Leaf display component. | -| | Breadcrumb | N/A | Yes | N/A | Deprecated alias of `Breadcrumbs` with `Item`. | -| | Breadcrumbs | N/A | Yes | N/A | Uses `Breadcrumbs.Item`; no props-only item list API. | -| | Button | Yes | N/A | N/A | Leaf action component. | -| | ButtonGroup | Yes | N/A | N/A | Props-driven grouping wrapper for button children. | -| | Checkbox | Yes | N/A | N/A | Native input wrapper. | -| | CheckboxGroup | N/A | Yes | No | Uses label, caption, and validation parts through the shared choice-group implementation. | -| | ConfirmationDialog | Yes | N/A | Yes | Props-driven dialog with `useConfirm` behavior hook. | -| | CounterLabel | Yes | N/A | N/A | Leaf count display component. | -| | Details | N/A | Yes | Yes | Exposes `Summary` plus `useDetails`. | -| | Dialog | Yes | Yes | No | Props-driven dialog also exposes parts for custom renderers; `useDialog` is internal. | -| | Flash | Yes | N/A | N/A | Props-driven message component. | -| | FocusKeys | N/A | N/A | Yes | Not a component; exported behavior constant used with `useFocusZone`. | -| | FormControl | N/A | Yes | Yes | Parts include `Label`, `Caption`, `LeadingVisual`, and `Validation`; hook forwards form-control props. | -| | Header | N/A | Yes | N/A | Structural API exposes `Item` and `Link`. | -| | Heading | Yes | N/A | N/A | Leaf typography component. | -| | IconButton | Yes | N/A | N/A | Leaf action component. | -| | IssueLabelToken | Yes | N/A | N/A | Props-driven token variant. | -| | Label | Yes | N/A | N/A | Leaf display component. | -| | LabelGroup | Yes | N/A | N/A | Props-driven grouping wrapper for labels. | -| | Link | Yes | N/A | N/A | Leaf navigation component. | -| | LinkButton | Yes | N/A | N/A | Leaf action/navigation component. | -| | NavList | N/A | Yes | No | Compound navigation API with item, group, visual, divider, and subnav parts. | -| | Overlay | Yes | N/A | Yes | Props-driven floating surface backed by `useOverlay`. | -| | PageHeader | N/A | Yes | N/A | Structural API exposes title, context, action, visual, description, and navigation parts. | -| | PageLayout | N/A | Yes | No | Layout parts include `Header`, `Content`, `Pane`, `Sidebar`, and `Footer`; no public layout hook. | -| | Pagination | Yes | N/A | No | Props-driven pagination model; no public pagination hook. | -| | Popover | Yes | Yes | N/A | Props-driven wrapper with `Content` part. | -| | Portal | Yes | N/A | N/A | Low-level rendering utility. | -| | PortalContext | N/A | N/A | N/A | Context export rather than a component API. | -| | ProgressBar | Yes | Yes | N/A | Props-driven bar with `Item` for segmented progress. | -| | Radio | Yes | N/A | N/A | Native input wrapper. | -| | RadioGroup | N/A | Yes | No | Uses label, caption, and validation parts through the shared choice-group implementation. | -| | RelativeTime | Yes | N/A | N/A | Props-driven time display. | -| | ResponsiveValue | N/A | N/A | Yes | Type-level API paired with `useResponsiveValue`. | -| | SegmentedControl | N/A | Yes | No | Compound control with `Button` and `IconButton` parts; no public segmented-control hook. | -| | Select | Yes | Yes | N/A | Native select wrapper with `Option` and `OptGroup` parts. | -| | SelectPanel | Yes | Yes | No | Props-driven selection panel; parts cover messages and secondary actions, not the full behavior. | -| | SideNav | N/A | Yes | N/A | Deprecated structural nav with `Link` part. | -| | SkeletonBox | Yes | N/A | N/A | Leaf skeleton component. | -| | Spinner | Yes | N/A | N/A | Leaf loading component. | -| | SplitPageLayout | N/A | Yes | No | Layout parts mirror `PageLayout`; no public layout hook. | -| | Stack | Yes | Yes | N/A | Props-driven layout primitive with optional `Item` part. | -| | StateLabel | Yes | N/A | N/A | Leaf display component. | -| | SubNav | N/A | Yes | N/A | Structural nav with `Link` and `Links` parts. | -| | Text | Yes | N/A | N/A | Leaf typography component. | -| | Textarea | Yes | N/A | N/A | Native input wrapper. | -| | TextInput | Yes | Yes | N/A | Props-driven input with `Action` as an optional part. | -| | TextInputWithTokens | Yes | N/A | No | Props-driven tokenized input; no public token-input behavior hook. | -| | ThemeProvider | Yes | N/A | Yes | Provider component plus `useTheme` and `useColorSchemeVar`. | -| | Timeline | N/A | Yes | N/A | Structural timeline with item, avatar, badge, body, break, and action parts. | -| | ToggleSwitch | Yes | N/A | N/A | Props-driven switch component. | -| | Token | Yes | N/A | N/A | Leaf token component. | -| | Tooltip | Yes | N/A | No | Props-driven tooltip; no public tooltip behavior hook. | -| | TreeView | N/A | Yes | Yes | Compound tree API with item/subtree/visual parts and `useRovingTabIndex`. | -| | Truncate | Yes | N/A | N/A | Props-driven text utility. | -| | UnderlineNav | N/A | Yes | N/A | Structural nav with `Item` part. | -| | VisuallyHidden | Yes | N/A | N/A | Leaf accessibility utility. | -| ./experimental | Announce | Yes | N/A | N/A | Props-driven live-region primitive; no public announcement hook (available through `@primer/live-region-element` | -| | AriaAlert | Yes | N/A | N/A | Props-driven assertive live-region wrapper. | -| | AriaStatus | Yes | N/A | N/A | Props-driven polite live-region wrapper. | -| | Blankslate | N/A | Yes | N/A | Parts-first API with visual, heading, description, and action parts. | -| | Card | N/A | Yes | N/A | Parts-first card with icon, image, heading, description, action, and metadata parts. | -| | DataTable | Yes | Yes | Yes | Props-driven data grid; presentational table parts are exposed through `Table`. Hook is `useTable` | -| | Dialog | Yes | Yes | No | Same public API shape as the root export. | -| | FilteredActionList | Yes | Yes | No | Props-driven filtered list with `Input` and `BodyLoader` parts. | -| | Hidden | N/A | Yes | N/A | Props-driven responsive visibility utility. | -| | InlineMessage | N/A | Yes | N/A | Leaf message component. | -| | IssueLabel | N/A | Yes | N/A | Props-driven issue label component. | -| | KeybindingHint | Yes | N/A | N/A | Props-driven text utility for keybindings. | -| | NavList | N/A | Yes | No | Same public API shape as the root export. | -| | PageHeader | N/A | Yes | N/A | Same public API shape as the root export. | -| | ScrollableRegion | Yes | N/A | N/A | Props-driven accessibility wrapper. | -| | SelectPanel | N/A | Yes | No | Experimental parts-first panel with button, header, search, footer, loading, message, and secondary action parts. | -| | SkeletonAvatar | Yes | N/A | N/A | Leaf skeleton component. | -| | SkeletonText | Yes | N/A | N/A | Leaf skeleton component. | -| | Stack | Yes | Yes | N/A | Same public API shape as the root export. | -| | Table | N/A | Yes | N/A | Presentational table parts for `DataTable`. | -| | Tabs | N/A | Yes | Yes | Experimental primitive exposes `TabList`, `Tab`, `TabPanel`, and related hooks. | -| | Tooltip | Yes | N/A | No | Same public API shape as the root export. | -| | TopicTag | Yes | Yes | N/A | Props-driven tag with `Group` part. | -| | UnderlinePanels | N/A | Yes | No | Parts-first tab panel API with `Tab` and `Panel`; no public hook. | - -### Low-level components and hooks - -We want to offer more low-level components and hooks, in particular with a focus -on accessibility. Providing these low-level abstractions allows for quickly creating -robust experiences instead of having to re-invent them from scratch. - -In particular, we would like to offer the following primitives: - -| Type | Name | Supported | Description | Notes | -| :--------- | :---------------- | :-------- | :----------------------------------------- | :-------------------------------------------------------------------------------------------------- | -| Components | Accordion | No | Disclosure group primitive. | Not exposed today. | -| | Combobox | No | Text input plus listbox popup primitive. | Autocomplete and SelectPanel cover product use cases, but no generic combobox primitive is exposed. | -| | Disclosure | No | Show/hide primitive. | `Details` and `useDetails` exist, but there is no named `Disclosure` primitive. | -| | Dialog | Yes | Modal dialog primitive. | `Dialog` exposes props and custom-renderer parts. | -| | Listbox | No | Option list primitive. | ActionList and SelectPanel cover product use cases, but no generic listbox primitive is exposed. | -| | Menu | No | Menu button and popup primitive. | ActionMenu covers product use cases, but no generic menu primitive is exposed. | -| | Menubar | No | Horizontal menu primitive. | Not exposed today. | -| | Popover | Yes | Anchored floating content primitive. | Covered by `Popover`, `Overlay`, and `AnchoredOverlay`. | -| | Tabs | Yes | Tab state and tab/panel primitive. | Available from `./experimental` with parts and hooks. | -| | Tree | Yes | Tree navigation primitive. | Covered by `TreeView`; no separate unstyled `Tree` primitive is exposed. | -| Hooks | useFocusTrap | Yes | Trap focus within a container. | Exported from the root entrypoint. | -| | useMergedRefs | Yes | Merge multiple refs into one ref callback. | Exported from the root entrypoint. | -| | useRovingTabIndex | Yes | Manage roving tab index behavior. | Exported from the root entrypoint via `TreeView`. | -| | useTabs | Yes | Manage tab state and ARIA wiring. | Available from `./experimental` alongside `useTab`, `useTabList`, and `useTabPanel`. | - -### Model for upstreaming work - -### Authoring components - -#### Config components - -These components are "all-in-one"; they provide a high level of abstraction that -support common use-cases making it simple to quickly build out established -patterns and experiences. However, they are often inflexible and difficult to -extend. - -````tsx - { - /* ... */ - }} - onFilter={query => { - /* ... */ - }} -/> - -#### Presentational components - -These components provide a lower level of abstraction and are more flexible and extensible, but require more work to build out common patterns and experiences. - -```tsx -function Example({items}) { - const [state, actions] = useList({ - defaultSelected: [], - }) - - return ( - - { - actions.updateQuery(query) - }} - /> - {items - .filter(item => item.label.includes(state.query)) - .map(item => { - return ( - { - actions.toggleSelect(item.label) - }} - > - - - - {item.label} - - ) - })} - - ) -} -```` - -Presentational components are accompanied by behavior or state hooks for a -component's core functionality. Often times, config components are built by -combining presentational components and the corresponding behavior and state -hooks needed for a feature. +### Embracing the spectrum of abstraction model ## Consequences -TODO - ## Alternatives -TODO - ## Questions -TODO +## Audit + +| Entrypoint | Type | Name | Parts | Hooks | Config | Notes | +| :------------- | :------- | :----------------- | :---- | :---- | :----- | :---- | +| . | Compound | ActionBar | ✅ | | | | +| | | ActionList | ✅ | | | | +| | | ActionMenu | ✅ | | | | +| | | Banner | ✅ | | | | +| | | Breadcrumbs | ✅ | | | | +| | | ConfirmationDialog | | | | | +| | | Details | ✅ | | | | +| | | Dialog | | | | | +| | | FormControl | ✅ | | | | +| | | Header | ✅ | | | | +| | | NavList | ✅ | | | | +| | | PageHeader | ✅ | | | | +| | | PageLayout | ✅ | | | | +| | | Pagination | | | | | +| | | Popover | ✅ | | | | +| | | ProgressBar | ✅ | | | | +| | | SegmentedControl | ✅ | | | | +| | | Select | ✅ | | | | +| | | SelectPanel | | | | | +| | | SplitPageLayout | ✅ | | | | +| | | Stack | ✅ | | | | +| | | SubNav | ✅ | | | | +| | | Timeline | ✅ | | | | +| | | TreeView | ✅ | | | | +| | | UnderlineNav | ✅ | | | | +| . | Leaf | Autocomplete | | | | | +| | | Avatar | | | | | +| | | AvatarStack | | | | | +| | | BranchName | | | | | +| | | Button | | | | | +| | | ButtonGroup | | | | | +| | | Checkbox | | | | | +| | | CheckboxGroup | | | | | +| | | CircleBadge | | | | | +| | | CounterLabel | | | | | +| | | Heading | | | | | +| | | IconButton | | | | | +| | | IssueLabelToken | | | | | +| | | Label | | | | | +| | | LabelGroup | | | | | +| | | Link | | | | | +| | | LinkButton | | | | | +| | | Overlay | | | | | +| | | Radio | | | | | +| | | RadioGroup | | | | | +| | | RelativeTime | | | | | +| | | SkeletonBox | | | | | +| | | Spinner | | | | | +| | | StateLabel | | | | | +| | | Text | | | | | +| | | TextInput | | | | | +| | | Textarea | | | | | +| | | ToggleSwitch | | | | | +| | | Token | | | | | +| | | Tooltip | | | | | +| | | Truncate | | | | | +| | Utility | | | | | | +| | | AnchoredOverlay | | | | | +| | | VisuallyHidden | | | | | +| ./experimental | Compound | | | | | | +| | | Blankslate | | | | | +| | | Card | | | | | +| | | DataTable | | | | | +| | | Dialog | | | | | +| | | FilteredActionList | | | | | +| | | KeybindingHint | | | | | +| | | SelectPanel | | | | | +| | | Stack | | | | | +| | | Table | | | | | +| | | Tabs | | | | | +| | | UnderlinePanels | | | | | +| | Leaf | | | | | | +| | | InlineMessage | | | | | +| | | IssueLabel | | | | | +| | | SkeletonAvatar | | | | | +| | | SkeletonText | | | | | +| | | Tooltip | | | | | +| | | TopicTag | | | | | +| | Utility | | | | | | +| | | Hidden | | | | | From a8140fd98eaf6b8904f8848076a146538f187a8d Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 19 Jun 2026 10:50:38 -0500 Subject: [PATCH 5/7] docs: update audit table --- contributor-docs/adrs/adr-024-modular-ds.md | 39 +++++++++------------ 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index cbb9fcdb008..cbc691af026 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -78,20 +78,20 @@ To do this, we will: | | | ActionMenu | ✅ | | | | | | | Banner | ✅ | | | | | | | Breadcrumbs | ✅ | | | | -| | | ConfirmationDialog | | | | | +| | | ConfirmationDialog | | | ✅ | | | | | Details | ✅ | | | | -| | | Dialog | | | | | +| | | Dialog | | | ✅ | | | | | FormControl | ✅ | | | | | | | Header | ✅ | | | | | | | NavList | ✅ | | | | | | | PageHeader | ✅ | | | | | | | PageLayout | ✅ | | | | -| | | Pagination | | | | | +| | | Pagination | | | ✅ | | | | | Popover | ✅ | | | | | | | ProgressBar | ✅ | | | | | | | SegmentedControl | ✅ | | | | | | | Select | ✅ | | | | -| | | SelectPanel | | | | | +| | | SelectPanel | | | ✅ | | | | | SplitPageLayout | ✅ | | | | | | | Stack | ✅ | | | | | | | SubNav | ✅ | | | | @@ -129,27 +129,22 @@ To do this, we will: | | | Token | | | | | | | | Tooltip | | | | | | | | Truncate | | | | | -| | Utility | | | | | | -| | | AnchoredOverlay | | | | | +| | Utility | AnchoredOverlay | | | | | | | | VisuallyHidden | | | | | -| ./experimental | Compound | | | | | | -| | | Blankslate | | | | | -| | | Card | | | | | -| | | DataTable | | | | | -| | | Dialog | | | | | -| | | FilteredActionList | | | | | -| | | KeybindingHint | | | | | -| | | SelectPanel | | | | | -| | | Stack | | | | | -| | | Table | | | | | -| | | Tabs | | | | | -| | | UnderlinePanels | | | | | -| | Leaf | | | | | | -| | | InlineMessage | | | | | +| ./experimental | Compound | Blankslate | ✅ | | | | +| | | Card | ✅ | | | | +| | | DataTable | | | ✅ | | +| | | FilteredActionList | | | ✅ | | +| | | KeybindingHint | | | ✅ | | +| | | SelectPanel | ✅ | | | | +| | | Stack | ✅ | | | | +| | | Table | ✅ | | | | +| | | Tabs | ✅ | ✅ | | | +| | | UnderlinePanels | ✅ | | | | +| | Leaf | InlineMessage | | | | | | | | IssueLabel | | | | | | | | SkeletonAvatar | | | | | | | | SkeletonText | | | | | | | | Tooltip | | | | | | | | TopicTag | | | | | -| | Utility | | | | | | -| | | Hidden | | | | | +| | Utility | Hidden | | | | | From e38e50f51a87c28782d135b8c15032ad61590f52 Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 19 Jun 2026 11:07:25 -0500 Subject: [PATCH 6/7] docs: add sections for low-level and spectrum docs --- contributor-docs/adrs/adr-024-modular-ds.md | 175 ++++++++++++++++++++ 1 file changed, 175 insertions(+) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index cbc691af026..be4a1ac6a95 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -61,8 +61,183 @@ To do this, we will: ### Delivering low-level components, hooks, and utilities +We will immediately deliver high priority components that assist in building accessible experiences, including: + +- **Combobox** for filtering and selection-based experiences +- **Dialog** for modal and nonmodal experiences with built in parts for + wiring up accessibility, behaviors, and semantics +- **Listbox** for selection-based experiences +- **Menu** for action-based experiences +- **Popover** for positioned, transient experiences +- **ScrollableRegion** for scrollable containers with built in accessibility and behaviors +- **Tabs** for building tabs-based experiences +- **ToggleButton**, **ToggleSwitch** for building toggle-based experiences + +We will also deliver documentation for all existing low-level components, +hooks, and utilities. + +In the future, we are investigating the following opportunities for offering +additional low-level components, hooks, and utilities: + +- useFilter +- useSelection + +#### Audit + +| Entrypoint | Type | Name | +| :------------- | :-------- | :--------------------------- | +| . | component | VisuallyHidden | +| | | Announce | +| | | AriaStatus | +| | | AriaAlert | +| | hook | useAnchoredPosition | +| | | useColorSchemeVar | +| | | useConfirm | +| | | useDetails | +| | | useFocusTrap | +| | | useFocusZone | +| | | useFormControlForwardedProps | +| | | useId | +| | | useIsomorphicLayoutEffect | +| | | useMergedRefs | +| | | useOnEscapePress | +| | | useOnOutsideClick | +| | | useOpenAndCloseFocus | +| | | useOverlay | +| | | useProvidedRefOrCreate | +| | | useRefObjectAsForwardedRef | +| | | useResizeObserver | +| | | useResponsiveValue | +| | | useRovingTabIndex | +| | | useSafeTimeout | +| | | useSlots | +| | | useSyncedState | +| | | useTheme | +| ./experimental | component | Hidden | +| | | Tabs | +| | hook | useSlots | +| | | useOverflow | +| | | useTab | +| | | useTabList | +| | | useTabPanel | + ### Embracing the spectrum of abstraction model +We will author components with a spectrum of abstraction in mind, specifically +beginning with presentational components that can combine with hooks to provide +opionated, config-driven components. + +This model allows us to offer opinionated defaults that work for common +scenarios while still allow teams to extend and customize components as needed. + +Default to building presentational components, then add behavior through hooks. +As opinions or defaults are established, create config-driven components that +combine presentational components and hooks to offer a higher level of +abstraction for common use-cases. + +#### Config components + +These components are "all-in-one"; they provide a high level of abstraction that +support common use-cases making it simple to quickly build out established +patterns and experiences. However, they are often inflexible and difficult to +extend. + +```tsx + { + /* ... */ + }} + onFilter={query => { + /* ... */ + }} +/> +``` + +#### Presentational components + +These components provide a lower level of abstraction and are more flexible and extensible, but require more work to build out common patterns and experiences. + +```tsx +function Example({items}) { + const [state, actions] = useList({ + defaultSelected: [], + }) + + return ( + + { + actions.updateQuery(query) + }} + /> + {items + .filter(item => item.label.includes(state.query)) + .map(item => { + return ( + { + actions.toggleSelect(item.label) + }} + > + + + + {item.label} + + ) + })} + + ) +} +``` + +Presentational components are accompanied by behavior or state hooks for a +component's core functionality. Often times, config components are built by +combining presentational components and the corresponding behavior and state +hooks needed for a feature. + +#### Base components + +Base components are unstyled and may optionally provide behavior. These +components are fundamental primitives that are used to build components, such as +accessibility primitives. + +```tsx +function Example() { + return ( + + + + + + + + ) +} +``` + +Other examples include: + +- Combobox (filtering, selection) +- Listbox (selection) +- Popover +- Tabs +- Treeview + +#### Utilities + +There are core utilities, hooks, functions, etc that are commonly used when +building out components or React applications. We provide hooks for established +patterns so that teams can build on solid foundations when authoring new +experiences. These can include hooks such as `useMergedRefs`, +`useOnEscapePress`, `useTimeout` and more. + +These utilities may extend beyond hooks, such as `@primer/behaviors` or custom +elements, where appropriate. + ## Consequences ## Alternatives From 429d646cbe005945bd4ddfcd8e1aa7c66efb7afe Mon Sep 17 00:00:00 2001 From: Josh Black Date: Fri, 19 Jun 2026 11:44:44 -0500 Subject: [PATCH 7/7] Add Disclosure component for content visibility --- contributor-docs/adrs/adr-024-modular-ds.md | 1 + 1 file changed, 1 insertion(+) diff --git a/contributor-docs/adrs/adr-024-modular-ds.md b/contributor-docs/adrs/adr-024-modular-ds.md index be4a1ac6a95..e83de99e7f3 100644 --- a/contributor-docs/adrs/adr-024-modular-ds.md +++ b/contributor-docs/adrs/adr-024-modular-ds.md @@ -66,6 +66,7 @@ We will immediately deliver high priority components that assist in building acc - **Combobox** for filtering and selection-based experiences - **Dialog** for modal and nonmodal experiences with built in parts for wiring up accessibility, behaviors, and semantics +- **Disclosure** for showing/hiding content - **Listbox** for selection-based experiences - **Menu** for action-based experiences - **Popover** for positioned, transient experiences