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
7 changes: 7 additions & 0 deletions .changeset/tidy-jars-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
'@cloudfour/patterns': patch
---

Load `src/index-with-dependencies.scss` with `@use` rather than `@import`, which Dart Sass 3 removes. This was the last `@import` in the repo.

Compiled output loses seven duplicate `@font-face` rules and nothing else. `@use` loads each stylesheet once, so the fonts configured at the top of the file are emitted a single time; under `@import` they came out twice, because `./index` loads `base/fonts` as well and an `@import` does not share the module graph with the file importing it. Every surviving rule is byte-for-byte one of the originals, in the same order, and all other CSS is byte-for-byte identical — 1,245 bytes smaller in the Storybook build.
8 changes: 1 addition & 7 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,7 @@ export default [
languageOptions: {
parserOptions: {
tsconfigRootDir: import.meta.dirname,
projectService: {
// Our tsconfig covers `src`, because that is what ships. These files
// configure the tooling around it and belong to no project, so the type
// aware rules read them through an inferred one instead of failing to
// find them at all.
allowDefaultProject: ['vitest.config.mts', 'vitest.setup.*.ts'],
},
projectService: true,
},
},
},
Expand Down
14 changes: 11 additions & 3 deletions src/components/button-swap/button-swap.browser.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import template from './button-swap.twig';

const body = () => page.elementLocator(document.body);

test('Swap UI state when clicked', async () => {
test('Render both states, exposing only the initial one', async () => {
document.body.innerHTML = template();

// This package ships the markup for Button Swap but not the script that swaps it:
// that lives in the consuming site. So what this asserts is the initial state --
// only the unsubscribed button is exposed, and it is not the slashed variant.
// that lives in the consuming site. So there is no swap to exercise here -- what
// the template has to get right is that both states are present and only the
// unsubscribed one reaches the accessibility tree. The snapshot covers the second
// half: `hidden` keeps the swapped state out of it.
await expect.element(body()).toMatchAriaInlineSnapshot(`
- status: Currently unsubscribed from notifications
- button "Get notifications"
Expand All @@ -21,6 +23,12 @@ test('Swap UI state when clicked', async () => {
const firstBtn = page.getByRole('button');
await expect.element(firstBtn).toBeVisible();
await expect.element(firstBtn).not.toHaveClass('is-slashed');

const swapped = document.querySelector(
'.js-button-swap__swapped-button-wrapper',
);
expect(swapped).not.toBeNull();
expect(swapped).toHaveAttribute('hidden');
});

test('Set custom messages and labels', async () => {
Expand Down
9 changes: 6 additions & 3 deletions src/index-with-dependencies.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
$dir: '/src/assets/fonts'
);

// stylelint-disable at-rule-disallowed-list
@import '../node_modules/@wordpress/block-library/build-style/style';
@import './index';
/// `@use` rather than `@import`, which Dart Sass 3 removes. Because `@use` loads each
/// stylesheet once, the `@font-face` rules from `base/fonts` above are emitted a single
/// time here; under `@import` they came out twice, since `./index` loads `base/fonts`
/// too and an `@import` does not share the module graph with the file importing it.
@use '../node_modules/@wordpress/block-library/build-style/style';
@use './index';
9 changes: 8 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,14 @@
"skipLibCheck": true,
"resolveJsonModule": true
},
"include": ["src"],
// `src` is what ships. The root-level globs pick up the tooling that configures the
// build and tests around it: those files belong to no project otherwise, so the
// type-aware lint rules either fail to find them or fall back to an inferred
// project that ignores the strictness settings above. Globs rather than a list, so
// the next root-level TypeScript file is covered without anyone remembering to add
// it. Nothing outside `ts-dist/src` reaches `dist`, so this does not widen what we
// publish.
"include": ["src", "*.ts", "*.mts", "*.cts"],
"exclude": [
"src/prototypes",
"src/vendor/highlight/demo/samples",
Expand Down
9 changes: 8 additions & 1 deletion twing/vite-plugin-twig.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -64,15 +64,22 @@ export const twigInputs =
export const twigPlugin = () => ({
name: 'cloudfour-twig',

/** @param {string} id */
resolveId(id) {
if (id === VIRTUAL_ID) return RESOLVED_VIRTUAL_ID;
},

/** @param {string} id */
load(id) {
if (id === RESOLVED_VIRTUAL_ID) return environmentModule;
},

transform(code, id) {
/**
* @param {string} _code The module source, which we never read: the transform
* rewrites `.twig` imports into a render wrapper generated from the id alone.
* @param {string} id
*/
transform(_code, id) {
// Let `?raw` imports through untouched -- the environment module needs the source.
if (!id.endsWith('.twig')) return;

Expand Down