From e535071ac2f93f78bc56eb363c3acb8947d8809a Mon Sep 17 00:00:00 2001 From: Marco Noleto Date: Thu, 11 Jun 2026 09:52:54 +0200 Subject: [PATCH 1/3] fix(Card): restore the border on the selected state The selected and selected+hover states drew their border with an undefined token (color-interactive-default), which invalidated the whole box-shadow and left the card with no border. Use color-line-strong (the value from the design) so the selected border is visible again. Co-Authored-By: Claude Opus 4.8 (1M context) --- .changeset/card-selected-border.md | 7 +++++++ .../components/src/components/Card/styles/card.module.scss | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 .changeset/card-selected-border.md diff --git a/.changeset/card-selected-border.md b/.changeset/card-selected-border.md new file mode 100644 index 0000000000..9814a3ab90 --- /dev/null +++ b/.changeset/card-selected-border.md @@ -0,0 +1,7 @@ +--- +"@frontify/fondue-components": patch +--- + +fix(Card): restore the border on the selected state + +A selected card (and a selected card on hover) lost its border. The selected border now shows again, using the `color-line-strong` value from the design. diff --git a/packages/components/src/components/Card/styles/card.module.scss b/packages/components/src/components/Card/styles/card.module.scss index 687c17e901..27a89de9fb 100644 --- a/packages/components/src/components/Card/styles/card.module.scss +++ b/packages/components/src/components/Card/styles/card.module.scss @@ -112,7 +112,7 @@ // Selected state &[data-selected='true'] { @include card-state( - $card-shadow: (inset 0 0 0 1px var(--color-line-strong), inset 0 0 0 2px var(--color-interactive-default)), + $card-shadow: inset 0 0 0 1px var(--color-line-strong), $root-bg: 'surface-dim' ); } @@ -121,7 +121,7 @@ &[data-selected='true']:hover, &[data-selected='true']:has([data-state='open']) { @include card-state( - $card-shadow: (inset 0 0 0 1px var(--color-interactive-default), inset 0 0 0 2px var(--color-interactive-default)), + $card-shadow: inset 0 0 0 1px var(--color-line-strong), $root-bg: 'surface-hover' ); } From 6a556311f935b99e5cac531ec380b574ef16cba1 Mon Sep 17 00:00:00 2001 From: Marco Noleto Date: Mon, 15 Jun 2026 10:29:14 +0200 Subject: [PATCH 2/3] test(Card): add component test for the selected-state border Adds a Playwright component test verifying the selected and selected+hover states render a border (inset box-shadow on the overlay) in the color-line-strong token, and that a non-selected card has none. Catches the regression where an undefined token removed the border. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/Card/__tests__/Card.ct.tsx | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 packages/components/src/components/Card/__tests__/Card.ct.tsx diff --git a/packages/components/src/components/Card/__tests__/Card.ct.tsx b/packages/components/src/components/Card/__tests__/Card.ct.tsx new file mode 100644 index 0000000000..afed3a59f9 --- /dev/null +++ b/packages/components/src/components/Card/__tests__/Card.ct.tsx @@ -0,0 +1,72 @@ +/* (c) Copyright Frontify Ltd., all rights reserved. */ + +import { expect, type Locator, test } from '@playwright/experimental-ct-react'; + +import { RouterProvider } from '../../RouterProvider/RouterProvider'; +import { Card } from '../Card'; + +const CARD_TEST_ID = 'test-card'; + +const readBorder = (card: Locator) => + card.evaluate((element: Element) => { + const probe = document.createElement('span'); + probe.style.color = 'var(--color-line-strong)'; + document.body.append(probe); + const expectedColor = getComputedStyle(probe).color; + probe.remove(); + + return { + boxShadow: getComputedStyle(element, '::after').boxShadow, + expectedColor, + }; + }); + +test('should render the border on the selected state', async ({ mount }) => { + const wrapper = await mount( + {}} useHref={(path) => path}> + {}} selected aria-label="Card"> + Card title + + , + ); + const card = wrapper.getByTestId(CARD_TEST_ID); + await expect(card).toHaveAttribute('data-selected', 'true'); + + const { boxShadow, expectedColor } = await readBorder(card); + + expect(boxShadow).not.toBe('none'); + expect(boxShadow).toContain(expectedColor); +}); + +test('should keep the border on the selected state while hovered', async ({ mount }) => { + const wrapper = await mount( + {}} useHref={(path) => path}> + {}} selected aria-label="Card"> + Card title + + , + ); + const card = wrapper.getByTestId(CARD_TEST_ID); + await card.hover(); + + const { boxShadow, expectedColor } = await readBorder(card); + + expect(boxShadow).not.toBe('none'); + expect(boxShadow).toContain(expectedColor); +}); + +test('should not render the card border when not selected', async ({ mount }) => { + const wrapper = await mount( + {}} useHref={(path) => path}> + {}} selected={false} aria-label="Card"> + Card title + + , + ); + const card = wrapper.getByTestId(CARD_TEST_ID); + await expect(card).toHaveAttribute('data-selected', 'false'); + + const { boxShadow } = await readBorder(card); + + expect(boxShadow).toBe('none'); +}); From 919f1d36dfdfb8aeba03c59c137687bf21f58929 Mon Sep 17 00:00:00 2001 From: Marco Noleto Date: Mon, 15 Jun 2026 10:32:47 +0200 Subject: [PATCH 3/3] test(Card): import Locator type from @playwright/test Locator is not exported from @playwright/experimental-ct-react; import it from @playwright/test (type-only) so the test type-checks. Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/components/src/components/Card/__tests__/Card.ct.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/components/src/components/Card/__tests__/Card.ct.tsx b/packages/components/src/components/Card/__tests__/Card.ct.tsx index afed3a59f9..3eb003c986 100644 --- a/packages/components/src/components/Card/__tests__/Card.ct.tsx +++ b/packages/components/src/components/Card/__tests__/Card.ct.tsx @@ -1,6 +1,7 @@ /* (c) Copyright Frontify Ltd., all rights reserved. */ -import { expect, type Locator, test } from '@playwright/experimental-ct-react'; +import { expect, test } from '@playwright/experimental-ct-react'; +import { type Locator } from '@playwright/test'; import { RouterProvider } from '../../RouterProvider/RouterProvider'; import { Card } from '../Card';