From e803a56352b5dfd53c9367e3a45c26191f68cd1b Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Fri, 6 Nov 2026 14:11:05 -0500 Subject: [PATCH 1/6] fix: scope css to sui- class prefix --- apps/storybook/src/stories/Card.stories.tsx | 15 +-- .../storybook/src/stories/Divider.stories.tsx | 5 +- apps/storybook/src/stories/HStack.stories.tsx | 25 +++-- apps/storybook/src/stories/Inline.stories.tsx | 13 ++- apps/storybook/src/stories/Tabs.stories.tsx | 33 +++++-- apps/storybook/src/stories/VStack.stories.tsx | 25 +++-- apps/storybook/src/styles/storybook.css | 10 +- packages/ui/src/css/global/reset.css | 95 ++++++++++--------- 8 files changed, 141 insertions(+), 80 deletions(-) diff --git a/apps/storybook/src/stories/Card.stories.tsx b/apps/storybook/src/stories/Card.stories.tsx index 64e2a7018b..6f62d33283 100644 --- a/apps/storybook/src/stories/Card.stories.tsx +++ b/apps/storybook/src/stories/Card.stories.tsx @@ -5,6 +5,7 @@ import {Card as CardV3} from 'ui3' import {Card} from '../../../../packages/ui/src/components/card/Card' import {cardProps} from '../../../../packages/ui/src/components/card/card.props' import {HStack} from '../../../../packages/ui/src/components/h-stack/HStack' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {TONE_WITH_DEFAULT} from '../../../../packages/ui/src/types/Tone' import {getArgTypes} from '../utils/getArgTypes' @@ -13,7 +14,7 @@ const argTypes = getArgTypes(cardProps) const meta: Meta = { title: 'Components/Card', args: { - children: 'This is a Card component.', + children: This is a Card component., as: 'div', }, argTypes, @@ -38,7 +39,9 @@ export const Default: Story = { return }, play: async ({canvas}) => { - await expect((await canvas.findByText('This is a Card component.')).dataset.ui).toBe('Card') + await expect( + (await canvas.findByText('This is a Card component.')).parentElement?.dataset.ui, + ).toBe('Card') }, } @@ -48,15 +51,15 @@ export const Tones: Story = { {TONE_WITH_DEFAULT.map((tone) => ( - {`Card ${tone} tone`} + {`Card ${tone} tone`} ))} ) }, play: async ({canvas}) => { - await expect((await canvas.findByText('Card positive tone')).classList).toContain( - 'sui-tone-positive', - ) + await expect( + (await canvas.findByText('Card positive tone')).parentElement?.classList, + ).toContain('sui-tone-positive') }, } diff --git a/apps/storybook/src/stories/Divider.stories.tsx b/apps/storybook/src/stories/Divider.stories.tsx index 82898a5f28..b19205415b 100644 --- a/apps/storybook/src/stories/Divider.stories.tsx +++ b/apps/storybook/src/stories/Divider.stories.tsx @@ -3,6 +3,7 @@ import {expect} from 'storybook/test' import {Divider} from '../../../../packages/ui/src/components/divider/Divider' import {dividerProps} from '../../../../packages/ui/src/components/divider/divider.props' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {getArgTypes} from '../utils/getArgTypes' const argTypes = getArgTypes(dividerProps) @@ -29,9 +30,9 @@ export const Default: Story = { render: (props) => { return ( <> -

Content above

+ Content above -

Content below

+ Content below ) }, diff --git a/apps/storybook/src/stories/HStack.stories.tsx b/apps/storybook/src/stories/HStack.stories.tsx index f0308f4ecb..e8b54c4eb2 100644 --- a/apps/storybook/src/stories/HStack.stories.tsx +++ b/apps/storybook/src/stories/HStack.stories.tsx @@ -3,6 +3,7 @@ import {expect} from 'storybook/test' import {Card} from '../../../../packages/ui/src/components/card/Card' import {HStack} from '../../../../packages/ui/src/components/h-stack/HStack' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {SPACE_INHERIT} from '../../../../packages/ui/src/types/Space' import {Square} from '../components/Square' import {getArgTypes} from '../utils/getArgTypes' @@ -40,9 +41,15 @@ export const Default: Story = { render: (props) => { return ( - Child 1 - Child 2 - Child 3 + + Child 1 + + + Child 2 + + + Child 3 + ) }, @@ -58,9 +65,15 @@ export const Inherit: Story = { return ( - Child 1 - Child 2 - Child 3 + + Child 1 + + + Child 2 + + + Child 3 + ) diff --git a/apps/storybook/src/stories/Inline.stories.tsx b/apps/storybook/src/stories/Inline.stories.tsx index b9ebcb568c..de89c077bd 100644 --- a/apps/storybook/src/stories/Inline.stories.tsx +++ b/apps/storybook/src/stories/Inline.stories.tsx @@ -4,6 +4,7 @@ import {Inline as InlineV3} from 'ui3' import {Inline} from '../../../../packages/ui/src/components/inline/Inline' import {inlineProps} from '../../../../packages/ui/src/components/inline/inline.props' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {Square} from '../components/Square' import {getArgTypes} from '../utils/getArgTypes' @@ -35,9 +36,15 @@ export const Default: Story = { render: (props) => { return ( - Child 1 - Child 2 - Child 3 + + Child 1 + + + Child 2 + + + Child 3 + ) }, diff --git a/apps/storybook/src/stories/Tabs.stories.tsx b/apps/storybook/src/stories/Tabs.stories.tsx index 359ede60e4..ca0ce62829 100644 --- a/apps/storybook/src/stories/Tabs.stories.tsx +++ b/apps/storybook/src/stories/Tabs.stories.tsx @@ -11,6 +11,7 @@ import {Box} from '../../../../packages/ui/src/components/box/Box' import {Card} from '../../../../packages/ui/src/components/card/Card' import {Tabs} from '../../../../packages/ui/src/components/tabs/Tabs' import {type TabsProps, tabsProps} from '../../../../packages/ui/src/components/tabs/tabs.props' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {getArgTypes} from '../utils/getArgTypes' const argTypes = getArgTypes(tabsProps) @@ -45,9 +46,15 @@ function TabsDefaultStory(props: TabsProps) { - First tab panel - Second tab panel - Third tab panel + + First tab panel + + + Second tab panel + + + Third tab panel + ) @@ -72,19 +79,29 @@ function TabsTonesAndIconsStory(props: TabsProps) { - Neutral Card in tab panel + + Neutral Card in tab panel + - Positive Card in tab panel + + Positive Card in tab panel + - Suggest Card in tab panel + + Suggest Card in tab panel + - Caution Card in tab panel + + Caution Card in tab panel + - Critical Card in tab panel + + Critical Card in tab panel + diff --git a/apps/storybook/src/stories/VStack.stories.tsx b/apps/storybook/src/stories/VStack.stories.tsx index b19cbfbfd5..5ec398f4ee 100644 --- a/apps/storybook/src/stories/VStack.stories.tsx +++ b/apps/storybook/src/stories/VStack.stories.tsx @@ -3,6 +3,7 @@ import {expect} from 'storybook/test' import {Stack as StackV3} from 'ui3' import {Card} from '../../../../packages/ui/src/components/card/Card' +import {Text} from '../../../../packages/ui/src/components/text/Text' import {VStack} from '../../../../packages/ui/src/components/v-stack/VStack' import {SPACE_INHERIT} from '../../../../packages/ui/src/types/Space' import {Square} from '../components/Square' @@ -42,9 +43,15 @@ export const Default: Story = { render: (props) => { return ( - Child 1 - Child 2 - Child 3 + + Child 1 + + + Child 2 + + + Child 3 + ) }, @@ -60,9 +67,15 @@ export const Inherit: Story = { return ( - Child 1 - Child 2 - Child 3 + + Child 1 + + + Child 2 + + + Child 3 + ) diff --git a/apps/storybook/src/styles/storybook.css b/apps/storybook/src/styles/storybook.css index b8a7594f88..884156f082 100644 --- a/apps/storybook/src/styles/storybook.css +++ b/apps/storybook/src/styles/storybook.css @@ -1,7 +1,13 @@ -html.dark body { +html body { + background: light-dark(var(--white), var(--black)); +} + +html.dark body, +html.dark body * { color-scheme: dark; } -html.light body { +html.light body, +html.light body * { color-scheme: light; } diff --git a/packages/ui/src/css/global/reset.css b/packages/ui/src/css/global/reset.css index d4be5c6155..dad10ecbcf 100644 --- a/packages/ui/src/css/global/reset.css +++ b/packages/ui/src/css/global/reset.css @@ -1,56 +1,51 @@ +/* Prevent adjustments of font size after orientation changes in iOS. */ +:where(html) { + -webkit-text-size-adjust: 100%; +} + +/* Reset font and color-scheme for first sui- class in a tree */ +:where([class*="sui-"]):not(:where([class*="sui-"]) :where([class*="sui-"])) { + font-family: var(--sans); + -webkit-font-smoothing: antialiased; + color-scheme: light dark; +} + /* Default to border-box sizing */ -*, -*::before, -*::after { +:where([class*="sui-"]), +:where([class*="sui-"]) *, +:where([class*="sui-"]) *::before, +:where([class*="sui-"]) *::after { box-sizing: border-box; } /* Zero out default margins, padding, and borders */ -* { +:where([class*="sui-"]), +:where([class*="sui-"]) * { margin: 0; padding: 0; border: 0 solid transparent; } -:root { - color-scheme: light dark; -} - -/* Prevent adjustments of font size after orientation changes in iOS. */ -:where(html) { - -webkit-text-size-adjust: 100%; -} - -:where(body) { - background: light-dark(var(--white), var(--black)); - font-family: var(--sans); - -webkit-font-smoothing: antialiased; -} - /* Display multimedia as block by default */ -:where( - audio, - canvas, - embed, - iframe, - img, - object, - picture, - video -){ +:is( + :where([class*="sui-"]) :where(audio, canvas, embed, iframe, img, object, picture, video), + :where(audio, canvas, embed, iframe, img, object, picture, video):where([class*="sui-"]) +) { display: block; max-width: 100%; } -:where(img, picture, video) { + +:is( + :where([class*="sui-"]) :where(img, picture, video), + :where(img, picture, video):where([class*="sui-"]) +) { block-size: auto; } /* Inherit typography in form controls */ -:where( - button, - input, - select, - textarea +:is( + :where([class*="sui-"]) :where(button, input, select, textarea), + :where(button, input, select, textarea):where([class*="sui-"]) ) { appearance: none; color: inherit; @@ -59,30 +54,36 @@ } /* Remove user agent reduced opacity on disabled form elements */ -:where( - button, - input, - select, - textarea -):disabled { +:is( + :where([class*="sui-"]) :where(button, input, select, textarea):disabled, + :where(button, input, select, textarea):where([class*="sui-"]):disabled +) { opacity: 1; } /* Remove excess space for table borders */ -:where(table) { +:is( + :where([class*="sui-"]) :where(table), + :where(table):where([class*="sui-"]) +) { border-collapse: collapse; border-spacing: 0; } -:where(code) { +/* Inherit typography for code blocks */ +:is( + :where([class*="sui-"]) :where(code), + :where(code):where([class*="sui-"]) +) { font-family: var(--mono); } -/* Enforce no animations for users that prefer reduced motion*/ +/* Enforce no animations for users that prefer reduced motion (whole sui subtree — same coverage as box-sizing above; no “outer root only” needed) */ @media (prefers-reduced-motion: reduce) { - *, - *::before, - *::after { + :where([class*="sui-"]), + :where([class*="sui-"]) *, + :where([class*="sui-"]) *::before, + :where([class*="sui-"]) *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; From d3b0cab6ca9a0b5f8d34587bc7ae528ae600dc4b Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Fri, 6 Nov 2026 14:36:47 -0500 Subject: [PATCH 2/6] fix: update lightningcss config --- apps/storybook/.storybook/main.ts | 13 +++++++++++++ apps/storybook/package.json | 1 + pnpm-lock.yaml | 3 +++ 3 files changed, 17 insertions(+) diff --git a/apps/storybook/.storybook/main.ts b/apps/storybook/.storybook/main.ts index c602cf97d8..4c278b9bd0 100644 --- a/apps/storybook/.storybook/main.ts +++ b/apps/storybook/.storybook/main.ts @@ -1,4 +1,5 @@ import type {StorybookConfig} from '@storybook/react-vite' +import {Features} from 'lightningcss' const config: StorybookConfig = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], @@ -16,5 +17,17 @@ const config: StorybookConfig = { shouldExtractLiteralValuesFromEnum: true, }, }, + async viteFinal(viteConfig) { + return { + ...viteConfig, + css: { + ...viteConfig.css, + lightningcss: { + ...viteConfig.css?.lightningcss, + exclude: Features.LightDark, + }, + }, + } + }, } export default config diff --git a/apps/storybook/package.json b/apps/storybook/package.json index aa185506cb..ce17fbaed4 100644 --- a/apps/storybook/package.json +++ b/apps/storybook/package.json @@ -29,6 +29,7 @@ "@vitejs/plugin-react": "catalog:", "@vitest/browser-playwright": "^4.1.1", "@vitest/coverage-v8": "^4.1.1", + "lightningcss": "^1.33.0", "oxc-transform-react": "catalog:", "playwright": "^1.58.2", "storybook": "^10.3.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e82fef3090..cb9303aea7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -399,6 +399,9 @@ importers: '@vitest/coverage-v8': specifier: ^4.1.1 version: 4.1.1(@vitest/browser@4.1.1(vite@8.2.2(@types/node@24.12.0)(esbuild@0.28.1)(jiti@2.6.1)(terser@5.46.1)(tsx@4.23.5)(yaml@2.8.3))(vitest@4.1.1))(vitest@4.1.1) + lightningcss: + specifier: ^1.33.0 + version: 1.33.0 oxc-transform-react: specifier: 'catalog:' version: 0.149.0 From 64209a430562e332275b785323b3bdc8048f97cd Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Fri, 6 Nov 2026 14:39:59 -0500 Subject: [PATCH 3/6] fix: update tab stories --- apps/storybook/src/stories/Tabs.stories.tsx | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/apps/storybook/src/stories/Tabs.stories.tsx b/apps/storybook/src/stories/Tabs.stories.tsx index ca0ce62829..08b50abb7c 100644 --- a/apps/storybook/src/stories/Tabs.stories.tsx +++ b/apps/storybook/src/stories/Tabs.stories.tsx @@ -119,14 +119,17 @@ export const Default: Story = { await expect(firstTab).toHaveAttribute('aria-selected', 'true') await expect(secondTab).toHaveAttribute('aria-selected', 'false') - await expect(canvas.getByText('First tab panel')).toBeVisible() - await expect(canvas.getByText('Second tab panel')).not.toBeVisible() + await expect(canvas.getByText('First tab panel').parentElement).toBeVisible() + await expect(canvas.getByText('Second tab panel').parentElement).not.toBeVisible() - await expect(canvas.getByText('First tab panel')).toHaveAttribute( + await expect(canvas.getByText('First tab panel').parentElement).toHaveAttribute( 'aria-labelledby', firstTab.id, ) - await expect(firstTab).toHaveAttribute('aria-controls', canvas.getByText('First tab panel').id) + await expect(firstTab).toHaveAttribute( + 'aria-controls', + canvas.getByText('First tab panel').parentElement?.id, + ) }, } @@ -170,8 +173,8 @@ export const Interactions: Story = { await expect(secondTab).toHaveAttribute('aria-selected', 'true') await expect(firstTab).toHaveAttribute('aria-selected', 'false') - await expect(canvas.getByText('Second tab panel')).toBeVisible() - await expect(canvas.getByText('First tab panel')).not.toBeVisible() + await expect(canvas.getByText('Second tab panel').parentElement).toBeVisible() + await expect(canvas.getByText('First tab panel').parentElement).not.toBeVisible() }) await step('Only the selected tab is in the tab sequence', async () => { @@ -219,12 +222,12 @@ export const Interactions: Story = { await step('Enter and Space select the focused tab', async () => { await userEvent.keyboard('{Enter}') await expect(thirdTab).toHaveAttribute('aria-selected', 'true') - await expect(canvas.getByText('Third tab panel')).toBeVisible() + await expect(canvas.getByText('Third tab panel').parentElement).toBeVisible() await userEvent.keyboard('{Home}') await userEvent.keyboard(' ') await expect(firstTab).toHaveAttribute('aria-selected', 'true') - await expect(canvas.getByText('First tab panel')).toBeVisible() + await expect(canvas.getByText('First tab panel').parentElement).toBeVisible() }) await step( @@ -234,7 +237,7 @@ export const Interactions: Story = { await expect(thirdTab).toHaveFocus() await userEvent.tab() - await expect(canvas.getByText('First tab panel')).toHaveFocus() + await expect(canvas.getByText('First tab panel').parentElement).toHaveFocus() await userEvent.tab({shift: true}) await expect(firstTab).toHaveFocus() From d4f13bdcb21caa7f332fc0766b723f53c3ff4f28 Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Fri, 6 Nov 2026 14:51:28 -0500 Subject: [PATCH 4/6] fix: remove extra comment --- packages/ui/src/css/global/reset.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/css/global/reset.css b/packages/ui/src/css/global/reset.css index dad10ecbcf..13cc3f6852 100644 --- a/packages/ui/src/css/global/reset.css +++ b/packages/ui/src/css/global/reset.css @@ -78,7 +78,7 @@ font-family: var(--mono); } -/* Enforce no animations for users that prefer reduced motion (whole sui subtree — same coverage as box-sizing above; no “outer root only” needed) */ +/* Enforce no animations for users that prefer reduced motion */ @media (prefers-reduced-motion: reduce) { :where([class*="sui-"]), :where([class*="sui-"]) *, From 77dfc9cfa22868d81e3c5f076bf88c45da86bc57 Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Tue, 10 Nov 2026 17:06:56 -0500 Subject: [PATCH 5/6] fix: move color scheme back to root --- packages/ui/src/css/global/reset.css | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ui/src/css/global/reset.css b/packages/ui/src/css/global/reset.css index 13cc3f6852..1adc3b3368 100644 --- a/packages/ui/src/css/global/reset.css +++ b/packages/ui/src/css/global/reset.css @@ -1,3 +1,7 @@ +:root { + color-scheme: light dark; +} + /* Prevent adjustments of font size after orientation changes in iOS. */ :where(html) { -webkit-text-size-adjust: 100%; @@ -7,7 +11,6 @@ :where([class*="sui-"]):not(:where([class*="sui-"]) :where([class*="sui-"])) { font-family: var(--sans); -webkit-font-smoothing: antialiased; - color-scheme: light dark; } /* Default to border-box sizing */ From 54cb8576bdc69d1326ee68128c1b3f8498c57e56 Mon Sep 17 00:00:00 2001 From: laurenashpole Date: Fri, 13 Nov 2026 12:16:36 -0500 Subject: [PATCH 6/6] fix: add where to root color scheme --- apps/storybook/src/styles/storybook.css | 6 ++---- packages/ui/src/css/global/reset.css | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/storybook/src/styles/storybook.css b/apps/storybook/src/styles/storybook.css index 884156f082..1d8267ae6e 100644 --- a/apps/storybook/src/styles/storybook.css +++ b/apps/storybook/src/styles/storybook.css @@ -2,12 +2,10 @@ html body { background: light-dark(var(--white), var(--black)); } -html.dark body, -html.dark body * { +html.dark body { color-scheme: dark; } -html.light body, -html.light body * { +html.light body { color-scheme: light; } diff --git a/packages/ui/src/css/global/reset.css b/packages/ui/src/css/global/reset.css index 1adc3b3368..8442b89c97 100644 --- a/packages/ui/src/css/global/reset.css +++ b/packages/ui/src/css/global/reset.css @@ -1,4 +1,4 @@ -:root { +:where(:root) { color-scheme: light dark; }