Skip to content

Commit

Permalink
docs: add Color Scale docs to Purmerend Theme
Browse files Browse the repository at this point in the history
  • Loading branch information
Robbert committed Dec 13, 2024
1 parent a61e224 commit 83acb9a
Show file tree
Hide file tree
Showing 8 changed files with 495 additions and 1 deletion.
11 changes: 11 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
.color-sample-list {
display: inline-flex;
padding-block: 0;
padding-inline: 0;
border: 1px solid silver;
flex-wrap: nowrap;
}

.color-sample-list__item {
margin-block: 0;
margin-inline: 0;
padding-block: 0;
padding-inline: 0;
}

.component-button,
.color-sample-list__button,
.color-sample-button {
/* `inline-size: min-intrinsic` size makes sense, but it is specifically neccessary for WebKit.
* The button should be no larger than its content, but WebKit uses a larger default width than other engines.
*/
border-width: 0;
padding-block: 0;
padding-inline: 0;
line-height: 1;
display: flex;
inline-size: min-intrinsic;
block-size: min-intrinsic;
min-block-size: 44px;
min-inline-size: 44px;

--utrecht-color-sample-inline-size: 100%;
--utrecht-color-sample-block-size: 44px;
}

.component-button,
.component-button:hover,
.color-sample-list__button:hover,
.color-sample-button:hover {
outline: 2px solid black;
z-index: 1;
}

.component-button:focus {
outline: 4px solid blue;
z-index: 1;
}

.color-sample-grid {
--utrecht-color-sample-inline-size: 66px;
}
.color-sample-grid,
.color-contrast-table {
inline-size: fit-content;
}
261 changes: 261 additions & 0 deletions proprietary/purmerend-design-tokens/documentation/ColorSampleList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
import {
Button,
Code,
Heading,
HeadingGroup,
Paragraph,
Table,
TableBody,
TableCell,
TableHeader,
TableHeaderCell,
TableRow,
} from '@utrecht/component-library-react/dist/css-module';
import {
calculateContrastRequirement,
getColorContrast,
} from '@nl-design-system-unstable/tokens-lib/dist/contrast-checker/check-colors';
import './ColorSampleList.css';
import { DesignToken } from '@nl-design-system-unstable/tokens-lib/dist/design-tokens';
import { Fragment, PropsWithChildren } from 'react';
import { ColorContrastCanvasElement } from './example-rendering.mjs';
import { ColorSampleElement } from './color-sample.mjs';

ColorContrastCanvasElement.define();
ColorSampleElement.define();

export const ColorSample = ({ color }: { color: string }) => (
<nldesignsystem-color-sample color={color}></nldesignsystem-color-sample>
);

export const StorybookIsolation = ({ children }: PropsWithChildren) => <div className="sb-unstyled">{children}</div>;

export const ComponentButton = ({ children }: PropsWithChildren) => (
<button className="component-button">{children}</button>
);

interface ColorSampleListProps {
tokens: DesignToken[];
ordered?: boolean;
}

export const ColorSampleList = ({ tokens, ordered }: ColorSampleListProps) => {
console.log(tokens);
const items = Object.values(tokens).map((token, index) => (
<li
key={index}
className="color-sample-list__item"
style={{
display: 'inline-block',
}}
>
{/* <ComponentButton onClick={() => console.log(123)}> */}
<ColorSample color={String(token['$value'])} />
{/* </ComponentButton> */}
</li>
));
const listProps = {
className: 'color-sample-list',
role: 'list',
style: {},
};
return ordered ? <ol {...listProps}>{items}</ol> : <ul {...listProps}>{items}</ul>;
};

export const ColorSampleGrid = ({ children }: PropsWithChildren) => {
return (
<Table className="color-sample-grid">
<TableHeader>
<TableRow>
<TableHeaderCell></TableHeaderCell>
<TableHeaderCell colSpan={2}>Background</TableHeaderCell>
<TableHeaderCell colSpan={3}>Interactive components</TableHeaderCell>
<TableHeaderCell colSpan={3}>Borders and separators</TableHeaderCell>
<TableHeaderCell colSpan={2}>Solid colors</TableHeaderCell>
<TableHeaderCell colSpan={2}>Accessible text</TableHeaderCell>
</TableRow>
<TableRow>
<TableHeaderCell></TableHeaderCell>
<TableHeaderCell>1</TableHeaderCell>
<TableHeaderCell>2</TableHeaderCell>
<TableHeaderCell>3</TableHeaderCell>
<TableHeaderCell>4</TableHeaderCell>
<TableHeaderCell>5</TableHeaderCell>
<TableHeaderCell>6</TableHeaderCell>
<TableHeaderCell>7</TableHeaderCell>
<TableHeaderCell>8</TableHeaderCell>
<TableHeaderCell>9</TableHeaderCell>
<TableHeaderCell>10</TableHeaderCell>
<TableHeaderCell>11</TableHeaderCell>
<TableHeaderCell>12</TableHeaderCell>
</TableRow>
</TableHeader>
<TableBody>{children}</TableBody>
</Table>
);
};

