Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
<!-- markdownlint-configure-file {"MD024": {"siblings_only": true}} -->

# Changelog

All notable changes to this package are documented in this file.

## Unreleased

### Added

- Added integration docs for using this package with `ui-style-kit-css` and its `interactive-surface-bridge` export.

### Changed

- Expanded dark theme icon-role selectors to also match `data-mode="dark"` and `data-mode="contrast"` containers for broader cross-library theming compatibility.
Comment on lines +13 to +15
- Removed `forced-color-adjust` from forced-colors styles to improve compatibility and avoid consumer integration warnings.

## 1.1.5 - 2026-05-18

### Changed

- Republished the release under `1.1.5` after npm rejected the already-published `1.1.4` version.

## 1.1.4 - 2026-05-18

### Fixed

- Corrected reduced-motion behavior so hover/focus/active lift transforms are fully disabled when `prefers-reduced-motion: reduce` is active.

### Changed

- Bumped package release metadata and docs references to `1.1.4` after the previous publish attempt issues.

## 1.1.3 - 2026-05-17

### Changed

- Superseded the failed `1.1.2` release with `1.1.3`.
- Updated version references across package metadata and release docs to `1.1.3`.
- Aligned package metadata with the published `1.1.3` release.
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,27 @@ Preferred token namespace:

The package also supports legacy fallback tokens and semantic fallback tokens. Full details and examples are in [Token Reference](./wiki/Token-Reference.md).

## Integration with UI Style Kit CSS

`interactive-surface-css` works directly with `ui-style-kit-css`.

If you use the combined UI Style Kit build, no extra bridge import is needed:

```js
import "ui-style-kit-css/dist/ui-style-kit.css";
import "interactive-surface-css/interactive-surface.css";
```

If you use per-style UI Style Kit imports, also include the bridge:

```js
import "ui-style-kit-css/styles/minimal-saas.css";
import "ui-style-kit-css/interactive-surface-bridge";
import "interactive-surface-css/interactive-surface.css";
```

The bridge maps active `data-ui`, `data-theme`, and `data-mode` tokens to Interactive Surface tokens, including variant and icon-role hooks.

## Accessibility

Built-in support includes:
Expand Down
13 changes: 6 additions & 7 deletions interactive-surface.css
Original file line number Diff line number Diff line change
Expand Up @@ -266,24 +266,24 @@
}
}

:where([data-theme="dark"], .theme-dark, .dark-mode, .dark) .interactive-surface.icon-only .light-icon,
:where([data-theme="dark"], .theme-dark, .dark-mode, .dark)
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark) .interactive-surface.icon-only .light-icon,
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark)
.interactive-surface.icon-only
[data-icon-role="light"] {
color: var(--interactive-surface-light-icon-color-dark, var(--icon-light-dark, rgb(255 255 255)));
}

:where([data-theme="dark"], .theme-dark, .dark-mode, .dark) .interactive-surface.icon-only .dark-icon,
:where([data-theme="dark"], .theme-dark, .dark-mode, .dark)
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark) .interactive-surface.icon-only .dark-icon,
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark)
.interactive-surface.icon-only
[data-icon-role="dark"] {
color: var(--interactive-surface-dark-icon-color-dark, var(--icon-dark-dark, rgb(30 58 138)));
}

:where([data-theme="dark"], .theme-dark, .dark-mode, .dark)
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark)
.interactive-surface.icon-only
.accessibility-icon,
:where([data-theme="dark"], .theme-dark, .dark-mode, .dark)
:where([data-theme="dark"], [data-mode="dark"], [data-mode="contrast"], .theme-dark, .dark-mode, .dark)
.interactive-surface.icon-only
[data-icon-role="accessibility"] {
Comment on lines +269 to 288
color: var(
Expand Down Expand Up @@ -473,7 +473,6 @@

@media (forced-colors: active) {
.interactive-surface {
forced-color-adjust: auto;
background-color: ButtonFace;
color: ButtonText;
border-color: ButtonText;
Expand Down
42 changes: 41 additions & 1 deletion tests/interactive-surface.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,25 @@ const html = `
<button id="target" class="interactive-surface">Target</button>
<button id="pressed" class="interactive-surface" aria-pressed="true">Pressed</button>
<button id="disabled" class="interactive-surface" aria-disabled="true">Disabled</button>
<button id="icon" class="interactive-surface icon-only" aria-label="Icon">+</button>
<button id="icon" class="interactive-surface icon-only" aria-label="Icon">
<span id="icon-light-default" data-icon-role="light">☀</span>
<span id="icon-dark-default" data-icon-role="dark">☾</span>
<span id="icon-accessibility-default" data-icon-role="accessibility">◎</span>
</button>
<div data-mode="dark">
<button id="icon-dark-mode" class="interactive-surface icon-only" aria-label="Dark mode icon">
<span id="icon-light-dark-mode" data-icon-role="light">☀</span>
<span id="icon-dark-dark-mode" data-icon-role="dark">☾</span>
<span id="icon-accessibility-dark-mode" data-icon-role="accessibility">◎</span>
</button>
</div>
<div data-mode="contrast">
<button id="icon-contrast-mode" class="interactive-surface icon-only" aria-label="Contrast mode icon">
<span id="icon-light-contrast-mode" data-icon-role="light">☀</span>
<span id="icon-dark-contrast-mode" data-icon-role="dark">☾</span>
<span id="icon-accessibility-contrast-mode" data-icon-role="accessibility">◎</span>
</button>
</div>
</body>
</html>
`;
Expand Down Expand Up @@ -112,4 +130,26 @@ test.describe("interactive surface package behavior", () => {
expect(iconStyles.minWidth).toBe("44px");
expect(iconStyles.minHeight).toBe("44px");
});

test("data-mode dark and contrast containers apply dark icon-role colors without changing baseline colors", async ({
page
}) => {
await page.emulateMedia({ colorScheme: "light" });
await page.setContent(html);

const getColor = async (selector: string) =>
page.locator(selector).evaluate((el) => window.getComputedStyle(el).color);
Comment on lines +134 to +141

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 70a1d3f. Added await page.emulateMedia({ colorScheme: "light" }) + await page.setContent(html) at the start of the test, following the same pattern as the existing reduced-motion test. Baseline color assertions are now deterministic regardless of the host OS color scheme.


expect(await getColor("#icon-light-default")).toBe("rgb(212, 175, 55)");
expect(await getColor("#icon-dark-default")).toBe("rgb(0, 0, 0)");
expect(await getColor("#icon-accessibility-default")).toBe("rgb(59, 130, 246)");

expect(await getColor("#icon-light-dark-mode")).toBe("rgb(255, 255, 255)");
expect(await getColor("#icon-dark-dark-mode")).toBe("rgb(30, 58, 138)");
expect(await getColor("#icon-accessibility-dark-mode")).toBe("rgb(156, 163, 175)");

expect(await getColor("#icon-light-contrast-mode")).toBe("rgb(255, 255, 255)");
expect(await getColor("#icon-dark-contrast-mode")).toBe("rgb(30, 58, 138)");
expect(await getColor("#icon-accessibility-contrast-mode")).toBe("rgb(156, 163, 175)");
});
});