Skip to main content
@craft-ts
LearnLearn with EffectAI agentsGuideReference
@craft-ts/core@craft-ts/component@craft-ts/dev-tools@craft-ts/effect@craft-ts/style@craft-ts/style-testing@craft-ts/i18n@craft-ts/i18n-effect@craft-ts/mcp
ExamplesMigrationEffect compatibility & maturityAdopting CraftTS progressivelyPress kitRoadmapBacklog
Beta
  • Learn
  • Learn with Effect
  • AI agents
  • Guide
  • Reference
  • Packages
  • Resources
  • Guide overview
  • Create a project
i.Core concepts
  • The mental model
  • Which primitive should I use?
  • Anatomy of a primitive
  • Generators and yield*
  • Insertions
  • Typed insertion pipes
  • Exceptions as values
ii.Managing state
  • Local state
  • State machines
  • query
  • Mutations
  • queryParams
  • asyncProcess
  • Selecting
  • Reacting to mutations
  • Collections
  • Collection utilities
  • Persistence
  • GlobalPersisterHandler
  • Pagination placeholders
  • Schema validation
iii.Recommended approaches
  • Inject at the point of use
iv.Structuring the app
  • craftService
  • Service scopes
  • Shaping the public API
  • Abstract services
  • App start
  • Lazy services
  • Server functions
  • craftRegisterFor
  • Target wrapper
v.Routing & type-safe DI
  • Setup
  • CLI automation
  • ESLint rules
  • Route providers
  • Route guards
  • Route exception handling
  • Non-blocking navigation
  • Global error component
  • Route load errors
  • Scaling routes
vi.Components & templates
  • Components
  • Activating the style system
  • Typed styles
  • Defining a design system
  • Tokens and variables
  • Global foundation and fonts
  • Pseudo-elements and animations
  • Axes and the matrix
  • Context obligations
  • Testing visual states
  • Text contrast
  • Visual attestation
  • Template obligations
  • Typed CSS variables
  • Fine-grained reactivity
  • Progressive rendering
  • Directives and .pipe(...)
  • settledValue & pendingNode
  • Accessibility
  • Customization
  • Content projection
  • Styling a component
  • Template migrator
vii.Forms
  • Overview
  • Validators
  • Submitting
  • Nested forms
  • Exception handling
  • Complete examples
viii.Testing
  • Testing services
  • Testing components
  • Type-level tests
  • Browser boundaries
  • Page stability
  • Architecture rules
    • Overview
    • Declarative baseline
    • Unique identities
    • HTTP endpoint ownership
    • Computed purity
    • Dependency cycles
    • Mutation reactions
    • Route DI proofs
    • Route component files
    • Path boundaries
    • Exclusive links
    • Persisted identities
    • insertSelect keys
    • craftEffect and network
    • craftEffect and imperative sync
    • Interactive element names
    • Metric thresholds
    • Server-state loaders
    • Primitive loader requirements
  • Extensible architecture graph
  • Graph insights
  • Craft graph vs Nx
ix.Reactivity utilities
  • craftComputed
  • craftEffect
  • craftMethod
  • source$
  • on$
  • fromEventToSource$
  • sourceFromEvent
  • afterRecomputation
x.Internationalisation
  • Type-safe i18n
  • The catalogue
  • Tokens
  • The runtime
  • With Effect
xi.Deployment (experimental)
  • Overview
  • Manifest reference
  • Diagnostics
  • Providers
  • Alchemy provider
xii.Going further
  • SSR and hydration
  • Effect integration
  • Program operators
  • Pattern matching
  • Observability
  • AI agents
  • Temporal runtime
  1. Components & templates
  2. Typed styles

Typed styles#

The only way to style a component

This section is @craft-ts/style: typed values, CSS emitted at build time, and a visual matrix you can enumerate. It costs a Vite plugin — see Activating the style system — and a design system to declare. A component's meta carries no CSS; see Styling a component: the only way.

@craft-ts/style makes a component's visual surface derivable instead of guessed. For any component you can ask what the exhaustive set of visual states is, which of them are impossible, and whether the context it needs exists — and the answers come from the same values the CSS is emitted from, not from a second description that can drift.

It buys that in three levels, and they do not adopt the same way.

levelwhat it gives yougranularity of adoption
1 — tokens and typed variablesno value is a string; no class is built at runtimeone component at a time
2 — axes and the matrixthe exhaustive list of visual states, with the drivers that reach themper component
3 — context obligationsa missing scroll port, container or clipping ancestor fails the buildper whole route

Read that last column carefully, because it is the part that is easy to get wrong. Level 3 is not a per-component guarantee: one unmigrated link in a route and the requirement travels past it unanswered, so the compiler has nothing to check. A partial level-3 adoption gives zero of the guarantee, not most of it — and the graph reports it rather than hiding it.

The rule the whole thing turns on#

Static goes to a class at build time; dynamic goes through a typed custom property. No class is ever assembled in the browser.

ts
// tone is an axis: five rules the emitter already wrote.
when(tone.danger, [set(v.bg, palette.accent.danger)]);
ts
// a width that depends on a signal cannot be a class — there is no finite set
// of widths to emit — so it goes through a registered <percentage>.
style: function* () {
  return assign(meterVars.value, unit.pct(yield* value()));
}

That split is what keeps the set of visual states finite, and therefore enumerable. A class built from a signal is a state nothing recorded.

Where to go next#

Start with Activating @craft-ts/style: the system is a build step, and none of the pages below produce a single byte of CSS until the Vite plugin is wired. Then Define your design system, which is where bp, palette and the theme variables the other pages spend come from.

  • Tokens and typed variables — level 1.

  • Axes and the visual matrix — level 2.

  • Context obligations — level 3.

  • Testing what you built — drivers, baselines, exhaustiveness.

  • Text contrast — WCAG AA proven from the sheets and the templates, with no browser, and an explicit list of what it does not cover.

A working example lives in the demo, at apps/demo/src/app/examples/design-system/, with a README that walks through the same three levels in code.

←Activating the style systemDefining a design system→

On this page

  • The rule the whole thing turns on
  • Where to go next

@craft-ts · MIT licensed

GitHubnpm

Search