Skip to content
Draft
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
14 changes: 13 additions & 1 deletion packages/gamut-docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,19 @@ export default defineConfig({
// needs an explicit label instead of a bare autogenerate.
label: 'System props',
items: [
{ autogenerate: { directory: 'foundations/system-props' } },
{ slug: 'foundations/system-props' },
{
label: 'Prop groups',
items: [
{
autogenerate: {
directory: 'foundations/system-props/prop-groups',
},
},
],
},
{ slug: 'foundations/system-props/compose-and-variants' },
{ slug: 'foundations/system-props/responsive-properties' },
],
},
{ slug: 'foundations/themes' },
Expand Down
145 changes: 145 additions & 0 deletions packages/gamut-docs/src/components/SystemPropTable.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
---
/**
* The Starlight counterpart of Storybook's system prop `TokenTable` (see
* styleguide's `Foundations/shared/elements.tsx`): one row per prop in a
* system prop group, with its CSS properties, scale, and transform.
*
* Rows are read from `variance/config.ts` at build time — the same source
* Storybook uses — so the table can't drift from the props themselves. That
* file isn't part of `@skillsoft/gamut-styles`' public exports, so it's
* imported by path, as Storybook does.
*
* Storybook resolves a prop's properties for whichever logical-properties mode
* its toolbar is set to. A static page has no toggle, so a prop whose physical
* and logical properties differ lists both.
*/
import * as ALL_PROPS from '../../../gamut-styles/src/variance/config';

type Group = keyof typeof ALL_PROPS;
type Mode = 'physical' | 'logical';

interface PropConfig {
property: string | Record<Mode, string>;
properties?: readonly string[] | Record<Mode, readonly string[]>;
scale?: string;
transform?: (...args: never[]) => unknown;
resolveProperty?: (useLogicalProperties: boolean) => Mode;
}

interface Props {
/** A system prop group exported from `variance/config.ts`, e.g. "color" */
group: Group;
}

const { group } = Astro.props;

const toKebab = (value: string) =>
value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);

const resolveProperties = (
{ property, properties }: PropConfig,
mode: Mode
): string[] => {
const resolved = typeof property === 'string' ? property : property[mode];
if (!properties) return [resolved];
if (Array.isArray(properties)) return [...properties];
return [...(properties as Record<Mode, readonly string[]>)[mode]];
};

const rows = Object.entries(
ALL_PROPS[group] as Record<string, PropConfig>
).map(([id, config]) => {
// Without `resolveProperty`, a prop always renders its physical properties.
const physical = resolveProperties(config, 'physical');
const logical = config.resolveProperty
? resolveProperties(config, 'logical')
: physical;
const modesDiffer = physical.join() !== logical.join();

return {
id,
propertySets: modesDiffer
? [
{ label: 'Logical', properties: logical },
{ label: 'Physical', properties: physical },
]
: [{ label: undefined, properties: physical }],
scale: config.scale,
transforms: [config.transform?.name, config.resolveProperty?.name].filter(
Boolean
),
};
});

// Hand-authored hrefs in components aren't rewritten by the markdown base-URL
// plugin in astro.config.mjs, so the base has to be applied here.
const scaleHref = `${import.meta.env.BASE_URL.replace(/\/$/, '')}/foundations/design-tokens/`;
---

<div class="system-prop-table">
<table>
<thead>
<tr>
<th>Prop</th>
<th>Properties</th>
<th>Scale</th>
<th>Transform</th>
</tr>
</thead>
<tbody>
{
rows.map(({ id, propertySets, scale, transforms }) => (
<tr>
<td>
<code>{id}</code>
</td>
<td>
{propertySets.map(({ label, properties }) => (
<div>
{label && <span>{label}: </span>}
{properties.map((prop, index) => (
<>
{index > 0 && ' '}
<a
href={`https://developer.mozilla.org/en-US/docs/Web/CSS/${toKebab(prop)}`}
rel="noreferrer"
target="_blank"
>
<code>{toKebab(prop)}</code>
</a>
</>
))}
</div>
))}
</td>
<td>{scale && <a href={scaleHref}>{scale}</a>}</td>
<td>
{transforms.map((name, index) => (
<>
{index > 0 && ' '}
<code>{name}</code>
</>
))}
</td>
</tr>
))
}
</tbody>
</table>
</div>

<style>
/* Starlight renders content tables as `display: block` so wide ones scroll,
which also shrinks them to their content. Scrolling moves to the wrapper
so the table itself can span the full content width. Starlight's rules
sit in a cascade layer, so these unlayered ones win without extra
specificity. */
.system-prop-table {
overflow-x: auto;
}

.system-prop-table table {
display: table;
width: 100%;
}
</style>

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Background
description: System props for background images and patterns.
sidebar:
order: 8
---

Background props control background images and patterns — sizing, positioning, and repetition. For solid background colors, use the [color props](/foundations/system-props/prop-groups/color/) instead.

```tsx
const BackgroundExample = styled.div(system.background);

<BackgroundExample background={`url(${myBg})`} backgroundSize="cover" />;
```

For every prop in this group — its CSS properties, scale, and transform — see the [Background prop table](https://gamut.codecademy.com/?path=/docs/foundations-system-props-background--docs) in Storybook.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
title: Border
description: System props for border width, style, and radius on any side.
sidebar:
order: 5
---

Border props add and style borders on any side of an element, with directional props and horizontal/vertical shorthands. `borderRadius` references the theme's `borderRadii` scale.

```tsx
const BorderExample = styled.div(system.border);

<BorderExample
border={1}
borderLeft="none"
borderRightStyle="dotted"
borderRadius="md"
/>;
```

These props support both physical and logical CSS properties, resolved by `useLogicalProperties` on `GamutProvider` — see [Migrating to logical properties](/guides/migrating-to-logical-properties/).

For every prop in this group — its CSS properties, scale, and transform — see the [Border prop table](https://gamut.codecademy.com/?path=/docs/foundations-system-props-border--docs) in Storybook.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: Color
description: System props for foreground, background, and border colors.
sidebar:
order: 4
---

import SystemPropTable from '~/components/SystemPropTable.astro';

Color props control foreground, background, and border colors, restricted to the theme's color palette. `bg` is a shorthand for background color.

```tsx
const ColorExample = styled.div(system.color);

<ColorExample bg="navy" textColor="gray-100" borderColor="blue" />;
```

These props support both physical and logical CSS properties, resolved by `useLogicalProperties` on `GamutProvider` — see [Migrating to logical properties](/guides/migrating-to-logical-properties/).

## Props

<SystemPropTable group="color" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: Flex
description: System props for flexbox containers and items.
sidebar:
order: 6
---

Flex props control flexbox layouts end to end — container behavior and individual item properties alike.

```tsx
const FlexExample = styled.div(system.flex);

<FlexExample flex={1} justifyContent="center" alignItems="flex-start" />;
```

For every prop in this group — its CSS properties, scale, and transform — see the [Flex prop table](https://gamut.codecademy.com/?path=/docs/foundations-system-props-flex--docs) in Storybook.
Loading
Loading