Skip to content
Open
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
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
- .github/workflows/test.yml
- "packages/**"
- "apps/storybook/**"
- "apps/www/**"

permissions:
checks: write
Expand Down
43 changes: 43 additions & 0 deletions apps/www/app/_components/css-attributes/css-attributes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { describe, expect, it } from 'vitest';

import { getAttributes } from './css-attributes';

describe('getAttributes', () => {
it('returns public data attributes', () => {
const attributes = getAttributes(`
.ds-chip[data-variant='primary'] {}
.ds-chip[data-removable] {}
`);

expect(attributes).toEqual({
removable: '',
variant: "'primary'",
});
});

it('filters internal floating UI selectors', () => {
const attributes = getAttributes(`
.ds-popover[data-floating] {}
.ds-tooltip[data-floating|='top'] {}
.ds-combobox [data-floating-ui-portal] {}
.ds-chip[data-removable] {}
`);

expect(attributes).toEqual({ removable: '' });
});

it('continues to filter global attributes', () => {
const attributes = getAttributes(`
[data-color='neutral'] {}
[data-size='sm'] {}
[data-color-scheme='dark'] {}
[data-removable] {}
`);

expect(attributes).toEqual({ removable: '' });
});

it('returns an empty object when no data attributes match', () => {
expect(getAttributes('.ds-button:hover {}')).toEqual({});
});
});
13 changes: 10 additions & 3 deletions apps/www/app/_components/css-attributes/css-attributes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ type CssAttributesProps = {
};
} & TableProps;

const EXCLUDED_ATTRIBUTES = new Set([
'color',
'size',
'color-scheme',
// Floating UI positioning hooks are internal and not authored by consumers.
'floating',
'floating-ui-portal',
]);

export const CssAttributes = forwardRef<HTMLTableElement, CssAttributesProps>(
function CssAttributes({ vars, className, ...rest }, ref) {
const { t } = useTranslation();
Expand Down Expand Up @@ -62,16 +71,14 @@ export const CssAttributes = forwardRef<HTMLTableElement, CssAttributesProps>(
/* returns data-attributes and their possible values as key value pairs*/
export function getAttributes(css: string) {
const res: { [key: string]: Set<unknown> | string } = {};
//filter out global attributes referenced locally
const globals = ['color', 'size', 'color-scheme'];

const allAttrs = Array.from(
css.matchAll(/\[data-([^=\]|$~*^]+)(?:([|$~*^]?=)([^\]]+))?\]/g),
).map((matches) => ({ [matches[1]]: matches[3] }));

for (const attr of allAttrs) {
for (const [key, value] of Object.entries(attr)) {
if (globals.includes(key)) continue;
if (EXCLUDED_ATTRIBUTES.has(key)) continue;
if (!res[key]) {
res[key] = new Set();
}
Expand Down
6 changes: 5 additions & 1 deletion apps/www/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { fileURLToPath } from 'node:url';
import { reactRouter } from '@react-router/dev/vite';
import { defineConfig } from 'vite';
import { defineConfig } from 'vitest/config';
import { envOnlyMacros } from 'vite-env-only';
import tsconfigPaths from 'vite-tsconfig-paths';
Comment on lines 1 to 5

Expand Down Expand Up @@ -51,4 +51,8 @@ export default defineConfig(({ isSsrBuild, command }) => ({
clientFiles: ['./app/root.tsx', './app/entry.client.tsx'],
},
},
test: {
environment: 'node',
globals: true,
},
}));
5 changes: 4 additions & 1 deletion vitest.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
projects: ['{packages,internal}/*/vitest.config.mjs'],
projects: [
'{packages,internal}/*/vitest.config.mjs',
'apps/www/vite.config.ts',
],
reporters: [
'default',
['junit', { suiteName: 'Unit tests', addFileAttribute: true }],
Expand Down