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
74 changes: 74 additions & 0 deletions .plop/templates/component/component.mdx.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { Canvas, Controls, Meta, Subtitle, Title } from '@storybook/addon-docs/blocks'

import * as {{pascalCase name}}Stories from './{{dashCase name}}.stories'

<Meta of={ {{pascalCase name}}Stories } />

<Title />

<Subtitle>One-line summary of what {{pascalCase name}} is for.</Subtitle>

## Overview

What {{pascalCase name}} is and the problem it solves, in a sentence or two. For design
guidance (anatomy, when to use, do and don't), see the
[{{pascalCase name}} handbook page](https://github.com/Doist/component-libraries/blob/main/handbook/components/{{dashCase name}}.md).

{/* Verify this handbook link: the slug isn't always the component's dash-name (e.g.
buttons.md, menus.md, switches.md) and some pages don't exist yet. */}

## When to use

{/* Two or more concrete scenarios. Trim to what the handbook doesn't already cover. */}

- Use {{pascalCase name}} when ...
- Prefer another component when ...

## Basic usage

The simplest real example. Pass `variant` and `children`.

<Canvas of={ {{pascalCase name}}Stories.Playground } />

## Variants

{{pascalCase name}} supports a `primary` and a `secondary` variant.

<Canvas of={ {{pascalCase name}}Stories.Variants } />

## States

{/* Visual states (idle, hover, disabled, loading) live here. Add a `States` story and
reference it with <Canvas of={ {{pascalCase name}}Stories.States } />, or delete this
section if the component has no distinct states. */}

## API

<Controls of={ {{pascalCase name}}Stories.Playground } />

{/* Composable components: add `ArgTypes` to the import above and document each exported
part with its own block, e.g.

### `<{{pascalCase name}}.Item>`

<ArgTypes of={ {{pascalCase name}}Item } />

Repeat per exported sub-component. */}

## Custom properties

The following CSS custom properties customize the {{pascalCase name}} appearance. The values
shown are the defaults.

```css
--reactist-{{dashCase name}}-tint
--reactist-{{dashCase name}}-fill
```

## Accessibility

- **Keyboard**: describe focus order and keys the component handles.
- **Screen reader**: the name, role, and state it exposes (and via which prop).
- **Focus**: focus management / trapping behavior, if any.

<Canvas of={ {{pascalCase name}}Stories.Accessibility } />
26 changes: 24 additions & 2 deletions .plop/templates/component/component.stories.tsx.hbs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as React from 'react'
import type { Meta, StoryObj } from '@storybook/react'

import { {{pascalCase name}} } from './{{dashCase name}}'

import type { Meta, StoryObj } from '@storybook/react'

const meta = {
title: 'Design system/{{pascalCase name}}',
component: {{pascalCase name}},
Expand Down Expand Up @@ -32,11 +33,32 @@ export const Playground: Story = {
control: { type: 'text' },
},
},
render(args) {
render(args: React.ComponentProps<typeof {{pascalCase name}}>) {
return (
<section>
<{{pascalCase name}} {...args} />
</section>
)
},
}

export const Variants: Story = {
render() {
return (
<section>
<{{pascalCase name}} variant="primary">Primary</{{pascalCase name}}>{' '}
<{{pascalCase name}} variant="secondary">Secondary</{{pascalCase name}}>
</section>
)
},
}

export const Accessibility: Story = {
render() {
return (
<section>
<{{pascalCase name}} variant="primary">Accessible content</{{pascalCase name}}>
</section>
)
},
}
2 changes: 2 additions & 0 deletions .plop/templates/component/component.test.tsx.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from 'react'

import { render, screen } from '@testing-library/react'

import { {{pascalCase name}} } from './{{dashCase name}}'

describe('{{pascalCase name}}', () => {
Expand Down
8 changes: 3 additions & 5 deletions .plop/templates/component/component.tsx.hbs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import * as React from 'react'

import { Box } from '../box'

import styles from './{{dashCase name}}.module.css'

type {{pascalCase name}}Props = {
Expand All @@ -14,11 +16,7 @@ type {{pascalCase name}}Props = {
}

function {{pascalCase name}}({ children, variant }: {{pascalCase name}}Props) {
return (
<Box className={[styles.container, styles[variant]]}>
{children}
</Box>
)
return <Box className={[styles.container, styles[variant]]}>{children}</Box>
}

export { {{pascalCase name}} }
Expand Down
2 changes: 1 addition & 1 deletion .plop/templates/component/index.ts.hbs
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { {{pascalCase name}} } from './{{dashCase name}}'
export type { {{pascalCase name}}Props } from './{{dashCase name}}'
export { {{pascalCase name}} } from './{{dashCase name}}'
5 changes: 3 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ src/
component-name.tsx # Implementation
component-name.module.css # CSS Modules styles
component-name.test.tsx # Tests
component-name.stories.mdx # Storybook docs (or .tsx)
component-name.stories.tsx # Storybook stories (CSF)
component-name.mdx # Storybook MDX docs page
styles/
design-tokens.css # Global CSS custom properties (--reactist-*)
utils/
Expand All @@ -43,7 +44,7 @@ src/

### File structure

Every component has `index.ts`, `component.tsx`, `component.module.css`, `component.test.tsx`, and a story file. Use `npm run plop component` to scaffold new components.
Every component has `index.ts`, `component.tsx`, `component.module.css`, `component.test.tsx`, a `component.stories.tsx` story file, and a `component.mdx` docs page. Use `npm run plop component` to scaffold new components.

### Implementation patterns

Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ The generated source files include the component implementation with sample prop

You also need to export your new component by adding a reference to it in the [top-level index file](src/index.ts).

The generator also creates a `<component-name>.mdx` documentation page next to the stories. Edit it to document the component: fill in the Overview and link the matching [design handbook page](https://github.com/Doist/component-libraries/tree/main/handbook/components), keep the sections that apply, and delete the ones that don't. For composable components (multiple exported parts), repeat the API block per part. Its live examples render from the generated `Playground`, `Variants`, and `Accessibility` stories.

## Storybook

For the first development mode run:
Expand Down
6 changes: 6 additions & 0 deletions plopfile.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ function componentGenerator(plop) {
templateFile: templateFile('component/component.stories.tsx'),
})

actions.push({
type: 'add',
path: 'src/{{dashCase name}}/{{dashCase name}}.mdx',
templateFile: templateFile('component/component.mdx'),
})

return actions
},
})
Expand Down
Loading