diff --git a/src/components/CardHorizontal/CardHorizontal.stories.tsx b/src/components/CardHorizontal/CardHorizontal.stories.tsx index c74550bad..2ee9695eb 100644 --- a/src/components/CardHorizontal/CardHorizontal.stories.tsx +++ b/src/components/CardHorizontal/CardHorizontal.stories.tsx @@ -8,6 +8,7 @@ import { CardHorizontal } from '@/components/CardHorizontal'; const GridCenter = styled.div` display: grid; width: 60%; + max-width: 480px; `; const meta: Meta = { @@ -20,12 +21,12 @@ const meta: Meta = { badgeState: { type: { name: 'enum', - // FIXME should refer to the Badge constants value: ['default', 'success', 'neutral', 'danger', 'disabled', 'warning', 'info'], }, }, - // FIXME should refer to a constant badgeIconDir: { type: { name: 'enum', value: ['start', 'end'] } }, + color: { type: { name: 'enum', value: ['default', 'muted'] } }, + size: { type: { name: 'enum', value: ['sm', 'md'] } }, }, decorators: Story => ( @@ -36,7 +37,9 @@ const meta: Meta = { export default meta; -export const Playground: StoryObj = { +type Story = StoryObj; + +export const Playground: Story = { args: { icon: 'building', title: 'Card title', @@ -50,5 +53,200 @@ export const Playground: StoryObj = { infoText: '', infoUrl: '', size: 'md', + color: 'default', + }, +}; + +export const DefaultColor: Story = { + args: { + icon: 'building', + title: 'Default Color Card', + description: 'This is the default color variant.', + color: 'default', + }, +}; + +export const MutedColor: Story = { + args: { + icon: 'building', + title: 'Muted Color Card', + description: 'This is the muted color variant.', + color: 'muted', + }, +}; + +export const SmallSize: Story = { + args: { + icon: 'building', + title: 'Small Card', + description: 'This is the small size variant.', + size: 'sm', + }, +}; + +export const MediumSize: Story = { + args: { + icon: 'building', + title: 'Medium Card', + description: 'This is the medium size variant.', + size: 'md', + }, +}; + +export const DefaultDisabled: Story = { + args: { + icon: 'building', + title: 'Disabled Default Card', + description: 'This card is disabled.', + disabled: true, + color: 'default', + }, +}; + +export const MutedDisabled: Story = { + args: { + icon: 'building', + title: 'Disabled Muted Card', + description: 'This card is disabled.', + disabled: true, + color: 'muted', + }, +}; + +export const DefaultSelected: Story = { + args: { + icon: 'building', + title: 'Selected Default Card', + description: 'This card is selected.', + isSelected: true, + color: 'default', + }, +}; + +export const MutedSelected: Story = { + args: { + icon: 'building', + title: 'Selected Muted Card', + description: 'This card is selected.', + isSelected: true, + color: 'muted', + }, +}; + +export const DefaultDisabledSelected: Story = { + args: { + icon: 'building', + title: 'Disabled & Selected Card', + description: 'This card is both disabled and selected.', + disabled: true, + isSelected: true, + color: 'default', + }, +}; + +export const WithBadge: Story = { + args: { + icon: 'building', + title: 'Card with Badge', + description: 'This card has a badge.', + badgeText: 'New', + badgeState: 'success', + }, +}; + +export const WithBadgeAndIcon: Story = { + args: { + icon: 'building', + title: 'Card with Badge and Icon', + description: 'This card has a badge with an icon.', + badgeText: 'Info', + badgeState: 'info', + badgeIcon: 'check', + badgeIconDir: 'start', + }, +}; + +export const WithInfoButton: Story = { + args: { + icon: 'building', + title: 'Card with Info Button', + description: 'This card has an info button.', + infoText: 'Learn more', + }, +}; + +export const WithInfoButtonMuted: Story = { + args: { + icon: 'building', + title: 'Muted Card with Info Button', + description: 'This is a muted card with an info button.', + infoText: 'Learn more', + color: 'muted', + }, +}; + +export const WithInfoButtonDisabled: Story = { + args: { + icon: 'building', + title: 'Disabled Card with Info Button', + description: 'This is a disabled card with an info button.', + infoText: 'Learn more', + disabled: true, + }, +}; + +export const NonSelectable: Story = { + args: { + icon: 'building', + title: 'Non-Selectable Card', + description: 'This card is not selectable (has infoText).', + infoText: 'Click me', + }, +}; + +export const WithoutIcon: Story = { + args: { + title: 'Card Without Icon', + description: 'This card does not have an icon.', + }, +}; + +export const TitleOnly: Story = { + args: { + icon: 'building', + title: 'Title Only Card', + }, +}; + +export const DescriptionOnly: Story = { + args: { + icon: 'building', + description: 'This card only has a description, no title.', + }, +}; + +export const WithChildren: Story = { + args: { + icon: 'building', + title: 'Card with Children', + description: 'This card has children content.', + children: 'Additional child content goes here.', + }, +}; + +export const Interactive: Story = { + args: { + icon: 'check', + title: 'Interactive Card', + description: 'Click this card to test interactions.', + }, +}; + +export const InteractiveWithHandler: Story = { + args: { + icon: 'check', + title: 'Interactive Card with Handler', + description: 'This card has an onButtonClick handler for E2E testing.', + onButtonClick: () => console.log('Card clicked!'), }, }; diff --git a/src/components/CardHorizontal/CardHorizontal.test.tsx b/src/components/CardHorizontal/CardHorizontal.test.tsx index 38f14a619..6ea89fdcd 100644 --- a/src/components/CardHorizontal/CardHorizontal.test.tsx +++ b/src/components/CardHorizontal/CardHorizontal.test.tsx @@ -1,4 +1,4 @@ -import { screen } from '@testing-library/react'; +import { screen, fireEvent } from '@testing-library/react'; import { CardHorizontal, CardHorizontalProps } from '@/components/CardHorizontal'; import { renderCUI } from '@/utils/test-utils'; @@ -187,4 +187,108 @@ describe('CardHorizontal Component', () => { expect(windowOpenSpy).not.toHaveBeenCalled(); windowOpenSpy.mockRestore(); }); + + it('should have aria-pressed="true" when selected and selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + isSelected: true, + isSelectable: true, + }); + + const wrapper = container.firstChild; + expect(wrapper).toHaveAttribute('aria-pressed', 'true'); + }); + + it('should have aria-pressed="false" when not selected but selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + isSelected: false, + isSelectable: true, + }); + + const wrapper = container.firstChild; + expect(wrapper).toHaveAttribute('aria-pressed', 'false'); + }); + + it('should have aria-pressed="false" when selectable but isSelected is not provided', () => { + const { container } = renderCard({ + title: 'Test Card', + isSelectable: true, + }); + + const wrapper = container.firstChild; + expect(wrapper).toHaveAttribute('aria-pressed', 'false'); + }); + + it('should not have aria-pressed when not selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + infoText: 'Click me', + isSelectable: false, + }); + + const wrapper = container.firstChild; + expect(wrapper).not.toHaveAttribute('aria-pressed'); + }); + + it('should have role=button when selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + isSelectable: true, + }); + + const wrapper = container.firstChild; + expect(wrapper).toHaveAttribute('role', 'button'); + }); + + it('should not have role when not selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + infoText: 'Click me', + isSelectable: false, + }); + + const wrapper = container.firstChild; + expect(wrapper).not.toHaveAttribute('role'); + }); + + it('should call onClick on Space key when selectable', () => { + const onClickMock = vitest.fn(); + const { container } = renderCard({ + title: 'Test Card', + isSelectable: true, + onButtonClick: onClickMock, + }); + + const wrapper = container.firstChild as HTMLElement; + fireEvent.keyDown(wrapper, { key: ' ' }); + + expect(onClickMock).toHaveBeenCalled(); + }); + + it('should not call onClick on Space key when disabled', () => { + const onClickMock = vitest.fn(); + const { container } = renderCard({ + title: 'Test Card', + disabled: true, + isSelectable: true, + onButtonClick: onClickMock, + }); + + const wrapper = container.firstChild as HTMLElement; + fireEvent.keyDown(wrapper, { key: ' ' }); + + expect(onClickMock).not.toHaveBeenCalled(); + }); + + it('should not have onKeyDown when not selectable', () => { + const { container } = renderCard({ + title: 'Test Card', + infoText: 'Click me', + isSelectable: false, + }); + + const wrapper = container.firstChild; + expect(wrapper).not.toHaveAttribute('onkeydown'); + }); }); diff --git a/src/components/CardHorizontal/CardHorizontal.tsx b/src/components/CardHorizontal/CardHorizontal.tsx index d00628c61..f330a310a 100644 --- a/src/components/CardHorizontal/CardHorizontal.tsx +++ b/src/components/CardHorizontal/CardHorizontal.tsx @@ -1,3 +1,4 @@ +import { type KeyboardEvent, type MouseEvent } from 'react'; import { styled } from 'styled-components'; import { Badge } from '@/components/Badge'; import { Button } from '@/components/Button'; @@ -195,7 +196,7 @@ export const CardHorizontal = ({ onButtonClick, ...props }: CardHorizontalProps) => { - const handleClick = (e: React.MouseEvent) => { + const handleClick = (e: MouseEvent) => { if (disabled) { e.preventDefault(); return; @@ -208,6 +209,14 @@ export const CardHorizontal = ({ window.open(infoUrl, '_blank'); } }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (isSelectable && !disabled && e.key === ' ') { + e.preventDefault(); + handleClick(e as unknown as MouseEvent); + } + }; + return ( diff --git a/tests/cards/CardHorizontal.spec.ts b/tests/cards/CardHorizontal.spec.ts new file mode 100644 index 000000000..2fbdc0fe9 --- /dev/null +++ b/tests/cards/CardHorizontal.spec.ts @@ -0,0 +1,405 @@ +import { test as it, expect } from '@playwright/test'; +import { getStoryUrl } from '../utils'; + +const { describe, use } = it; + +describe('CardHorizontal Visual Regression', () => { + describe('Light Theme (Storybook Global)', () => { + describe('Color Variants', () => { + it('default color matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-default-color-light.png', { + maxDiffPixels: 100, + }); + }); + + it('muted color matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--muted-color', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-muted-color-light.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Size Variants', () => { + it('small size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--small-size', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-small-light.png', { + maxDiffPixels: 100, + }); + }); + + it('medium size matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--medium-size', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-medium-light.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Disabled States', () => { + it('default disabled matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-disabled', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveScreenshot( + 'card-horizontal-default-disabled-light.png', + { + maxDiffPixels: 100, + } + ); + }); + + it('muted disabled matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--muted-disabled', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-muted-disabled-light.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Selected States', () => { + it('default selected matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-selected', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-pressed', 'true'); + await expect(card).toHaveScreenshot( + 'card-horizontal-default-selected-light.png', + { + maxDiffPixels: 100, + } + ); + }); + + it('muted selected matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--muted-selected', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-pressed', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-muted-selected-light.png', { + maxDiffPixels: 100, + }); + }); + + it('disabled and selected matches snapshot', async ({ page }) => { + await page.goto( + getStoryUrl('cards-horizontal-card--default-disabled-selected', 'light'), + { + waitUntil: 'networkidle', + } + ); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveAttribute('aria-pressed', 'true'); + await expect(card).toHaveScreenshot( + 'card-horizontal-disabled-selected-light.png', + { + maxDiffPixels: 100, + } + ); + }); + }); + + describe('With Badge', () => { + it('with badge matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--with-badge', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-with-badge-light.png', { + maxDiffPixels: 100, + }); + }); + + it('with badge and icon matches snapshot', async ({ page }) => { + await page.goto( + getStoryUrl('cards-horizontal-card--with-badge-and-icon', 'light'), + { + waitUntil: 'networkidle', + } + ); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-with-badge-icon-light.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('With Info Button', () => { + it('with info button matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--with-info-button', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-with-info-light.png', { + maxDiffPixels: 100, + }); + }); + + it('muted with info button matches snapshot', async ({ page }) => { + await page.goto( + getStoryUrl('cards-horizontal-card--with-info-button-muted', 'light'), + { + waitUntil: 'networkidle', + } + ); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-info-muted-light.png', { + maxDiffPixels: 100, + }); + }); + + it('disabled with info button matches snapshot', async ({ page }) => { + await page.goto( + getStoryUrl('cards-horizontal-card--with-info-button-disabled', 'light'), + { + waitUntil: 'networkidle', + } + ); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-info-disabled-light.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Interactive States', () => { + it('hover state - default color', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.hover(); + await expect(card).toHaveScreenshot('card-horizontal-default-hover-light.png', { + maxDiffPixels: 100, + }); + }); + + it('focus state - default color', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.focus(); + await expect(card).toHaveScreenshot('card-horizontal-default-focus-light.png', { + maxDiffPixels: 100, + }); + }); + }); + }); + + describe('Dark Theme (System prefers-color-scheme)', () => { + use({ colorScheme: 'dark' }); + + describe('Color Variants', () => { + it('default color matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-default-color-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('muted color matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--muted-color'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-muted-color-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Disabled States', () => { + it('default disabled matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-disabled'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-default-disabled-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('muted disabled matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--muted-disabled'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-muted-disabled-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Selected States', () => { + it('default selected matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-selected'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-pressed', 'true'); + await expect(card).toHaveScreenshot('card-horizontal-default-selected-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('Interactive States', () => { + it('hover state - default color', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.hover(); + await expect(card).toHaveScreenshot('card-horizontal-default-hover-dark.png', { + maxDiffPixels: 100, + }); + }); + + it('focus state - default color', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.focus(); + await expect(card).toHaveScreenshot('card-horizontal-default-focus-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('With Badge', () => { + it('with badge matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--with-badge'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-with-badge-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + + describe('With Info Button', () => { + it('with info button matches snapshot', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--with-info-button'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveScreenshot('card-horizontal-with-info-dark.png', { + maxDiffPixels: 100, + }); + }); + }); + }); + + describe('Events and Accessibility', () => { + // NOTE: Click and keyboard tests verify the card remains functional (no crash) + // but cannot assert handler invocation since Storybook stories don't expose + // onButtonClick handlers for E2E verification. Handler logic is covered by + // unit tests in CardHorizontal.test.tsx. + it('click event fires correctly', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--interactive', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.click(); + // Verify card remains visible and functional after click (no crash) + await expect(card).toBeVisible(); + }); + + it('disabled card prevents click and has aria-disabled', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-disabled', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('aria-disabled', 'true'); + }); + + it('keyboard navigation works', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--interactive', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await card.focus(); + await expect(card).toBeFocused(); + await page.keyboard.press('Enter'); + // Verify card remains visible and functional after Enter key (no crash) + await expect(card).toBeVisible(); + }); + + it('tabIndex is -1 when disabled', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-disabled', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('tabindex', '-1'); + }); + + it('tabIndex is 0 when enabled', async ({ page }) => { + await page.goto(getStoryUrl('cards-horizontal-card--default-color', 'light'), { + waitUntil: 'networkidle', + }); + const card = page.getByTestId('card-horizontal'); + await expect(card).toBeVisible({ timeout: 10000 }); + await expect(card).toHaveAttribute('tabindex', '0'); + }); + }); +}); diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-dark-chromium-linux.png new file mode 100644 index 000000000..289a606f5 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-light-chromium-linux.png new file mode 100644 index 000000000..86dffa4e7 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-color-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-dark-chromium-linux.png new file mode 100644 index 000000000..bf6946829 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-light-chromium-linux.png new file mode 100644 index 000000000..026d6ea19 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-disabled-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-dark-chromium-linux.png new file mode 100644 index 000000000..927675e47 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-light-chromium-linux.png new file mode 100644 index 000000000..eb57dd7ae Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-focus-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-dark-chromium-linux.png new file mode 100644 index 000000000..62fdc6be8 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-light-chromium-linux.png new file mode 100644 index 000000000..699558b32 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-hover-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-dark-chromium-linux.png new file mode 100644 index 000000000..0a3145163 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-light-chromium-linux.png new file mode 100644 index 000000000..7df4bb2f3 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-default-selected-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-disabled-selected-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-disabled-selected-light-chromium-linux.png new file mode 100644 index 000000000..c66cb8bb6 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-disabled-selected-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-disabled-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-disabled-light-chromium-linux.png new file mode 100644 index 000000000..ad9344bbb Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-disabled-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-muted-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-muted-light-chromium-linux.png new file mode 100644 index 000000000..89b67809c Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-info-muted-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-medium-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-medium-light-chromium-linux.png new file mode 100644 index 000000000..fb60d1208 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-medium-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-dark-chromium-linux.png new file mode 100644 index 000000000..20aec3ad7 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-light-chromium-linux.png new file mode 100644 index 000000000..4b8e04841 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-color-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-dark-chromium-linux.png new file mode 100644 index 000000000..65a1f277c Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-light-chromium-linux.png new file mode 100644 index 000000000..4e25127da Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-disabled-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-selected-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-selected-light-chromium-linux.png new file mode 100644 index 000000000..58b4ce4bd Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-muted-selected-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-small-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-small-light-chromium-linux.png new file mode 100644 index 000000000..ebbb56c7d Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-small-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-dark-chromium-linux.png new file mode 100644 index 000000000..5a712da29 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-icon-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-icon-light-chromium-linux.png new file mode 100644 index 000000000..c3369d4e3 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-icon-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-light-chromium-linux.png new file mode 100644 index 000000000..69227fece Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-badge-light-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-dark-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-dark-chromium-linux.png new file mode 100644 index 000000000..e96abb25c Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-dark-chromium-linux.png differ diff --git a/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-light-chromium-linux.png b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-light-chromium-linux.png new file mode 100644 index 000000000..3821fafa9 Binary files /dev/null and b/tests/cards/CardHorizontal.spec.ts-snapshots/card-horizontal-with-info-light-chromium-linux.png differ