@ign-junn/design-system
v0.38.0
Published
Design system of the Junn applications (IGN): Mantine theme, design tokens and generic React components
Readme
Junn design system
The design system of the Junn applications (IGN): a Mantine theme, design tokens and generic React components, shared by the Junn applications (junn-apps, flowbench…). Components receive their data and their texts through props: no translation, no route, no business logic inside.
bun add @ign-junn/design-systemQuick start
import '@mantine/core/styles.css';
import '@mantine/code-highlight/styles.css';
import '@ign-junn/design-system/styles.css';
import { MantineProvider } from '@mantine/core';
import theme from '@ign-junn/design-system/theme';
import { Button } from '@ign-junn/design-system';
const App = () => (
<MantineProvider theme={theme}>
<Button label="Hello" />
</MantineProvider>
);Everything comes from the single entry: import { Button, Stack, colors, sizes, isDefined } from '@ign-junn/design-system'
(components, tokens, type guards and types). Only the theme and the global styles keep their own paths, imported once
by the application. Bundlers keep only what is imported (each component stays its own module).
Components
| Category | Components |
|---|---|
| DataDisplay | Typography (every text, through its variants), Tooltip, Badge (tones, dot, count, external link), StatusIcon, DataTable (column hints), PropertyTable, ColorLegend (stacked or in a row), Steps, CodeSnippet, KanbanBoard (cards moved between columns by drag and drop), Timeline (dates on the left, detail on the right) |
| Feedback | Alert (tones), ProgressBar (task or colored segments with their legend), Spinner |
| Inputs | Button (text in label, with an optional icon, or icon only with iconOnly, the label then being its tooltip: action, route or external href; IconButton is deprecated), FileButton, CopyButton, IconSwitch, TextField (types text, password, email, search, url, tel, number, tags; multiline), Select, MultiSelect, Autocomplete, ColorField, ColorPicker, Checkbox, CheckboxGroup, ChipGroup, Switch, RadioGroup, Slider, StepSlider, SegmentedSwitch, EditableText, ColorSchemeToggle |
| Layout | Stack (direction="row" or "column"), Box, Grid (responsive columns), Carousel (items on a scrolling row), Divider, ScrollArea, Page, ResizeHandle |
| Navigation | TabBar (closable, renamable tabs), Tabs (simple tabs, counters), Link (external page) |
| Surfaces | Card, ProjectCard, CatalogCard, FloatingPanel, CollapsibleSection, Dialog |
| Utils | PageLoader, SortableList, NavigationLoader (page loader between two pages of a data router) |
Every component has its stories in Storybook: bun run storybook (http://localhost:6006), and online at
https://ign-mut.pages.gpf-tech.ign.fr/junn/junn-design-system/ (GitLab Pages, public; updated on each push on main).
Develop
bun install
bun run storybook # component explorer (stories in src/stories)
bun run check # Biome (lint + format + imports)
bun run check:rules # repository rules (no `function`, `let`, HTML tag, hardcoded text…)
bun run typecheck # TypeScript
bun run test # unit tests (src/tests, happy-dom)
bun run test:stories # every story as a test, in Chromium, light and dark: play functions + accessibility (axe)
bun run test:all # both
bun run coverage # both, with the coverage report (coverage/index.html)
bun run build # library in dist/: one module and one declaration file per source file
bun run build-storybook # static Storybook in storybook-static/Storybook 10 needs Node.js 20.19+: the scripts run it on Bun (bunx --bun).
The story tests need the Playwright browser once: bunx playwright install chromium.
A Husky pre-commit hook runs Biome on the staged files, the repository rules, the types and the unit tests
(bun install sets it up); never bypass it (--no-verify).
Storybook
- Controls: every prop of a story can be changed from the Controls panel; interactive components (fields, switches, tabs…) also update their controls when they are used, and their callbacks are logged in Actions.
- Docs: a page per component, with its props table.
- Toolbar: the color scheme (light, dark) and the viewport (mobile, tablet, laptop, desktop).
- Accessibility: the Accessibility panel lists the axe violations of the story; a violation fails its test.
- Tests: the Test widget runs the stories as tests (the same as
bun run test:stories), with their interactions (playfunctions, shown in the Interactions panel) and the coverage. - Visual tests are not set up: they need a Chromatic account (
@chromatic-com/storybook).
CI
.gitlab-ci.yml: Biome, repository rules, types, then the unit tests with the coverage, and the builds (library and
static Storybook as artifacts). The stories in Chromium do not run on each push: start the manual test:stories job from
the pipeline page when needed (locally: bun run test:stories). On main, the pages job publishes the static Storybook on GitLab Pages
(https://ign-mut.pages.gpf-tech.ign.fr/junn/junn-design-system/). Publishing the npm package stays manual (see Publish).
src/
├── components/ # the components, by category (DataDisplay, Feedback, Inputs, Layout, Navigation, Surfaces, Utils)
├── style/ # design tokens and the global CSS
├── types/ # every type and type guard (component props, token names)
├── theme.ts # the Mantine theme
├── stories/ # Storybook stories, mirroring components/ (+ Introduction, Foundations/Tokens)
└── tests/ # Vitest tests, and their helpersPublish
Every change is listed in CHANGELOG.md (also published with the package).
Published by hand, in the public npm organization ign-junn, with an npm granular access token ("Read and write" on
ign-junn, "Bypass two-factor authentication", 90 days at most, then renewed):
cp .env.example .env # once, then paste the token after NPM_TOKEN= (.env is ignored by git)
bun run whoami # checks the token: prints the npm account
# CHANGELOG.md: move the changes under a new "## [X.Y.Z] - date" section (and its compare link), then
npm version <patch|minor|major> # new version, commit and tag vX.Y.Z
bun run release # npm publish with .env loaded (scripts/npm.ts): every check runs first
bun run release:fast # same, without the checks and tests: only the build, then npm publish
git push --follow-tagsLearn more
API reference
Everything is imported from the single entry, except the theme and the global styles. The former paths of each file
(…/Inputs/Button, …/style/colors, …/types/common) still work, and will be removed in a major version.
| Import | Content |
|---|---|
| @ign-junn/design-system | Every component by its name, the tokens (colors, sizes, spacing, fontSizes…), the type guards (isDefined, isString…) and every type (ButtonProps, Tone…) |
| @ign-junn/design-system/icons | Every Tabler icon (IconSettings…), typed IconComponent: the applications import their icons here, never from @tabler/icons-react (own path: icon names such as IconSwitch would collide with components) |
| @ign-junn/design-system/theme | Mantine theme built on the tokens (importing it also registers the token names in Mantine's types) |
| @ign-junn/design-system/styles.css | Global styles: full height page, code highlighting colors |
| @ign-junn/design-system/style/<file> | Tokens: colors, sizes, spacing, typography, shadows, transitions |
| @ign-junn/design-system/types/<file> | Prop types (components), type guards (common), token names (mantine) |
| @ign-junn/design-system/<Category>/<Component> | Components (below) |
Prop types are documented in types/components and in the Storybook (Docs tab of each component: props table,
their description and default values).
Peer dependencies
Installed by the application: react, react-dom, react-router, @mantine/core, @mantine/hooks,
@mantine/code-highlight, highlight.js, @dnd-kit/*. The icons (@tabler/icons-react) come with the design
system, through @ign-junn/design-system/icons.
License
MIT © IGN
