From a27dc7795d8c6e27edf2515c1c788a458a0dce6e Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 25 Feb 2026 12:53:35 +0000 Subject: [PATCH 1/4] feat(ui): simplify neutral bg prop to single auto-incrementing 'neutral' value Signed-off-by: Charles de Dreuille --- .../Accordion/Accordion.stories.tsx | 64 ++++++++-------- .../ui/src/components/Accordion/definition.ts | 2 +- .../ui/src/components/Alert/Alert.stories.tsx | 26 ++++--- .../ui/src/components/Box/Box.stories.tsx | 27 ++++--- .../src/components/Button/Button.stories.tsx | 32 ++++---- .../ui/src/components/Card/Card.stories.tsx | 62 +++++++++------- packages/ui/src/components/Card/Card.tsx | 2 +- .../ui/src/components/Flex/Flex.stories.tsx | 39 +++++----- .../ui/src/components/Grid/Grid.stories.tsx | 73 ++++++++++--------- .../ToggleButton/ToggleButton.stories.tsx | 21 ++++-- .../ToggleButtonGroup.stories.tsx | 49 +++++++------ packages/ui/src/hooks/useBg.tsx | 10 +-- packages/ui/src/types.ts | 16 ++-- 13 files changed, 237 insertions(+), 186 deletions(-) diff --git a/packages/ui/src/components/Accordion/Accordion.stories.tsx b/packages/ui/src/components/Accordion/Accordion.stories.tsx index b88b547e08..5def4f57d3 100644 --- a/packages/ui/src/components/Accordion/Accordion.stories.tsx +++ b/packages/ui/src/components/Accordion/Accordion.stories.tsx @@ -195,7 +195,7 @@ export const AutoBg = meta.story({ - + Neutral 1 container @@ -210,35 +210,41 @@ export const AutoBg = meta.story({ - - Neutral 2 container - - - - - - - - - - - - + + + Neutral 2 container + + + + + + + + + + + + + - - Neutral 3 container - - - - - - - - - - - - + + + + Neutral 3 container + + + + + + + + + + + + + + ), diff --git a/packages/ui/src/components/Accordion/definition.ts b/packages/ui/src/components/Accordion/definition.ts index 69ef9be3a7..2e76f0cd77 100644 --- a/packages/ui/src/components/Accordion/definition.ts +++ b/packages/ui/src/components/Accordion/definition.ts @@ -34,7 +34,7 @@ export const AccordionDefinition = defineComponent()({ }, bg: 'provider', propDefs: { - bg: { dataAttribute: true, default: 'neutral-auto' }, + bg: { dataAttribute: true, default: 'neutral' }, children: {}, className: {}, }, diff --git a/packages/ui/src/components/Alert/Alert.stories.tsx b/packages/ui/src/components/Alert/Alert.stories.tsx index 28239becb9..589d55b7dd 100644 --- a/packages/ui/src/components/Alert/Alert.stories.tsx +++ b/packages/ui/src/components/Alert/Alert.stories.tsx @@ -297,7 +297,7 @@ export const OnDifferentBackgrounds = meta.story({ On Neutral 1 - + @@ -305,18 +305,24 @@ export const OnDifferentBackgrounds = meta.story({ On Neutral 2 - - - - + + + + + + On Neutral 3 - - - - + + + + + + + + ), @@ -337,7 +343,7 @@ export const Responsive = meta.story({ export const WithUtilityProps = meta.story({ render: () => ( - + ( Default - - Neutral 1 + + Neutral (level 1) - - Neutral 2 + + + Neutral (level 2) + - - Neutral 3 - - - Responsive Neutral + + + + Neutral (level 3) + + Danger @@ -381,11 +384,11 @@ export const BackgroundColors = meta.story({ export const NestedNeutralColors = meta.story({ args: { px: '6', py: '4', children: null }, render: args => ( - + - + - + diff --git a/packages/ui/src/components/Button/Button.stories.tsx b/packages/ui/src/components/Button/Button.stories.tsx index 2e2f94b4e1..5781daca6a 100644 --- a/packages/ui/src/components/Button/Button.stories.tsx +++ b/packages/ui/src/components/Button/Button.stories.tsx @@ -357,26 +357,32 @@ export const AutoBg = meta.story({ neutral level by 1. No prop is needed on the button -- it's fully automatic. - + Neutral 1 container - - Neutral 2 container - - - - + + + Neutral 2 container + + + + + - - Neutral 3 container - - - - + + + + Neutral 3 container + + + + + + ), diff --git a/packages/ui/src/components/Card/Card.stories.tsx b/packages/ui/src/components/Card/Card.stories.tsx index 3957b7beff..87671c4cf6 100644 --- a/packages/ui/src/components/Card/Card.stories.tsx +++ b/packages/ui/src/components/Card/Card.stories.tsx @@ -135,23 +135,29 @@ export const Backgrounds = meta.story({ No parent Defaults to neutral-1 - + On neutral-1 Auto-increments to neutral-2 - - - On neutral-2 - Auto-increments to neutral-3 - + + + + On neutral-2 + Auto-increments to neutral-3 + + - - - On neutral-3 - Steps up to neutral-4 - + + + + + On neutral-3 + Steps up to neutral-4 + + + ), @@ -197,23 +203,29 @@ export const BgOnProviders = meta.story({ No provider Card defaults to neutral-1 - + On neutral-1 Card auto-increments to neutral-2 - - - On neutral-2 - Card auto-increments to neutral-3 - + + + + On neutral-2 + Card auto-increments to neutral-3 + + - - - On neutral-3 - Card visually at neutral-4 - + + + + + On neutral-3 + Card visually at neutral-4 + + + ), @@ -226,11 +238,7 @@ export const CustomCardWithBox = meta.story({ A custom card built with Box. Use Box with an explicit bg prop to create a card-like container that participates in the bg system as a provider. - + diff --git a/packages/ui/src/components/Card/Card.tsx b/packages/ui/src/components/Card/Card.tsx index e3e4781eac..5eb09f2edc 100644 --- a/packages/ui/src/components/Card/Card.tsx +++ b/packages/ui/src/components/Card/Card.tsx @@ -44,7 +44,7 @@ export const Card = forwardRef((props, ref) => { return ( ( Default - - Neutral 1 - - - Neutral 2 - - - Neutral 3 - - - Responsive Bg + + Neutral (level 1) + + + Neutral (level 2) + + + + + + Neutral (level 3) + + + Danger @@ -278,20 +281,20 @@ export const Backgrounds = meta.story({ ), }); -export const BgNeutralAuto = meta.story({ +export const BgNeutral = meta.story({ args: { px: '6', py: '4', gap: '4' }, render: args => (
- Using bg="neutral-auto" on Flex auto-increments from the parent context. - The first Flex defaults to neutral-1 (no parent), then each nested Flex + Using bg="neutral" on Flex auto-increments from the parent context. The + first Flex defaults to neutral-1 (no parent), then each nested Flex increments by one, capping at neutral-3.
- -
Neutral 1 (auto, no parent)
- + +
Neutral 1 (no parent)
+
Neutral 2 (auto-incremented)
- +
Neutral 3 (auto-incremented, capped)
diff --git a/packages/ui/src/components/Grid/Grid.stories.tsx b/packages/ui/src/components/Grid/Grid.stories.tsx index b3b6957359..f60517bc31 100644 --- a/packages/ui/src/components/Grid/Grid.stories.tsx +++ b/packages/ui/src/components/Grid/Grid.stories.tsx @@ -113,18 +113,21 @@ export const Backgrounds = meta.story({ render: args => ( - - Neutral 1 - - - Neutral 2 - - - Neutral 3 - - - Responsive Bg + + Neutral (level 1) + + + Neutral (level 2) + + + + + + Neutral (level 3) + + + Danger @@ -137,28 +140,26 @@ export const Backgrounds = meta.story({ - - Neutral 1 - - - - - Neutral 2 - - - - - Neutral 3 - - - - - Responsive Bg + + Neutral (level 1) + + + + Neutral (level 2) + + + + + + + + Neutral (level 3) + + + + Danger @@ -179,7 +180,7 @@ export const Backgrounds = meta.story({ ), }); -export const BgNeutralAuto = meta.story({ +export const BgNeutral = meta.story({ args: { px: '6', py: '4', columns: '2', gap: '4' }, render: args => ( @@ -188,12 +189,12 @@ export const BgNeutralAuto = meta.story({ default. Only an explicit bg prop establishes a new bg level. Nested grids without a bg prop inherit the parent context unchanged. - + Neutral 1 (Grid.Root) - - Nested: neutral-2 (explicit) - Nested: neutral-2 (explicit) + + Nested: neutral-2 (auto-incremented) + Nested: neutral-2 (auto-incremented) diff --git a/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx b/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx index a89bbe3862..876ff654b0 100644 --- a/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx +++ b/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx @@ -16,6 +16,7 @@ import preview from '../../../../../.storybook/preview'; import { ToggleButton } from './ToggleButton'; +import { Box } from '../Box'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { useState } from 'react'; @@ -65,21 +66,27 @@ export const Backgrounds = meta.story({ On Neutral 1 - + Toggle On Neutral 2 - - Toggle - + + + Toggle + + On Neutral 3 - - Toggle - + + + + Toggle + + + ), diff --git a/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx b/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx index 617cd0c0fa..c98a2e18f1 100644 --- a/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx +++ b/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx @@ -17,6 +17,7 @@ import preview from '../../../../../.storybook/preview'; import { ToggleButtonGroup } from './ToggleButtonGroup'; import { ToggleButton } from '../ToggleButton/ToggleButton'; +import { Box } from '../Box'; import { Flex } from '../Flex'; import { Text } from '../Text'; import { useState } from 'react'; @@ -100,7 +101,7 @@ export const Backgrounds = meta.story({ On Neutral 1 - + On Neutral 2 - - - Option 1 - Option 2 - Option 3 - - + + + + Option 1 + Option 2 + Option 3 + + + On Neutral 3 - - - Option 1 - Option 2 - Option 3 - - + + + + + Option 1 + Option 2 + Option 3 + + + + ), diff --git a/packages/ui/src/hooks/useBg.tsx b/packages/ui/src/hooks/useBg.tsx index 6e298fedf9..ea9376b039 100644 --- a/packages/ui/src/hooks/useBg.tsx +++ b/packages/ui/src/hooks/useBg.tsx @@ -90,10 +90,10 @@ export function useBgConsumer(): BgContextValue { * * - `bg` is `undefined` -- transparent, no context change, returns `{ bg: undefined }`. * This is the default for Box, Flex, and Grid (they do **not** auto-increment). - * - `bg` is a `ContainerBg` value -- uses that value directly (e.g. `'neutral-1'`). - * - `bg` is `'neutral-auto'` -- increments the neutral level from the parent context, - * capping at `neutral-3`. Only components that explicitly pass `'neutral-auto'` - * (e.g. Card) will auto-increment; it is never implicit. + * - `bg` is `'neutral'` -- increments the neutral level from the parent context, + * capping at `neutral-3`. The increment is always relative to the parent; it is + * not possible to pin a container to an explicit neutral level. + * - `bg` is `'danger'` | `'warning'` | `'success'` -- used as-is. * * **Capping:** * @@ -116,7 +116,7 @@ export function useBgProvider(bg?: Responsive): BgContextValue { const resolved = resolveResponsiveValue(bg, breakpoint); - if (resolved === 'neutral-auto') { + if (resolved === 'neutral') { return { bg: incrementNeutralBg(context.bg) }; } diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index d3dfd996aa..05ef25d5dc 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -182,7 +182,7 @@ export interface ComponentDefinition { } /** - * Background type for the neutral bg system. + * Resolved background level stored in context and applied as `data-bg` on DOM elements. * * Supports neutral levels ('neutral-1' through 'neutral-3') and * intent backgrounds ('danger', 'warning', 'success'). @@ -190,7 +190,9 @@ export interface ComponentDefinition { * The 'neutral-4' level is not exposed as a prop value -- it is reserved * for leaf component CSS (e.g. Button on a 'neutral-3' surface). * - * @public + * This type is internal. Use `ProviderBg` for component prop types. + * + * @internal */ export type ContainerBg = | 'neutral-1' @@ -201,11 +203,13 @@ export type ContainerBg = | 'success'; /** - * Background values accepted by provider components. + * Background values accepted by provider components (Box, Flex, Grid, Card, etc.). * - * Includes all `ContainerBg` values plus `'neutral-auto'` which - * automatically increments the neutral level from the parent context. + * - `'neutral'` — automatically increments the neutral level from the parent context, + * capping at the maximum level. This is always incremental; explicit levels cannot + * be set directly. + * - `'danger'` | `'warning'` | `'success'` — intent backgrounds used as-is. * * @public */ -export type ProviderBg = ContainerBg | 'neutral-auto'; +export type ProviderBg = 'neutral' | 'danger' | 'warning' | 'success'; From 53268fa77233b25a9c30198f4c229ca66430a64b Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 25 Feb 2026 16:55:08 +0000 Subject: [PATCH 2/4] Add BgReset Signed-off-by: Charles de Dreuille --- .storybook/preview.tsx | 2 +- packages/ui/report.api.md | 4 +- packages/ui/src/components/Dialog/Dialog.tsx | 15 +- packages/ui/src/components/Menu/Menu.tsx | 241 +++++++++--------- .../components/Popover/Popover.stories.tsx | 2 +- .../ui/src/components/Popover/Popover.tsx | 15 +- .../ui/src/components/Tooltip/Tooltip.tsx | 15 +- packages/ui/src/hooks/useBg.tsx | 18 ++ packages/ui/src/types.ts | 5 +- 9 files changed, 177 insertions(+), 140 deletions(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index c5074f7749..9734cee295 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -176,7 +176,7 @@ export default definePreview({ : parseInt(selectedBackground.split('-')[1], 10), }).reduce( children => ( - + {children} ), diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 25522f1825..3ca30cd73c 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -76,7 +76,7 @@ export const AccordionDefinition: { readonly propDefs: { readonly bg: { readonly dataAttribute: true; - readonly default: 'neutral-auto'; + readonly default: 'neutral'; }; readonly children: {}; readonly className: {}; @@ -1604,7 +1604,7 @@ export interface PopoverProps extends Omit { } // @public -export type ProviderBg = ContainerBg | 'neutral-auto'; +export type ProviderBg = 'neutral' | 'danger' | 'warning' | 'success'; // @public (undocumented) export interface QueryOptions { diff --git a/packages/ui/src/components/Dialog/Dialog.tsx b/packages/ui/src/components/Dialog/Dialog.tsx index efdc6c4567..0c0f4bf53f 100644 --- a/packages/ui/src/components/Dialog/Dialog.tsx +++ b/packages/ui/src/components/Dialog/Dialog.tsx @@ -34,6 +34,7 @@ import { useStyles } from '../../hooks/useStyles'; import { DialogDefinition } from './definition'; import { Flex } from '../Flex'; import { Box } from '../Box'; +import { BgReset } from '../../hooks/useBg'; import styles from './Dialog.module.css'; /** @public */ @@ -72,12 +73,14 @@ export const Dialog = forwardRef, DialogProps>( ...style, }} > - - {children} - + + + {children} + + ); diff --git a/packages/ui/src/components/Menu/Menu.tsx b/packages/ui/src/components/Menu/Menu.tsx index da4243f643..a9835b2f68 100644 --- a/packages/ui/src/components/Menu/Menu.tsx +++ b/packages/ui/src/components/Menu/Menu.tsx @@ -59,6 +59,7 @@ import { import styles from './Menu.module.css'; import clsx from 'clsx'; import { Box } from '../Box'; +import { BgReset } from '../../hooks/useBg'; const { RoutingProvider, useRoutingRegistrationEffect } = createRoutingRegistration(); @@ -120,23 +121,25 @@ export const Menu = (props: MenuProps) => { )} placement={placement} > - - {virtualized ? ( - - {menuContent} - - ) : ( - menuContent - )} - + + + {virtualized ? ( + + {menuContent} + + ) : ( + menuContent + )} + + ); @@ -175,23 +178,25 @@ export const MenuListBox = (props: MenuListBoxProps) => { )} placement={placement} > - - {virtualized ? ( - - {listBoxContent} - - ) : ( - listBoxContent - )} - + + + {virtualized ? ( + + {listBoxContent} + + ) : ( + listBoxContent + )} + + ); }; @@ -230,48 +235,50 @@ export const MenuAutocomplete = (props: MenuAutocompleteProps) => { )} placement={placement} > - - - + + + + + + + + + {virtualized ? ( + + {menuContent} + + ) : ( + menuContent )} - aria-label={props.placeholder || 'Search'} - > - - - - - - {virtualized ? ( - - {menuContent} - - ) : ( - menuContent - )} - - + + + ); @@ -314,48 +321,50 @@ export const MenuAutocompleteListbox = ( )} placement={placement} > - - - + + + + + + + + + {virtualized ? ( + + {listBoxContent} + + ) : ( + listBoxContent )} - aria-label={props.placeholder || 'Search'} - > - - - - - - {virtualized ? ( - - {listBoxContent} - - ) : ( - listBoxContent - )} - - + + + ); }; diff --git a/packages/ui/src/components/Popover/Popover.stories.tsx b/packages/ui/src/components/Popover/Popover.stories.tsx index e05b352fc9..0a0e68b572 100644 --- a/packages/ui/src/components/Popover/Popover.stories.tsx +++ b/packages/ui/src/components/Popover/Popover.stories.tsx @@ -208,7 +208,7 @@ export const WithRichContent = Default.extend({ This is a popover with rich content. It can contain multiple elements and formatted text. - + You can also use the automatic bg system inside it. diff --git a/packages/ui/src/components/Popover/Popover.tsx b/packages/ui/src/components/Popover/Popover.tsx index ad8a203558..ed13328a94 100644 --- a/packages/ui/src/components/Popover/Popover.tsx +++ b/packages/ui/src/components/Popover/Popover.tsx @@ -23,6 +23,7 @@ import { useStyles } from '../../hooks/useStyles'; import { PopoverDefinition } from './definition'; import styles from './Popover.module.css'; import { Box } from '../Box'; +import { BgReset } from '../../hooks/useBg'; /** * A popover component built on React Aria Components that displays floating @@ -95,12 +96,14 @@ export const Popover = forwardRef( )} - - {children} - + + + {children} + + )} diff --git a/packages/ui/src/components/Tooltip/Tooltip.tsx b/packages/ui/src/components/Tooltip/Tooltip.tsx index a64c8c072d..d7fb97005b 100644 --- a/packages/ui/src/components/Tooltip/Tooltip.tsx +++ b/packages/ui/src/components/Tooltip/Tooltip.tsx @@ -28,6 +28,7 @@ import { useStyles } from '../../hooks/useStyles'; import { TooltipDefinition } from './definition'; import styles from './Tooltip.module.css'; import { Box } from '../Box'; +import { BgReset } from '../../hooks/useBg'; /** @public */ export const TooltipTrigger = (props: TooltipTriggerComponentProps) => { @@ -71,12 +72,14 @@ export const Tooltip = forwardRef( - - {children} - + + + {children} + + ); }, diff --git a/packages/ui/src/hooks/useBg.tsx b/packages/ui/src/hooks/useBg.tsx index ea9376b039..e67c47da49 100644 --- a/packages/ui/src/hooks/useBg.tsx +++ b/packages/ui/src/hooks/useBg.tsx @@ -69,6 +69,24 @@ export const BgProvider = ({ bg, children }: BgProviderProps) => { ); }; +/** + * Resets the bg context to undefined, cutting any inherited neutral chain. + * Use this inside overlay components (Popover, Tooltip, Dialog, Menu) so + * their content always starts from neutral-1 regardless of where the trigger + * is placed in the tree. + * + * @internal + */ +export const BgReset = ({ children }: { children: ReactNode }) => { + return ( + + {children} + + ); +}; + /** * Hook for consumer components (e.g. Button) to read the parent bg context. * diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index 05ef25d5dc..af87bfb20b 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -190,9 +190,10 @@ export interface ComponentDefinition { * The 'neutral-4' level is not exposed as a prop value -- it is reserved * for leaf component CSS (e.g. Button on a 'neutral-3' surface). * - * This type is internal. Use `ProviderBg` for component prop types. + * This is the resolved/internal representation used by the bg context system. + * For the prop type accepted by container components, use `ProviderBg` instead. * - * @internal + * @public */ export type ContainerBg = | 'neutral-1' From 768f09d49c3372fd691bdd7dd697aa0d739c6598 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 25 Feb 2026 17:01:55 +0000 Subject: [PATCH 3/4] Create dark-snakes-nail.md Signed-off-by: Charles de Dreuille --- .changeset/dark-snakes-nail.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .changeset/dark-snakes-nail.md diff --git a/.changeset/dark-snakes-nail.md b/.changeset/dark-snakes-nail.md new file mode 100644 index 0000000000..d4eb6f0dd2 --- /dev/null +++ b/.changeset/dark-snakes-nail.md @@ -0,0 +1,21 @@ +--- +'@backstage/ui': minor +--- + +**BREAKING**: Simplified the neutral background prop API for container components. The explicit `neutral-1`, `neutral-2`, `neutral-3`, and `neutral-auto` values have been removed from `ProviderBg`. They are replaced by a single `'neutral'` value that always auto-increments from the parent context, making it impossible to skip or pin to an explicit neutral level. + +**Migration:** + +Replace any explicit `bg="neutral-1"`, `bg="neutral-2"`, `bg="neutral-3"`, or `bg="neutral-auto"` props with `bg="neutral"`. To achieve a specific neutral level in stories or tests, use nested containers — each additional `bg="neutral"` wrapper increments by one level. + +```tsx +// Before +... + +// After + + ... + +``` + +**Affected components:** Box, Flex, Grid, Card, Accordion, Popover, Tooltip, Dialog, Menu From 1afa036222f5e0002835b3760badafa57125ec9a Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Wed, 25 Feb 2026 19:46:17 +0000 Subject: [PATCH 4/4] Cleanup Signed-off-by: Charles de Dreuille --- docs-ui/src/app/snippets.ts | 8 +++--- packages/ui/report.api.md | 27 +++---------------- packages/ui/src/components/Flex/definition.ts | 9 +------ packages/ui/src/components/Grid/definition.ts | 18 ++----------- packages/ui/src/hooks/useBg.tsx | 12 ++++++--- 5 files changed, 18 insertions(+), 56 deletions(-) diff --git a/docs-ui/src/app/snippets.ts b/docs-ui/src/app/snippets.ts index e16463a085..4a93c31831 100644 --- a/docs-ui/src/app/snippets.ts +++ b/docs-ui/src/app/snippets.ts @@ -1,19 +1,19 @@ export const surfacesSnippet = ` - + - + `; -export const adaptiveSnippet = ` +export const adaptiveSnippet = ` {/* automatically set background to neutral-2 */} `; -export const customCardSnippet = ` +export const customCardSnippet = ` Hello World `; diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 3ca30cd73c..1a015747a8 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -1012,14 +1012,7 @@ export const FlexDefinition: { 'direction', ]; readonly dataAttributes: { - readonly bg: readonly [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ]; + readonly bg: readonly ['neutral', 'danger', 'warning', 'success']; }; }; @@ -1096,14 +1089,7 @@ export const GridDefinition: { 'py', ]; readonly dataAttributes: { - readonly bg: readonly [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ]; + readonly bg: readonly ['neutral', 'danger', 'warning', 'success']; }; }; @@ -1114,14 +1100,7 @@ export const GridItemDefinition: { }; readonly utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan']; readonly dataAttributes: { - readonly bg: readonly [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ]; + readonly bg: readonly ['neutral', 'danger', 'warning', 'success']; }; }; diff --git a/packages/ui/src/components/Flex/definition.ts b/packages/ui/src/components/Flex/definition.ts index d0452d6b2c..2701ce5e10 100644 --- a/packages/ui/src/components/Flex/definition.ts +++ b/packages/ui/src/components/Flex/definition.ts @@ -45,13 +45,6 @@ export const FlexDefinition = { 'direction', ], dataAttributes: { - bg: [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ] as const, + bg: ['neutral', 'danger', 'warning', 'success'] as const, }, } as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Grid/definition.ts b/packages/ui/src/components/Grid/definition.ts index c3acb59274..2f417ab34b 100644 --- a/packages/ui/src/components/Grid/definition.ts +++ b/packages/ui/src/components/Grid/definition.ts @@ -43,14 +43,7 @@ export const GridDefinition = { 'py', ], dataAttributes: { - bg: [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ] as const, + bg: ['neutral', 'danger', 'warning', 'success'] as const, }, } as const satisfies ComponentDefinition; @@ -64,13 +57,6 @@ export const GridItemDefinition = { }, utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'], dataAttributes: { - bg: [ - 'neutral-1', - 'neutral-2', - 'neutral-3', - 'danger', - 'warning', - 'success', - ] as const, + bg: ['neutral', 'danger', 'warning', 'success'] as const, }, } as const satisfies ComponentDefinition; diff --git a/packages/ui/src/hooks/useBg.tsx b/packages/ui/src/hooks/useBg.tsx index e67c47da49..2284e5f337 100644 --- a/packages/ui/src/hooks/useBg.tsx +++ b/packages/ui/src/hooks/useBg.tsx @@ -108,10 +108,14 @@ export function useBgConsumer(): BgContextValue { * * - `bg` is `undefined` -- transparent, no context change, returns `{ bg: undefined }`. * This is the default for Box, Flex, and Grid (they do **not** auto-increment). - * - `bg` is `'neutral'` -- increments the neutral level from the parent context, - * capping at `neutral-3`. The increment is always relative to the parent; it is - * not possible to pin a container to an explicit neutral level. - * - `bg` is `'danger'` | `'warning'` | `'success'` -- used as-is. + * - `bg` is `'neutral'` -- when the parent bg is neutral, increments the neutral + * level from the parent context, capping at `neutral-3`. When the parent bg is + * an intent (`'danger'` | `'warning'` | `'success'`), the intent passes through + * unchanged (i.e. `bg: 'neutral'` does not override the parent intent). The + * increment is always relative to the parent; it is not possible to pin a + * container to an explicit neutral level. + * - `bg` is `'danger'` | `'warning'` | `'success'` -- sets the bg to that intent + * explicitly, regardless of the parent value. * * **Capping:** *