Skip to content

Rendering Decisions in Docs

Setup

🚧 This guide is for @noodlestan/designer-shows/astro components and requires a working Astro website. You can create a website similar to this one using the Starlight theme in a matter of minutes.

This guide presents a simple way to document design decisions and tokens in your documentation pages.

Example:

<ShowDecision store={store} d="Brand Color Set" size="xs" value="hsl" />
<ShowDecision store={store} d="Sizing Space Scale" size="xs" />
hsl(336.18deg 59.82% 57.06%)
hsl(192.11deg 94.78% 45.1%)
hsl(0deg 0% 9.41%)
hsl(0deg 0% 96.86%)
25px
50px
100px
200px

Dependencies

The following packages are required:

Terminal window
npm install @noodlestan/designer-decisions @noodlestan/designer-functions \
@noodlestan/designer-schemas @noodlestan/designer-shows

Decision data

Populate your design decisions data source. 🚧

As illustrated in the Capturing Design Decisions guide, you can simply create one or more JSON files anywhere in your project.

  • Directorydata/
    • Directorydecisions/
      • color.json
      • space.json

Decision loader

Create a file to declare the loader.

We will use the all-in-one createDecisionLoader(), providing it with:

src/decisions/index.ts
import path from 'node:path';
import { createDecisionLoader } from '@noodlestan/designer-functions';
import { DECISION_SCHEMAS } from '@noodlestan/designer-schemas';
const DATA_PATH = path.resolve('./data/decisions');
export const loader = createDecisionLoader(
[DECISION_SCHEMAS],
[DATA_PATH],
async (moduleName: string) => `./node_modules/${moduleName}`,
);

API 🚧🚧 Banner: Help appreciated: how to provide a package resolution default?

The loader is an async function that returns a decision store. We will pass this store directly to our Astro components for them to retrieve decision data and resolve decision values.

const store = await loader();
const decision = store.decision('Action Color');

Rendering decisions in MDX

Retrieve the decision store and pass it to the components along with the decision name.

In this example we are using the <ShowDecision/> component to render both a ColorValueDecision and a ColorSetDecision. It selects the appropriate component according to the decision type and both visualizes and renders its value.

src/content/page.mdx
import { ShowDecision } from '@noodlestan/designer-shows/astro';
import { loader } from '../decisions';
export const store = await loader();
<ShowDecision store={store} d="Action Color" size="m" />
<ShowDecision store={store} d="Pink Palette" size="xs" />
#9b2c5a
#3d1a28
#64263e
#8e2f55
#ba366a
#d35084
#d67199
#da90ad
#e0aec2
#e8c9d6

Using built-in components

In the Components reference you will find a comprehensive set of components for rendering decisions in different scenarios and layouts.

For instance, the <ShowDecisionCard/> can also render all, or some, of the decision details.

src/content/page.mdx
import { ShowDecisionCard } from '@noodlestan/designer-shows/astro';
<CardGrid>
<ShowDecisionCard d="Action Color" loader={decisionLoader} />
</CardGrid>
Action Color
#9b2c5a

Used for buttons, links and navigation

Intended For:

  • Link Foreground
  • Action Background
  • Action Foreground
  • Action Border
  • Navigation Item Background

Not For:

  • Non-interactive elements

Creating custom components

In the Components reference you will also find a comprehensive set of primitives that render specific decision types and decision values, as well as a few helpful layouts and atoms.

You can reuse these built-in components to create your own, composing any layout of your choice, with total control over styling. You can also merge data from other sources, add custom logic, and format values as you wish.

In this example, we compose the <ShowColorValue/> and the <ShowDecisionUsage/> atom within the standard <DecisionCard/> layout.

MyColorDecision.Astro
---
import { type Decision } from '@noodlestan/designer-decisions';
import { type StaticDecisionStore } from '@noodlestan/designer-functions';
import {
DecisionCardLayout,
ShowDecision,
ShowDecisionUsage,
} from '@noodlestan/designer-shows/astro';
type Props = {
d: string;
store: StaticDecisionStore;
};
const { d, store } = Astro.props;
const [decision] = store.decision(d)
---
<DecisionCardLayout>
<h2 slot="header">{decision.name}</h2>
<ShowDecision slot="viz" store={store} d={d} value={['rgb', 'oklch']} />
<div slot="details">
<h3>Usage</h3>
<ShowDecisionUsage store={store} d={d} />
</div>
</DecisionCardLayout>

Use the new component directly in your MDX files.

src/content/page.mdx
import MyColorDecision from '../components/';
<MyColorDecision store={store} d="Action Color" />

Resolve decision values

You can also resolve decision values by calling value() on the decision object.

This code block demonstrates how you can use a decision value to build your own visualization.

---
import { getCollection } from 'astro:content';
import { type ColorDecision } from '@noodlestan/designer-decisions';
import { ShowDecisionCard } from '@noodlestan/designer-shows/astro';
const decisions = await getCollection('decisions');
const store = createDecisionStaticStore(decisions);
const { d } = Astro.props
const [, decision] = store.decision<ColorDecision>(d);
const color = decision.value().toString('oklch')
---
<div class="my-color-value-viz">{color.value}</div>
<style define:vars={{ 'my-color': color }}>
.my-color-value-viz { background-color: var(--my-color) }
</style>

See Also