diff --git a/.changeset/migrate-spacer-to-css-modules.md b/.changeset/migrate-spacer-to-css-modules.md new file mode 100644 index 000000000..6fff6ca11 --- /dev/null +++ b/.changeset/migrate-spacer-to-css-modules.md @@ -0,0 +1,5 @@ +--- +'@clickhouse/click-ui': patch +--- + +Migrate Spacer from styled-components to css modules with no change in behavior diff --git a/src/components/Spacer/Spacer.module.css b/src/components/Spacer/Spacer.module.css new file mode 100644 index 000000000..7c1e1833c --- /dev/null +++ b/src/components/Spacer/Spacer.module.css @@ -0,0 +1,28 @@ +.spacer { + display: flex; + background: transparent; +} + +.spacer_size_xs { + padding: var(--click-spacer-horizontal-space-y-xs) var(--click-spacer-horizontal-space-x-all); +} + +.spacer_size_sm { + padding: var(--click-spacer-horizontal-space-y-sm) var(--click-spacer-horizontal-space-x-all); +} + +.spacer_size_md { + padding: var(--click-spacer-horizontal-space-y-md) var(--click-spacer-horizontal-space-x-all); +} + +.spacer_size_lg { + padding: var(--click-spacer-horizontal-space-y-lg) var(--click-spacer-horizontal-space-x-all); +} + +.spacer_size_xl { + padding: var(--click-spacer-horizontal-space-y-xl) var(--click-spacer-horizontal-space-x-all); +} + +.spacer_size_xxl { + padding: var(--click-spacer-horizontal-space-y-xxl) var(--click-spacer-horizontal-space-x-all); +} diff --git a/src/components/Spacer/Spacer.stories.tsx b/src/components/Spacer/Spacer.stories.tsx index 3dd6a97b9..2ffc72dd7 100644 --- a/src/components/Spacer/Spacer.stories.tsx +++ b/src/components/Spacer/Spacer.stories.tsx @@ -1,5 +1,6 @@ import { Meta, StoryObj } from '@storybook/react-vite'; import { Spacer } from '@/components/Spacer'; +import type { SizeType } from '@/components/Spacer'; const meta: Meta = { component: Spacer, @@ -11,8 +12,53 @@ export default meta; type Story = StoryObj; +const SpacerHarness = ({ size }: { size?: SizeType }) => ( +
+
+ +
+
+); + export const Playground: Story = { args: { size: 'xxl', }, }; + +export const SizeXs: Story = { + render: () => , +}; + +export const SizeSm: Story = { + render: () => , +}; + +export const SizeMd: Story = { + render: () => , +}; + +export const SizeLg: Story = { + render: () => , +}; + +export const SizeXl: Story = { + render: () => , +}; + +export const SizeXxl: Story = { + render: () => , +}; + +export const DefaultSize: Story = { + render: () => , +}; diff --git a/src/components/Spacer/Spacer.tsx b/src/components/Spacer/Spacer.tsx index e44ea6290..dfe8eb3d3 100644 --- a/src/components/Spacer/Spacer.tsx +++ b/src/components/Spacer/Spacer.tsx @@ -1,13 +1,23 @@ -import { styled } from 'styled-components'; -import { SpacerProps, SizeType } from './Spacer.types'; +import { cn, cva } from '@/lib/cva'; +import { SpacerProps } from './Spacer.types'; +import styles from './Spacer.module.css'; -const CUISpacer = styled.div<{ - $size?: SizeType; -}>` - background: transparent; - display: flex; - padding: ${({ theme, $size = 'md' }) => - `${theme.click.spacer.horizontal.space.y[$size]} ${theme.click.spacer.horizontal.space.x.all}`}; -`; +const spacerVariants = cva(styles.spacer, { + variants: { + size: { + xs: styles['spacer_size_xs'], + sm: styles['spacer_size_sm'], + md: styles['spacer_size_md'], + lg: styles['spacer_size_lg'], + xl: styles['spacer_size_xl'], + xxl: styles['spacer_size_xxl'], + }, + }, + defaultVariants: { + size: 'md', + }, +}); -export const Spacer = ({ size }: SpacerProps) => ; +export const Spacer = ({ size }: SpacerProps) => ( +
+); diff --git a/tests/display/spacer.spec.ts b/tests/display/spacer.spec.ts new file mode 100644 index 000000000..aa10cc462 --- /dev/null +++ b/tests/display/spacer.spec.ts @@ -0,0 +1,172 @@ +import { test as it, expect } from '@playwright/test'; +import { getStoryUrl } from '../utils'; + +const { describe, use } = it; + +const harnessLocator = '[data-testid="spacer-harness"]'; + +describe('Spacer Visual Regression', () => { + describe('Light Theme (Storybook Global)', () => { + describe('Size Variants', () => { + it('xs size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xs', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xs-light.png', { + maxDiffPixels: 100, + }); + }); + + it('sm size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-sm', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-sm-light.png', { + maxDiffPixels: 100, + }); + }); + + it('md size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-md', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-md-light.png', { + maxDiffPixels: 100, + }); + }); + + it('lg size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-lg', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-lg-light.png', { + maxDiffPixels: 100, + }); + }); + + it('xl size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xl', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xl-light.png', { + maxDiffPixels: 100, + }); + }); + + it('xxl size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xxl', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xxl-light.png', { + maxDiffPixels: 100, + }); + }); + + it('default size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--default-size', 'light'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-default-size-light.png', { + maxDiffPixels: 100, + }); + }); + }); + }); + + describe('Dark Theme (System prefers-color-scheme)', () => { + use({ colorScheme: 'dark' }); + + describe('Size Variants', () => { + it('xs size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xs'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xs-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('sm size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-sm'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-sm-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('md size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-md'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-md-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('lg size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-lg'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-lg-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('xl size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xl'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xl-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('xxl size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--size-xxl'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-size-xxl-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('default size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('display-spacer--default-size'), { + waitUntil: 'networkidle', + }); + const harness = page.locator(harnessLocator).first(); + await expect(harness).toBeVisible({ timeout: 10000 }); + await expect(harness).toHaveScreenshot('spacer-default-size-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + }); +}); diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-default-size-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-default-size-dark-chromium-linux.png new file mode 100644 index 000000000..66c8f1ae3 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-default-size-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-default-size-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-default-size-light-chromium-linux.png new file mode 100644 index 000000000..66c8f1ae3 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-default-size-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-dark-chromium-linux.png new file mode 100644 index 000000000..007fbd0cb Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-light-chromium-linux.png new file mode 100644 index 000000000..007fbd0cb Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-lg-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-md-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-md-dark-chromium-linux.png new file mode 100644 index 000000000..66c8f1ae3 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-md-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-md-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-md-light-chromium-linux.png new file mode 100644 index 000000000..66c8f1ae3 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-md-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-dark-chromium-linux.png new file mode 100644 index 000000000..309e70059 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-light-chromium-linux.png new file mode 100644 index 000000000..309e70059 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-sm-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-dark-chromium-linux.png new file mode 100644 index 000000000..2cce1f16e Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-light-chromium-linux.png new file mode 100644 index 000000000..2cce1f16e Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xl-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-dark-chromium-linux.png new file mode 100644 index 000000000..ebd67c592 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-light-chromium-linux.png new file mode 100644 index 000000000..ebd67c592 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xs-light-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-dark-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-dark-chromium-linux.png new file mode 100644 index 000000000..be27e9e80 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-dark-chromium-linux.png differ diff --git a/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-light-chromium-linux.png b/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-light-chromium-linux.png new file mode 100644 index 000000000..be27e9e80 Binary files /dev/null and b/tests/display/spacer.spec.ts-snapshots/spacer-size-xxl-light-chromium-linux.png differ