Skip to content
Hooney
한국어

Engines & modules · In use

Design system

A shared design system that organizes base values such as color and size into three levels and lets components change only by purpose, size, and style.

189Component stories, consumed by every app in the monorepo

Period
2024.12 ~ Present
Organization
Firstage
Role
Design and implementation (solo)
The photobook workspace showcase in the design system Storybook: cherry blossom photos beside a settings panel for the photobook title, featured place, book size, and story.

Core value

Every app keeps the same accessibility standard while choosing its own color theme.

Outcomes

  • Used by every app, from Journey to ROUND
  • 189 component examples (Storybook stories)
  • Automated checks keep component rules and documentation in line
  • Automated accessibility checks (axe) on the component examples

Tech stack

  • React
  • Tailwind CSS
  • Radix UI
  • tailwind-variants
  • Storybook

Context

The monorepo holds several apps, including Firstage’s Journey app and homepage, the internal Dashboard, the blog, and ROUND, a sports event service. Korean, English, and Japanese copy has to fit a 390px screen without clipping, and accessibility standards cannot vary from app to app. If each app made its own styles, those standards would scatter quickly, so I gathered them into one package that every app consumes.

Decisions and implementation

  • Tokens come in three tiers, primitive, semantic, and component, with colors defined in OKLCH. Interactive elements read only semantic tokens, so an app sets its theme by changing the semantic roles for light and dark modes.
  • Variants are expressed only through three axes: intent, size, and variant. A new case is solved inside those axes instead of with ad hoc styles, and className is reserved for layout so it cannot paint over color, height, or padding. Lint rules check the variant rules and the JSDoc on every public prop.
  • Components style Radix primitives with tailwind-variants, and compound components export separate Root and Part pieces to compose.
  • Apps pass in translated copy, locale, time zone, writing direction, and font. Components never guess language or time zone from the browser, so the same component can follow each app’s own policy.
  • Screens start at 390px and widen from there. Visible focus, meaningful labels, and touch targets of at least 44px on touch devices are the floor, and Storybook runs axe accessibility checks.

Current state

Every app in the monorepo uses this package, and it has 189 Storybook stories. It is still a pre-1.0 beta, and widening the axe checks and adding visual regression tests for Journey screens remain.

The photo selection showcase: four cherry blossom photos selected, with a resolution note and a button to preview the selection.
The journal composer showcase: a note for September 8 at Seoul Forest beside its context of when, where, and with whom.
The settings showcase: a weekly recap toggle, the default audience for new memories, and the summary language on one screen.