diff --git a/.changeset/alert-remove-surface.md b/.changeset/alert-remove-surface.md index ed32bd38d2..fcdd9303e5 100644 --- a/.changeset/alert-remove-surface.md +++ b/.changeset/alert-remove-surface.md @@ -10,3 +10,5 @@ The Alert component's background is now driven entirely by its `status` prop. Th - + ``` + +**Affected components:** Alert diff --git a/.changeset/clean-bags-occur.md b/.changeset/clean-bags-occur.md index ca7cb06b1a..27986eee24 100644 --- a/.changeset/clean-bags-occur.md +++ b/.changeset/clean-bags-occur.md @@ -86,6 +86,6 @@ Update CSS selectors targeting surface data attributes: + [data-on-bg='neutral-1'] { ... } ``` -Note: Provider components use `data-bg` (values: `neutral-1` through `neutral-3`, plus intents). Consumer components use `data-on-bg`, which reflects the parent container's bg directly (no auto-increment). +Note: Provider components use `data-bg` (values: `neutral-1` through `neutral-3`, plus intents). Consumer components use `data-on-bg`, which reflects the parent container's `bg` directly. **Affected components:** Box, Button, ButtonIcon, ButtonLink, ToggleButton, Card, Flex, Grid diff --git a/packages/ui/src/components/Box/Box.tsx b/packages/ui/src/components/Box/Box.tsx index dc1a8521ea..fb87be9ae1 100644 --- a/packages/ui/src/components/Box/Box.tsx +++ b/packages/ui/src/components/Box/Box.tsx @@ -25,7 +25,7 @@ export const Box = forwardRef((props, ref) => { BoxDefinition, props, ); - const { classes, as, bgChildren } = ownProps; + const { classes, as, childrenWithBgProvider } = ownProps; return createElement( as, @@ -36,7 +36,7 @@ export const Box = forwardRef((props, ref) => { ...dataAttributes, ...restProps, }, - bgChildren, + childrenWithBgProvider, ); }); diff --git a/packages/ui/src/components/Box/definition.ts b/packages/ui/src/components/Box/definition.ts index 7c1150c2dc..3837dc8ea4 100644 --- a/packages/ui/src/components/Box/definition.ts +++ b/packages/ui/src/components/Box/definition.ts @@ -27,7 +27,7 @@ export const BoxDefinition = defineComponent()({ classNames: { root: 'bui-Box', }, - bg: { provider: true }, + bg: 'provider', propDefs: { as: { default: 'div' }, bg: { dataAttribute: true }, diff --git a/packages/ui/src/components/Button/definition.ts b/packages/ui/src/components/Button/definition.ts index 3007064a48..d15ceabd77 100644 --- a/packages/ui/src/components/Button/definition.ts +++ b/packages/ui/src/components/Button/definition.ts @@ -29,7 +29,7 @@ export const ButtonDefinition = defineComponent()({ content: 'bui-ButtonContent', spinner: 'bui-ButtonSpinner', }, - bg: { consumer: true }, + bg: 'consumer', propDefs: { size: { dataAttribute: true, default: 'small' }, variant: { dataAttribute: true, default: 'primary' }, diff --git a/packages/ui/src/components/ButtonIcon/definition.ts b/packages/ui/src/components/ButtonIcon/definition.ts index 3750a7f3d9..76f6be68ce 100644 --- a/packages/ui/src/components/ButtonIcon/definition.ts +++ b/packages/ui/src/components/ButtonIcon/definition.ts @@ -29,7 +29,7 @@ export const ButtonIconDefinition = defineComponent()({ content: 'bui-ButtonIconContent', spinner: 'bui-ButtonIconSpinner', }, - bg: { consumer: true }, + bg: 'consumer', propDefs: { size: { dataAttribute: true, default: 'small' }, variant: { dataAttribute: true, default: 'primary' }, diff --git a/packages/ui/src/components/ButtonLink/definition.ts b/packages/ui/src/components/ButtonLink/definition.ts index d528b90917..c86cb026b5 100644 --- a/packages/ui/src/components/ButtonLink/definition.ts +++ b/packages/ui/src/components/ButtonLink/definition.ts @@ -28,7 +28,7 @@ export const ButtonLinkDefinition = defineComponent()({ root: 'bui-ButtonLink', content: 'bui-ButtonLinkContent', }, - bg: { consumer: true }, + bg: 'consumer', propDefs: { size: { dataAttribute: true, default: 'small' }, variant: { dataAttribute: true, default: 'primary' }, diff --git a/packages/ui/src/components/Card/Card.module.css b/packages/ui/src/components/Card/Card.module.css index 5450c1feb4..445873f6ba 100644 --- a/packages/ui/src/components/Card/Card.module.css +++ b/packages/ui/src/components/Card/Card.module.css @@ -21,7 +21,6 @@ display: flex; flex-direction: column; gap: var(--bui-space-3); - background-color: var(--bui-bg-neutral-1); border-radius: var(--bui-radius-3); padding-block: var(--bui-space-3); color: var(--bui-fg-primary); @@ -30,18 +29,6 @@ width: 100%; } - .bui-Card[data-on-bg='neutral-1'] { - background-color: var(--bui-bg-neutral-2); - } - - .bui-Card[data-on-bg='neutral-2'] { - background-color: var(--bui-bg-neutral-3); - } - - .bui-Card[data-on-bg='neutral-3'] { - background-color: var(--bui-bg-neutral-4); - } - .bui-CardBody { flex: 1; min-height: 0; diff --git a/packages/ui/src/components/Card/Card.tsx b/packages/ui/src/components/Card/Card.tsx index 4e030fcc4c..e3e4781eac 100644 --- a/packages/ui/src/components/Card/Card.tsx +++ b/packages/ui/src/components/Card/Card.tsx @@ -28,6 +28,7 @@ import type { CardBodyProps, CardFooterProps, } from './types'; +import { Box } from '../Box/Box'; /** * Card component. @@ -39,12 +40,18 @@ export const Card = forwardRef((props, ref) => { CardDefinition, props, ); - const { classes, bgChildren } = ownProps; + const { classes, children } = ownProps; return ( -
- {bgChildren} -
+ + {children} + ); }); diff --git a/packages/ui/src/components/Card/definition.ts b/packages/ui/src/components/Card/definition.ts index 0fc56b482b..6493d01839 100644 --- a/packages/ui/src/components/Card/definition.ts +++ b/packages/ui/src/components/Card/definition.ts @@ -32,7 +32,6 @@ export const CardDefinition = defineComponent()({ classNames: { root: 'bui-Card', }, - bg: { provider: true, consumer: true, defaultBg: 'neutral-auto' }, propDefs: { children: {}, className: {}, diff --git a/packages/ui/src/hooks/useDefinition/types.ts b/packages/ui/src/hooks/useDefinition/types.ts index 925172d160..91ebdb8ef5 100644 --- a/packages/ui/src/hooks/useDefinition/types.ts +++ b/packages/ui/src/hooks/useDefinition/types.ts @@ -27,21 +27,6 @@ export interface PropDefConfig { export type UtilityPropKey = keyof typeof utilityClassMap; -/** - * Configuration for how a component participates in the bg system. - * - * - `provider` — calls `useBgProvider`, sets `data-bg`, wraps children in `BgProvider` - * - `consumer` — calls `useBgConsumer`, sets `data-on-bg` - * - `defaultBg` — default bg value when no `bg` prop is provided (e.g. `'neutral-auto'`) - * - * A component can be provider-only, consumer-only, or both. - */ -export interface BgConfig { - provider?: boolean; - consumer?: boolean; - defaultBg?: string; -} - export interface ComponentConfig< P extends Record, S extends Record, @@ -51,19 +36,22 @@ export interface ComponentConfig< propDefs: { [K in keyof P]: PropDefConfig }; // readonly for compatibility with const inference from factory utilityProps?: readonly UtilityPropKey[]; - bg?: BgConfig; + /** + * How this component participates in the bg system. + * + * - `'provider'` — calls `useBgProvider`, sets `data-bg`, wraps children in `BgProvider` + * - `'consumer'` — calls `useBgConsumer`, sets `data-on-bg` + */ + bg?: 'provider' | 'consumer'; } /** * Type constraint that validates bg props are present in the props type. - * - Provider-only components must include 'bg' in their props - * - Provider+consumer components (e.g. Card) don't need a bg prop (they auto-increment) - * - Consumer-only components don't need a bg prop + * - Provider components must include 'bg' in their props + * - Consumer components don't need a bg prop */ -export type BgPropsConstraint = Bg extends { provider: true } - ? Bg extends { consumer: true } - ? {} // provider+consumer: bg prop is optional (auto-increment via defaultBg) - : 'bg' extends keyof P +export type BgPropsConstraint = Bg extends 'provider' + ? 'bg' extends keyof P ? {} : { __error: 'Bg provider components must include bg in props type.'; @@ -93,11 +81,10 @@ type ResolvedOwnProps< [K in keyof PropDefs & keyof P]: ResolvePropType; }; -type ChildrenProps = Bg extends { - provider: true; -} - ? { bgChildren: ReactNode; children?: never } - : { children: ReactNode; bgChildren?: never }; +type ChildrenProps = + Bg extends 'provider' + ? { childrenWithBgProvider: ReactNode; children?: never } + : { children: ReactNode; childrenWithBgProvider?: never }; type DataAttributeKeys = { [K in keyof PropDefs]: PropDefs[K] extends { dataAttribute: true } diff --git a/packages/ui/src/hooks/useDefinition/useDefinition.tsx b/packages/ui/src/hooks/useDefinition/useDefinition.tsx index 15817a754c..d1fe9af96c 100644 --- a/packages/ui/src/hooks/useDefinition/useDefinition.tsx +++ b/packages/ui/src/hooks/useDefinition/useDefinition.tsx @@ -36,14 +36,10 @@ export function useDefinition< ): UseDefinitionResult { const { breakpoint } = useBreakpoint(); - // Resolve the effective bg value: use the bg prop if provided, - // otherwise fall back to the defaultBg from the bg config - const effectiveBg = definition.bg?.provider - ? props.bg ?? definition.bg.defaultBg - : undefined; - // Provider: resolve bg and provide context for children - const providerBg = useBgProvider(effectiveBg); + const providerBg = useBgProvider( + definition.bg === 'provider' ? props.bg : undefined, + ); // Consumer: read parent context bg const consumerBg = useBgConsumer(); @@ -74,7 +70,7 @@ export function useDefinition< ownPropsResolved[key] = finalValue; // Skip data-bg for bg prop when the provider path handles it - if (key === 'bg' && definition.bg?.provider) continue; + if (key === 'bg' && definition.bg === 'provider') continue; if ((config as any).dataAttribute) { // eslint-disable-next-line no-restricted-syntax @@ -83,17 +79,13 @@ export function useDefinition< } } - // Provider-only: set data-bg (provider+consumer components use data-on-bg instead) - if ( - definition.bg?.provider && - !definition.bg?.consumer && - providerBg.bg !== undefined - ) { + // Provider: set data-bg from the resolved provider bg + if (definition.bg === 'provider' && providerBg.bg !== undefined) { dataAttributes['data-bg'] = String(providerBg.bg); } // Consumer: set data-on-bg from the parent context - if (definition.bg?.consumer && consumerBg.bg !== undefined) { + if (definition.bg === 'consumer' && consumerBg.bg !== undefined) { dataAttributes['data-on-bg'] = String(consumerBg.bg); } @@ -117,10 +109,10 @@ export function useDefinition< } let children: ReactNode | undefined; - let bgChildren: ReactNode | undefined; + let childrenWithBgProvider: ReactNode | undefined; - if (definition.bg?.provider) { - bgChildren = providerBg.bg ? ( + if (definition.bg === 'provider') { + childrenWithBgProvider = providerBg.bg ? ( {props.children} ) : ( props.children @@ -133,7 +125,9 @@ export function useDefinition< ownProps: { classes, ...ownPropsResolved, - ...(definition.bg?.provider ? { bgChildren } : { children }), + ...(definition.bg === 'provider' + ? { childrenWithBgProvider } + : { children }), }, restProps, dataAttributes,