From 591d8a2483cf335635f6e8ebb0a60c26cc3f70e4 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Tue, 23 Dec 2025 08:23:37 +0100 Subject: [PATCH] Add surfaces to Flex and Grid Signed-off-by: Charles de Dreuille --- packages/ui/report.api.md | 23 ++++++++++ .../ui/src/components/Flex/Flex.module.css | 16 +++++++ .../ui/src/components/Flex/Flex.stories.tsx | 27 ++++++++++++ packages/ui/src/components/Flex/Flex.tsx | 18 +++++--- packages/ui/src/components/Flex/definition.ts | 3 ++ packages/ui/src/components/Flex/types.ts | 3 +- .../ui/src/components/Grid/Grid.module.css | 20 +++++++++ .../ui/src/components/Grid/Grid.stories.tsx | 44 +++++++++++++++++++ packages/ui/src/components/Grid/Grid.tsx | 35 ++++++++++----- packages/ui/src/components/Grid/definition.ts | 6 +++ packages/ui/src/components/Grid/types.ts | 10 ++++- 11 files changed, 185 insertions(+), 20 deletions(-) diff --git a/packages/ui/report.api.md b/packages/ui/report.api.md index 0a7e289d0a..ec0fad7e7a 100644 --- a/packages/ui/report.api.md +++ b/packages/ui/report.api.md @@ -194,6 +194,9 @@ export const BoxDefinition: { 'minHeight', 'maxHeight', ]; + readonly dataAttributes: { + readonly surface: readonly ['0', '1', '2', '3']; + }; }; // @public (undocumented) @@ -223,6 +226,8 @@ export interface BoxProps extends SpaceProps { // (undocumented) style?: React.CSSProperties; // (undocumented) + surface?: Responsive; + // (undocumented) width?: Responsive; } @@ -657,6 +662,9 @@ export const FlexDefinition: { 'justify', 'direction', ]; + readonly dataAttributes: { + readonly surface: readonly ['0', '1', '2', '3']; + }; }; // @public (undocumented) @@ -678,6 +686,8 @@ export interface FlexProps extends SpaceProps { justify?: Responsive<'start' | 'center' | 'end' | 'between'>; // (undocumented) style?: React.CSSProperties; + // (undocumented) + surface?: Responsive; } // @public (undocumented) @@ -714,6 +724,9 @@ export const GridDefinition: { 'px', 'py', ]; + readonly dataAttributes: { + readonly surface: readonly ['0', '1', '2', '3']; + }; }; // @public @@ -722,6 +735,9 @@ export const GridItemDefinition: { readonly root: 'bui-GridItem'; }; readonly utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan']; + readonly dataAttributes: { + readonly surface: readonly ['0', '1', '2', '3']; + }; }; // @public (undocumented) @@ -740,6 +756,8 @@ export interface GridItemProps { rowSpan?: Responsive; // (undocumented) style?: React.CSSProperties; + // (undocumented) + surface?: Responsive; } // @public (undocumented) @@ -754,6 +772,8 @@ export interface GridProps extends SpaceProps { gap?: Responsive; // (undocumented) style?: React.CSSProperties; + // (undocumented) + surface?: Responsive; } // @public @@ -1229,6 +1249,9 @@ export const SubmenuTrigger: (props: SubmenuTriggerProps) => JSX_2.Element; // @public (undocumented) export interface SubmenuTriggerProps extends SubmenuTriggerProps_2 {} +// @public +export type Surface = '0' | '1' | '2' | '3'; + // @public (undocumented) export const Switch: ForwardRefExoticComponent< SwitchProps & RefAttributes diff --git a/packages/ui/src/components/Flex/Flex.module.css b/packages/ui/src/components/Flex/Flex.module.css index 0d44fbd12f..76c0eb33dd 100644 --- a/packages/ui/src/components/Flex/Flex.module.css +++ b/packages/ui/src/components/Flex/Flex.module.css @@ -23,4 +23,20 @@ /* This helps when using `truncate` on text inside a flex container */ min-width: 0; } + + .bui-Flex[data-surface='0'] { + background-color: var(--bui-bg-surface-0); + } + + .bui-Flex[data-surface='1'] { + background-color: var(--bui-bg-surface-1); + } + + .bui-Flex[data-surface='2'] { + background-color: var(--bui-bg-surface-2); + } + + .bui-Flex[data-surface='3'] { + background-color: var(--bui-bg-surface-3); + } } diff --git a/packages/ui/src/components/Flex/Flex.stories.tsx b/packages/ui/src/components/Flex/Flex.stories.tsx index 17ee740997..411025914d 100644 --- a/packages/ui/src/components/Flex/Flex.stories.tsx +++ b/packages/ui/src/components/Flex/Flex.stories.tsx @@ -243,3 +243,30 @@ export const WithTextTruncate = meta.story({ ), }); + +export const Surfaces = meta.story({ + args: { + px: '6', + py: '4', + }, + render: args => ( + + Default + + Surface 0 + + + Surface 1 + + + Surface 2 + + + Surface 3 + + + Responsive Surface + + + ), +}); diff --git a/packages/ui/src/components/Flex/Flex.tsx b/packages/ui/src/components/Flex/Flex.tsx index 878bcfe0ea..6ad248d3a4 100644 --- a/packages/ui/src/components/Flex/Flex.tsx +++ b/packages/ui/src/components/Flex/Flex.tsx @@ -20,17 +20,16 @@ import clsx from 'clsx'; import { useStyles } from '../../hooks/useStyles'; import { FlexDefinition } from './definition'; import styles from './Flex.module.css'; +import { SurfaceProvider } from '../../hooks/useSurface'; /** @public */ export const Flex = forwardRef((props, ref) => { - const { classNames, utilityClasses, style, cleanedProps } = useStyles( - FlexDefinition, - { gap: '4', ...props }, - ); + const { classNames, dataAttributes, utilityClasses, style, cleanedProps } = + useStyles(FlexDefinition, { gap: '4', ...props }); - const { className, ...rest } = cleanedProps; + const { className, surface, ...rest } = cleanedProps; - return ( + const content = (
((props, ref) => { className, )} style={style} + {...dataAttributes} {...rest} /> ); + + return surface ? ( + {content} + ) : ( + content + ); }); diff --git a/packages/ui/src/components/Flex/definition.ts b/packages/ui/src/components/Flex/definition.ts index d6902e2f47..82e216addc 100644 --- a/packages/ui/src/components/Flex/definition.ts +++ b/packages/ui/src/components/Flex/definition.ts @@ -44,4 +44,7 @@ export const FlexDefinition = { 'justify', 'direction', ], + dataAttributes: { + surface: ['0', '1', '2', '3'] as const, + }, } as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Flex/types.ts b/packages/ui/src/components/Flex/types.ts index 7699e0ddc5..33bc476f93 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 } from '../../types'; +import type { Responsive, Space, SpaceProps, Surface } from '../../types'; /** @public */ export interface FlexProps extends SpaceProps { @@ -25,4 +25,5 @@ export interface FlexProps extends SpaceProps { direction?: Responsive<'row' | 'column' | 'row-reverse' | 'column-reverse'>; className?: string; style?: React.CSSProperties; + surface?: Responsive; } diff --git a/packages/ui/src/components/Grid/Grid.module.css b/packages/ui/src/components/Grid/Grid.module.css index ff98e9337f..abe22ad6a9 100644 --- a/packages/ui/src/components/Grid/Grid.module.css +++ b/packages/ui/src/components/Grid/Grid.module.css @@ -20,4 +20,24 @@ .bui-Grid { display: grid; } + + .bui-Grid[data-surface='0'], + .bui-GridItem[data-surface='0'] { + background-color: var(--bui-bg-surface-0); + } + + .bui-Grid[data-surface='1'], + .bui-GridItem[data-surface='1'] { + background-color: var(--bui-bg-surface-1); + } + + .bui-Grid[data-surface='2'], + .bui-GridItem[data-surface='2'] { + background-color: var(--bui-bg-surface-2); + } + + .bui-Grid[data-surface='3'], + .bui-GridItem[data-surface='3'] { + background-color: var(--bui-bg-surface-3); + } } diff --git a/packages/ui/src/components/Grid/Grid.stories.tsx b/packages/ui/src/components/Grid/Grid.stories.tsx index 56251b6085..12943dc5bc 100644 --- a/packages/ui/src/components/Grid/Grid.stories.tsx +++ b/packages/ui/src/components/Grid/Grid.stories.tsx @@ -103,3 +103,47 @@ export const RowAndColumns = meta.story({ ), }); + +export const Surfaces = meta.story({ + args: { px: '6', py: '4' }, + render: args => ( + + + + Surface 0 + + + Surface 1 + + + Surface 2 + + + Surface 3 + + + Responsive Surface + + + + + Surface 0 + + + Surface 1 + + + Surface 2 + + + Surface 3 + + + + Responsive Surface + + + + + ), +}); diff --git a/packages/ui/src/components/Grid/Grid.tsx b/packages/ui/src/components/Grid/Grid.tsx index aa30d25fc0..b2fc401ca8 100644 --- a/packages/ui/src/components/Grid/Grid.tsx +++ b/packages/ui/src/components/Grid/Grid.tsx @@ -20,16 +20,15 @@ import type { GridItemProps, GridProps } from './types'; import { useStyles } from '../../hooks/useStyles'; import { GridDefinition, GridItemDefinition } from './definition'; import styles from './Grid.module.css'; +import { SurfaceProvider } from '../../hooks/useSurface'; const GridRoot = forwardRef((props, ref) => { - const { classNames, utilityClasses, style, cleanedProps } = useStyles( - GridDefinition, - { columns: 'auto', gap: '4', ...props }, - ); + const { classNames, dataAttributes, utilityClasses, style, cleanedProps } = + useStyles(GridDefinition, { columns: 'auto', gap: '4', ...props }); - const { className, ...rest } = cleanedProps; + const { className, surface, ...rest } = cleanedProps; - return ( + const content = (
((props, ref) => { className, )} style={style} + {...dataAttributes} {...rest} /> ); + + return surface ? ( + {content} + ) : ( + content + ); }); const GridItem = forwardRef((props, ref) => { - const { classNames, utilityClasses, style, cleanedProps } = useStyles( - GridItemDefinition, - props, - ); + const { classNames, dataAttributes, utilityClasses, style, cleanedProps } = + useStyles(GridItemDefinition, props); - const { className, ...rest } = cleanedProps; + const { className, surface, ...rest } = cleanedProps; - return ( + const content = (
((props, ref) => { className, )} style={style} + {...dataAttributes} {...rest} /> ); + + return surface ? ( + {content} + ) : ( + content + ); }); /** @public */ diff --git a/packages/ui/src/components/Grid/definition.ts b/packages/ui/src/components/Grid/definition.ts index 201ef4dc66..267c6fc872 100644 --- a/packages/ui/src/components/Grid/definition.ts +++ b/packages/ui/src/components/Grid/definition.ts @@ -42,6 +42,9 @@ export const GridDefinition = { 'px', 'py', ], + dataAttributes: { + surface: ['0', '1', '2', '3'] as const, + }, } as const satisfies ComponentDefinition; /** @@ -53,4 +56,7 @@ export const GridItemDefinition = { root: 'bui-GridItem', }, utilityProps: ['colSpan', 'colEnd', 'colStart', 'rowSpan'], + dataAttributes: { + surface: ['0', '1', '2', '3'] as const, + }, } as const satisfies ComponentDefinition; diff --git a/packages/ui/src/components/Grid/types.ts b/packages/ui/src/components/Grid/types.ts index d9d18b4718..f5ce9ca9cb 100644 --- a/packages/ui/src/components/Grid/types.ts +++ b/packages/ui/src/components/Grid/types.ts @@ -14,7 +14,13 @@ * limitations under the License. */ -import type { Space, SpaceProps, Responsive, Columns } from '../../types'; +import type { + Space, + SpaceProps, + Responsive, + Columns, + Surface, +} from '../../types'; /** @public */ export interface GridProps extends SpaceProps { @@ -23,6 +29,7 @@ export interface GridProps extends SpaceProps { columns?: Responsive; gap?: Responsive; style?: React.CSSProperties; + surface?: Responsive; } /** @public */ @@ -34,4 +41,5 @@ export interface GridItemProps { colStart?: Responsive; rowSpan?: Responsive; style?: React.CSSProperties; + surface?: Responsive; }