export const ColorSampleGridRow = ({ name, tokens }: { name: string; tokens: DesignToken[] }) => {
const items = Object.values(tokens).map((token, index) => (
<td key={index} className="color-sample-grid_cell">
<ComponentButton>
<ColorSample color={String(token['$value'])} />
</ComponentButton>
</td>
));
const listProps = {
role: 'list',
style: {},
};
return (
<tr className="color-sample-grid__row" {...listProps}>
<th>{name}</th>
{items}
<th>
<Button appearance="subtle">Wijzigen</Button>
</th>
</tr>
);
};

export const ColorContrastTable = ({ tokens }: DesignToken[]) => {
const map = [
{ type: 'background', vs: 11 },
{ type: 'background', vs: 12 },
{ type: 'inactive', vs: 1 },
{ type: 'inactive', vs: 1 },
{ type: 'inactive', vs: 1 },
{ type: 'border', vs: 1 },
{ type: 'border', vs: 1 },
{ type: 'border', vs: 1 },
{ type: 'solid', vs: 1 },
{ type: 'solid', vs: 1 },
{ type: 'text', vs: 1 },
{ type: 'text', vs: 1 },
];
const tokensArray = Object.values(tokens);
const pairs = tokensArray
.map((token, index) => {
const data = map[index];
const contrastToken = tokensArray[data.vs - 1];
let pair = [token['$value'], contrastToken['$value']];

if (['border', 'solid', 'text'].includes(data.type)) {
pair.reverse();
}

return {
foreground: '',
background: '',
fontSize: 16,
foregroundColor: pair[1],
backgroundColor: pair[0],
type: ['border', 'inactive'].includes(data.type) ? 'non-functional' : 'functional',
};
})
.map(getColorContrast)
.map((x) => ({
...x,
aaaContrast: calculateContrastRequirement('', '', x.fontSize, 'AAA', false),
aaContrast: calculateContrastRequirement('', '', x.fontSize, 'AA', false),
aaa: x.contrast >= calculateContrastRequirement('', '', x.fontSize, 'AAA', false),
aa: x.contrast >= calculateContrastRequirement('', '', x.fontSize, 'AA', false),
}));
console.log(pairs);
return (
<>
<Table className="color-contrast-table">
<TableHeader>
<TableRow>
<TableHeader>name</TableHeader>
<TableHeader>color</TableHeader>
<TableHeader>contrast</TableHeader>
<TableHeader>result</TableHeader>
</TableRow>
</TableHeader>
<TableBody>
{Object.values(tokens).map((token, index) => (
<TableRow key={index}>
<TableHeader>{token['name']}</TableHeader>
<TableCell>
<ComponentButton onClick={() => console.log(123)}>
<ColorSample color={token['$value']} />
</ComponentButton>
</TableCell>
<TableCell>{pairs[index].contrast.toPrecision(2)}</TableCell>
<TableCell>
<details>
<summary>{pairs[index].aaa ? '🥇 AAA' : pairs[index].aa ? '👍 AA' : '🔴 FAIL'}</summary>
<dl>
<div>
<dt>Voorgrond:</dt>
<dd>
<ColorSample color={pairs[index].foregroundColor} />
<Code>{String(pairs[index].foregroundColor)}</Code>
</dd>
</div>
<div>
<dt>Achtergrond:</dt>
<dd>
<ColorSample color={pairs[index].backgroundColor} />
<Code>{String(pairs[index].backgroundColor)}</Code>
</dd>
</div>
</dl>
<nldesignsystem-example-rendering
label="voorbeeldtekst in verschillende font-sizes groter dan 18.5px, met vette tekst"
style={{ '--utrecht-paragraph-font-size': '16px' }}
>
<Paragraph>
16px: Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt
in culpa qui officia deserunt mollit anim id est laborum.
</Paragraph>
</nldesignsystem-example-rendering>
</details>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{Object.values(tokens).map((token, index) => (
<section key={index}>
<HeadingGroup>
<Heading level={3}>{token['name']}</Heading>
{index === 0 ? <Paragraph>Shade 1 is bedoeld als</Paragraph> : null}
</HeadingGroup>
{index === 0 ? <Paragraph>Shade 1 is bedoeld als</Paragraph> : null}
</section>
))}
</>
);
};

interface ColorSamplePageProps {
scales: {
id: string;
label: string;
tokens: DesignToken[];
}[];
}

export const ColorSamplePage = ({ scales }: ColorSamplePageProps) => {
return (
<StorybookIsolation>
<ColorSampleGrid>
{scales.map(({ id, label, tokens }) => (
<ColorSampleGridRow key={id} name={label} tokens={tokens} />
))}
</ColorSampleGrid>
{scales.map(({ id, label, tokens }) => (
<Fragment key={id}>
<Heading level={2}>{label}</Heading>
<ColorSampleList tokens={tokens} />
<ColorContrastTable tokens={tokens} />
</Fragment>
))}
</StorybookIsolation>
);
};
Loading

0 comments on commit 83acb9a

Please sign in to comment.