From 2899ed02412362dcf32df04bee2b834ce47edcb1 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 9 Feb 2026 18:34:11 +0000 Subject: [PATCH] Improve leaf props for background Signed-off-by: Charles de Dreuille --- packages/ui/report.api.md | 38 +++++++------- .../ui/src/components/Alert/Alert.stories.tsx | 8 --- packages/ui/src/components/Box/Box.module.css | 4 -- packages/ui/src/components/Box/types.ts | 4 +- .../src/components/Button/Button.module.css | 12 ++--- .../src/components/Button/Button.stories.tsx | 23 --------- .../ButtonIcon/ButtonIcon.module.css | 12 ++--- .../ButtonLink/ButtonLink.module.css | 12 ++--- .../ui/src/components/Card/Card.module.css | 4 -- .../ui/src/components/Card/Card.stories.tsx | 10 ---- packages/ui/src/components/Card/types.ts | 4 +- .../ui/src/components/Flex/Flex.module.css | 4 -- .../ui/src/components/Flex/Flex.stories.tsx | 3 -- packages/ui/src/components/Flex/definition.ts | 1 - packages/ui/src/components/Flex/types.ts | 4 +- .../ui/src/components/Grid/Grid.module.css | 5 -- .../ui/src/components/Grid/Grid.stories.tsx | 8 --- packages/ui/src/components/Grid/definition.ts | 2 - packages/ui/src/components/Grid/types.ts | 12 +++-- .../ToggleButton/ToggleButton.stories.tsx | 6 --- .../components/ToggleButton/ToggleButton.tsx | 2 +- .../ToggleButtonGroup.stories.tsx | 13 ----- packages/ui/src/hooks/useBg.tsx | 50 +++++++++++-------- packages/ui/src/hooks/useDefinition/types.ts | 2 +- .../src/hooks/useDefinition/useDefinition.tsx | 6 ++- packages/ui/src/types.ts | 8 +-- 26 files changed, 89 insertions(+), 168 deletions(-) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 34889aaf4f..235d152454 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -205,20 +205,10 @@ export interface AvatarProps extends React.ComponentPropsWithoutRef<'div'> { src: string; } -// @public -export type Bg = - | 'neutral-1' - | 'neutral-2' - | 'neutral-3' - | 'neutral-4' - | 'danger' - | 'warning' - | 'success'; - // @public (undocumented) export interface BgContextValue { // (undocumented) - bg: Bg | undefined; + bg: ContainerBg | undefined; } // @public @@ -227,7 +217,7 @@ export const BgProvider: ({ bg, children }: BgProviderProps) => JSX_2.Element; // @public (undocumented) export interface BgProviderProps { // (undocumented) - bg: Bg; + bg: ContainerBg; // (undocumented) children: ReactNode; } @@ -300,7 +290,7 @@ export const BoxDefinition: { // @public (undocumented) export type BoxOwnProps = { as?: keyof JSX.IntrinsicElements; - bg?: Responsive; + bg?: Responsive; children?: ReactNode; className?: string; style?: CSSProperties; @@ -599,7 +589,7 @@ export interface CardHeaderProps // @public (undocumented) export type CardOwnProps = { - bg?: Responsive; + bg?: Responsive; children?: ReactNode; className?: string; }; @@ -747,6 +737,15 @@ export const Container: ForwardRefExoticComponent< ContainerProps & RefAttributes >; +// @public +export type ContainerBg = + | 'neutral-1' + | 'neutral-2' + | 'neutral-3' + | 'danger' + | 'warning' + | 'success'; + // @public export const ContainerDefinition: { readonly classNames: { @@ -952,7 +951,6 @@ export const FlexDefinition: { 'neutral-1', 'neutral-2', 'neutral-3', - 'neutral-4', 'danger', 'warning', 'success', @@ -968,7 +966,7 @@ export interface FlexProps extends SpaceProps { // (undocumented) align?: Responsive<'start' | 'center' | 'end' | 'baseline' | 'stretch'>; // (undocumented) - bg?: Responsive; + bg?: Responsive; // (undocumented) children?: React.ReactNode; // (undocumented) @@ -1022,7 +1020,6 @@ export const GridDefinition: { 'neutral-1', 'neutral-2', 'neutral-3', - 'neutral-4', 'danger', 'warning', 'success', @@ -1041,7 +1038,6 @@ export const GridItemDefinition: { 'neutral-1', 'neutral-2', 'neutral-3', - 'neutral-4', 'danger', 'warning', 'success', @@ -1052,7 +1048,7 @@ export const GridItemDefinition: { // @public (undocumented) export interface GridItemProps { // (undocumented) - bg?: Responsive; + bg?: Responsive; // (undocumented) children?: React.ReactNode; // (undocumented) @@ -1072,7 +1068,7 @@ export interface GridItemProps { // @public (undocumented) export interface GridProps extends SpaceProps { // (undocumented) - bg?: Responsive; + bg?: Responsive; // (undocumented) children?: React.ReactNode; // (undocumented) @@ -2182,7 +2178,7 @@ export const useBg: (options?: UseBgOptions) => BgContextValue; // @public (undocumented) export interface UseBgOptions { - bg?: Responsive; + bg?: Responsive; mode: 'container' | 'leaf'; } diff --git a/packages/ui/src/components/Alert/Alert.stories.tsx b/packages/ui/src/components/Alert/Alert.stories.tsx index 1cd21434d3..28239becb9 100644 --- a/packages/ui/src/components/Alert/Alert.stories.tsx +++ b/packages/ui/src/components/Alert/Alert.stories.tsx @@ -318,14 +318,6 @@ export const OnDifferentBackgrounds = meta.story({ - - - On Neutral 4 - - - - - ), }); diff --git a/packages/ui/src/components/Box/Box.module.css b/packages/ui/src/components/Box/Box.module.css index 07b0ac2dc1..dd1ff447bc 100644 --- a/packages/ui/src/components/Box/Box.module.css +++ b/packages/ui/src/components/Box/Box.module.css @@ -35,10 +35,6 @@ background-color: var(--bui-bg-neutral-3); } - .bui-Box[data-bg='neutral-4'] { - background-color: var(--bui-bg-neutral-4); - } - .bui-Box[data-bg='danger'] { background-color: var(--bui-bg-danger); } diff --git a/packages/ui/src/components/Box/types.ts b/packages/ui/src/components/Box/types.ts index 89325cf8f2..dabd56fc48 100644 --- a/packages/ui/src/components/Box/types.ts +++ b/packages/ui/src/components/Box/types.ts @@ -15,12 +15,12 @@ */ import type { ReactNode, CSSProperties } from 'react'; -import type { Responsive, Bg, SpaceProps } from '../../types'; +import type { Responsive, ContainerBg, SpaceProps } from '../../types'; /** @public */ export type BoxOwnProps = { as?: keyof JSX.IntrinsicElements; - bg?: Responsive; + bg?: Responsive; children?: ReactNode; className?: string; style?: CSSProperties; diff --git a/packages/ui/src/components/Button/Button.module.css b/packages/ui/src/components/Button/Button.module.css index 847e9ced0d..322a65279d 100644 --- a/packages/ui/src/components/Button/Button.module.css +++ b/packages/ui/src/components/Button/Button.module.css @@ -118,19 +118,19 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg: var(--bui-bg-neutral-2); --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg: var(--bui-bg-neutral-3); --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg: var(--bui-bg-neutral-4); --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); @@ -182,17 +182,17 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); } diff --git a/packages/ui/src/components/Button/Button.stories.tsx b/packages/ui/src/components/Button/Button.stories.tsx index f04550ef57..5e5df2073b 100644 --- a/packages/ui/src/components/Button/Button.stories.tsx +++ b/packages/ui/src/components/Button/Button.stories.tsx @@ -150,29 +150,6 @@ export const Variants = meta.story({ - - Neutral 4 - - - - - - - - - ), }); diff --git a/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css b/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css index 5730efee0d..128e958594 100644 --- a/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css +++ b/packages/ui/src/components/ButtonIcon/ButtonIcon.module.css @@ -85,19 +85,19 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg: var(--bui-bg-neutral-2); --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg: var(--bui-bg-neutral-3); --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg: var(--bui-bg-neutral-4); --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); @@ -122,17 +122,17 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); } diff --git a/packages/ui/src/components/ButtonLink/ButtonLink.module.css b/packages/ui/src/components/ButtonLink/ButtonLink.module.css index 8713a62a58..74a3fe6ba6 100644 --- a/packages/ui/src/components/ButtonLink/ButtonLink.module.css +++ b/packages/ui/src/components/ButtonLink/ButtonLink.module.css @@ -79,19 +79,19 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg: var(--bui-bg-neutral-2); --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg: var(--bui-bg-neutral-3); --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg: var(--bui-bg-neutral-4); --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); @@ -115,17 +115,17 @@ --bg-active: var(--bui-bg-neutral-1-pressed); --fg: var(--bui-fg-primary); - &[data-bg='neutral-2'] { + &[data-on-bg='neutral-1'] { --bg-hover: var(--bui-bg-neutral-2-hover); --bg-active: var(--bui-bg-neutral-2-pressed); } - &[data-bg='neutral-3'] { + &[data-on-bg='neutral-2'] { --bg-hover: var(--bui-bg-neutral-3-hover); --bg-active: var(--bui-bg-neutral-3-pressed); } - &[data-bg='neutral-4'] { + &[data-on-bg='neutral-3'] { --bg-hover: var(--bui-bg-neutral-4-hover); --bg-active: var(--bui-bg-neutral-4-pressed); } diff --git a/packages/ui/src/components/Card/Card.module.css b/packages/ui/src/components/Card/Card.module.css index 62c4c78cb7..1ca0b7a1b4 100644 --- a/packages/ui/src/components/Card/Card.module.css +++ b/packages/ui/src/components/Card/Card.module.css @@ -42,10 +42,6 @@ background-color: var(--bui-bg-neutral-3); } - .bui-Card[data-bg='neutral-4'] { - background-color: var(--bui-bg-neutral-4); - } - .bui-Card[data-bg='danger'] { background-color: var(--bui-bg-danger); } diff --git a/packages/ui/src/components/Card/Card.stories.tsx b/packages/ui/src/components/Card/Card.stories.tsx index b934048622..80dd0ad8d6 100644 --- a/packages/ui/src/components/Card/Card.stories.tsx +++ b/packages/ui/src/components/Card/Card.stories.tsx @@ -147,10 +147,6 @@ export const Backgrounds = meta.story({ Neutral 3 Explicit neutral-3 - - Neutral 4 - Explicit neutral-4 - Card auto → neutral-4 - - - On neutral-4 - Card auto → neutral-4 (capped) - - ), }); diff --git a/packages/ui/src/components/Card/types.ts b/packages/ui/src/components/Card/types.ts index fae864e621..2b32bbf50a 100644 --- a/packages/ui/src/components/Card/types.ts +++ b/packages/ui/src/components/Card/types.ts @@ -15,11 +15,11 @@ */ import type { ReactNode } from 'react'; -import type { Responsive, Bg } from '../../types'; +import type { Responsive, ContainerBg } from '../../types'; /** @public */ export type CardOwnProps = { - bg?: Responsive; + bg?: Responsive; children?: ReactNode; className?: string; }; diff --git a/packages/ui/src/components/Flex/Flex.module.css b/packages/ui/src/components/Flex/Flex.module.css index 01f9c29dbc..499326b9ea 100644 --- a/packages/ui/src/components/Flex/Flex.module.css +++ b/packages/ui/src/components/Flex/Flex.module.css @@ -36,10 +36,6 @@ background-color: var(--bui-bg-neutral-3); } - .bui-Flex[data-bg='neutral-4'] { - background-color: var(--bui-bg-neutral-4); - } - .bui-Flex[data-bg='danger'] { background-color: var(--bui-bg-danger); } diff --git a/packages/ui/src/components/Flex/Flex.stories.tsx b/packages/ui/src/components/Flex/Flex.stories.tsx index 5bc7258312..158110d20a 100644 --- a/packages/ui/src/components/Flex/Flex.stories.tsx +++ b/packages/ui/src/components/Flex/Flex.stories.tsx @@ -261,9 +261,6 @@ export const Backgrounds = meta.story({ Neutral 3 - - Neutral 4 - Responsive Bg diff --git a/packages/ui/src/components/Flex/definition.ts b/packages/ui/src/components/Flex/definition.ts index 12772e107e..d0452d6b2c 100644 --- a/packages/ui/src/components/Flex/definition.ts +++ b/packages/ui/src/components/Flex/definition.ts @@ -49,7 +49,6 @@ export const FlexDefinition = { 'neutral-1', 'neutral-2', 'neutral-3', - 'neutral-4', 'danger', 'warning', 'success', diff --git a/packages/ui/src/components/Flex/types.ts b/packages/ui/src/components/Flex/types.ts index a3503dc79c..ad5404e41d 100644 --- a/packages/ui/src/components/Flex/types.ts +++ b/packages/ui/src/components/Flex/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import type { Responsive, Space, SpaceProps, Bg } from '../../types'; +import type { Responsive, Space, SpaceProps, ContainerBg } from '../../types'; /** @public */ export interface FlexProps extends SpaceProps { @@ -25,5 +25,5 @@ export interface FlexProps extends SpaceProps { direction?: Responsive<'row' | 'column' | 'row-reverse' | 'column-reverse'>; className?: string; style?: React.CSSProperties; - bg?: Responsive; + bg?: Responsive; } diff --git a/packages/ui/src/components/Grid/Grid.module.css b/packages/ui/src/components/Grid/Grid.module.css index e8a7248bad..8fdaf15c3b 100644 --- a/packages/ui/src/components/Grid/Grid.module.css +++ b/packages/ui/src/components/Grid/Grid.module.css @@ -36,11 +36,6 @@ background-color: var(--bui-bg-neutral-3); } - .bui-Grid[data-bg='neutral-4'], - .bui-GridItem[data-bg='neutral-4'] { - background-color: var(--bui-bg-neutral-4); - } - .bui-Grid[data-bg='danger'], .bui-GridItem[data-bg='danger'] { background-color: var(--bui-bg-danger); diff --git a/packages/ui/src/components/Grid/Grid.stories.tsx b/packages/ui/src/components/Grid/Grid.stories.tsx index 80c4327dce..fe5b96dfe1 100644 --- a/packages/ui/src/components/Grid/Grid.stories.tsx +++ b/packages/ui/src/components/Grid/Grid.stories.tsx @@ -120,9 +120,6 @@ export const Backgrounds = meta.story({ Neutral 3 - - Neutral 4 - Responsive Bg @@ -152,11 +149,6 @@ export const Backgrounds = meta.story({ Neutral 3 - - - Neutral 4 - - ; gap?: Responsive; style?: React.CSSProperties; - bg?: Responsive; + bg?: Responsive; } /** @public */ @@ -35,5 +41,5 @@ export interface GridItemProps { colStart?: Responsive; rowSpan?: Responsive; style?: React.CSSProperties; - bg?: Responsive; + bg?: Responsive; } diff --git a/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx b/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx index 1a40dc626a..a89bbe3862 100644 --- a/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx +++ b/packages/ui/src/components/ToggleButton/ToggleButton.stories.tsx @@ -81,12 +81,6 @@ export const Backgrounds = meta.story({ Toggle - - On Neutral 4 - - Toggle - - ), }); diff --git a/packages/ui/src/components/ToggleButton/ToggleButton.tsx b/packages/ui/src/components/ToggleButton/ToggleButton.tsx index 612db4945c..c9956b4f22 100644 --- a/packages/ui/src/components/ToggleButton/ToggleButton.tsx +++ b/packages/ui/src/components/ToggleButton/ToggleButton.tsx @@ -43,7 +43,7 @@ export const ToggleButton = forwardRef( className={clsx(classNames.root, styles[classNames.root], className)} ref={ref} {...dataAttributes} - {...(bg ? { 'data-bg': bg } : {})} + {...(bg ? { 'data-on-bg': bg } : {})} {...rest} > {renderProps => { diff --git a/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx b/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx index 458d57683a..617cd0c0fa 100644 --- a/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx +++ b/packages/ui/src/components/ToggleButtonGroup/ToggleButtonGroup.stories.tsx @@ -137,19 +137,6 @@ export const Backgrounds = meta.story({ - - On Neutral 4 - - - Option 1 - Option 2 - Option 3 - - - ), }); diff --git a/packages/ui/src/hooks/useBg.tsx b/packages/ui/src/hooks/useBg.tsx index 7a681f9b19..fd3d4319e5 100644 --- a/packages/ui/src/hooks/useBg.tsx +++ b/packages/ui/src/hooks/useBg.tsx @@ -19,18 +19,18 @@ import { createVersionedContext, createVersionedValueMap, } from '@backstage/version-bridge'; -import { Bg, Responsive } from '../types'; +import { ContainerBg, Responsive } from '../types'; import { useBreakpoint } from './useBreakpoint'; import { resolveResponsiveValue } from './useDefinition/helpers'; /** @public */ export interface BgContextValue { - bg: Bg | undefined; + bg: ContainerBg | undefined; } /** @public */ export interface BgProviderProps { - bg: Bg; + bg: ContainerBg; children: ReactNode; } @@ -40,16 +40,18 @@ export interface UseBgOptions { * The bg mode of the component. * * - `'container'` — for components like Box, Card, Flex that establish bg context. - * If `bg` prop is provided, uses that value. Otherwise auto-increments from parent. + * If `bg` prop is provided, uses that value. Otherwise auto-increments from parent, + * capping at `neutral-3`. * - `'leaf'` — for components like Button that consume bg context. - * Always auto-increments from parent context. The `bg` prop is ignored. + * Returns the parent context bg unchanged (no increment). The leaf component's CSS + * handles the visual step-up. The `bg` prop is ignored. */ mode: 'container' | 'leaf'; /** * The explicit bg value from the component's prop. * Only used in container mode — leaf mode ignores this. */ - bg?: Responsive; + bg?: Responsive; } const BgContext = createVersionedContext<{ @@ -57,19 +59,23 @@ const BgContext = createVersionedContext<{ }>('bg-context'); /** - * Increments a neutral bg level by one, capping at 'neutral-4'. + * Increments a neutral bg level by one, capping at 'neutral-3'. * Intent backgrounds (danger, warning, success) pass through unchanged. * + * Only used by container components for auto-increment. The 'neutral-4' + * level is reserved for leaf components and is never set on containers. + * * @param bg - The current bg value * @returns The incremented bg value * @internal */ -function incrementNeutralBg(bg: Bg | undefined): Bg | undefined { +function incrementNeutralBg( + bg: ContainerBg | undefined, +): ContainerBg | undefined { if (!bg) return undefined; if (bg === 'neutral-1') return 'neutral-2'; if (bg === 'neutral-2') return 'neutral-3'; - if (bg === 'neutral-3') return 'neutral-4'; - if (bg === 'neutral-4') return 'neutral-4'; // capped + if (bg === 'neutral-3') return 'neutral-3'; // capped at neutral-3 // Intent values pass through unchanged return bg; } @@ -84,9 +90,9 @@ function incrementNeutralBg(bg: Bg | undefined): Bg | undefined { * @internal */ function resolveBgForContainer( - contextBg: Bg | undefined, - propBg: Bg | undefined, -): Bg | undefined { + contextBg: ContainerBg | undefined, + propBg: ContainerBg | undefined, +): ContainerBg | undefined { // Explicit bg prop takes priority if (propBg !== undefined) { return propBg; @@ -103,16 +109,16 @@ function resolveBgForContainer( /** * Resolves the bg value for a leaf component. * - * Always auto-increments from parent context. If no context, returns undefined. + * Returns the parent context bg unchanged. The leaf component's CSS + * handles the visual step-up (e.g. on neutral-1 surface → use neutral-2 tokens). + * If no context, returns undefined. * * @internal */ -function resolveBgForLeaf(contextBg: Bg | undefined): Bg | undefined { - if (contextBg === undefined) { - return undefined; - } - - return incrementNeutralBg(contextBg); +function resolveBgForLeaf( + contextBg: ContainerBg | undefined, +): ContainerBg | undefined { + return contextBg; } /** @@ -135,8 +141,8 @@ export const BgProvider = ({ bg, children }: BgProviderProps) => { * and (for containers) the explicit bg prop value. * * - **Container mode** — uses explicit `bg` if provided, otherwise auto-increments - * from parent context. Caps at `neutral-4`. - * - **Leaf mode** — always auto-increments from parent context. No prop needed. + * from parent context. Caps at `neutral-3`. + * - **Leaf mode** — returns the parent context bg unchanged. No prop needed. * - **No options** — returns the raw context value without resolution. * * @param options - Configuration for bg resolution diff --git a/packages/ui/src/hooks/useDefinition/types.ts b/packages/ui/src/hooks/useDefinition/types.ts index d7fe0aaf98..d28b7e8552 100644 --- a/packages/ui/src/hooks/useDefinition/types.ts +++ b/packages/ui/src/hooks/useDefinition/types.ts @@ -90,7 +90,7 @@ type DataAttributes = { [K in DataAttributeKeys as `data-${Lowercase< string & K >}`]?: string; -} & { 'data-bg'?: string }; +} & { 'data-bg'?: string; 'data-on-bg'?: string }; export type UtilityKeys> = D['utilityProps'] extends ReadonlyArray ? K : never; diff --git a/packages/ui/src/hooks/useDefinition/useDefinition.tsx b/packages/ui/src/hooks/useDefinition/useDefinition.tsx index 4de6d40443..e7a4caca97 100644 --- a/packages/ui/src/hooks/useDefinition/useDefinition.tsx +++ b/packages/ui/src/hooks/useDefinition/useDefinition.tsx @@ -72,9 +72,11 @@ export function useDefinition< } } - // Set data-bg from the resolved bg value (works for both container and leaf) + // Set the bg data attribute from the resolved bg value + // Containers use data-bg, leaf components use data-on-bg if (definition.bg && resolvedBg !== undefined) { - dataAttributes['data-bg'] = String(resolvedBg); + const attrName = definition.bg === 'leaf' ? 'data-on-bg' : 'data-bg'; + dataAttributes[attrName] = String(resolvedBg); } const { utilityClasses, utilityStyle } = processUtilityProps>( diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index 9587dd1142..4b0b783656 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -184,16 +184,18 @@ export interface ComponentDefinition { /** * Background type for the neutral bg system. * - * Supports neutral levels ('neutral-1' through 'neutral-4') and + * Supports neutral levels ('neutral-1' through 'neutral-3') and * intent backgrounds ('danger', 'warning', 'success'). * + * 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 */ -export type Bg = +export type ContainerBg = | 'neutral-1' | 'neutral-2' | 'neutral-3' - | 'neutral-4' | 'danger' | 'warning' | 'success';