Journal

September 17, 2026 · 2 min read

Styling a view you did not write

There is no stylesheet in this demo. Views name their parts, and styles attach to the names: how foldkit-mixins styles the studio, the site and the builder.

There is no CSS file in this demo. The studio, the site and the page builder are styled from TypeScript, and the builder looks like the rest of the studio though its views come from another package.

Views name their parts

A view drawn with foldkit-mixins does not write class names. It draws Slots: named parts, like a table’s row or the builder’s palette, each marked as what it is, such as a control or a part of a layout.

A Style is a value: declarations, nested rules, a media or container query. Style.forSlots(AdminSlots)({ … }) gives a Style for each Slot, and attaching it to a view gives each Slot a class. A Style’s rules are written when a view first draws it. This is the “Live” pill in a post’s History:

revisionLive: Style.self({
  background: `color-mix(in oklch,
    ${t.success.default} 14%, ${t.surface.base})`,
  borderRadius: t.radius.full,
  color: t.success.ink,
})

A theme is tokens

Colours, spacing and type come from a theme’s tokens, the t above. The palette is built from one accent hue in OKLCH, with a lighter accent for dark mode:

Theme.oklch({
  accent: { h: 265, c: 0.16, l: '52%', dark: { l: '72%', c: 0.13 } },
})

So the site follows the reader’s light or dark setting with no second set of styles.

Styling what you did not write

The builder’s views live in foldkit-mixins-builder. This demo does not fork them: it attaches its own Styles to the builder’s Slots, so the palette, the layers and the settings look like the rest of the studio. The table of posts from foldkit-mixins-crud and the forms from foldkit-mixins-form are styled the same way.

Styles sit in cascade layers, so an application’s Style outranks a package’s default without a contest of selectors. And a layout can answer to the right width: the builder stacks its panels by its own width, with a container query, so it stacks in a narrow window and in a narrow pane of a wide one.

The first paint

One stylesheet belongs to no view: the reset, the tokens and the theme. The build writes it into the page’s HTML, so every page’s first paint already has the theme’s background, before any script has run.

← More from the blog