Penpot kit

Theming

Theming this kit means changing a small number of token values and letting the file follow. Nothing is repainted by hand, and no component needs to be opened.

Work with the library file itself open. The components live here, and a token edited in a consuming file changes that file only.

Making it your colour

One colour drives more than you would expect: filled buttons, focus rings, switch tracks, selected rows, the active item in a sidebar. It is colors.primary-light and colors.primary-dark in the theme set, and there are two ways to change it.

Option one - stay on the scale

Open the Tokens panel, select the theme set, and change colors.primary-light from {neutral.900} to {blue.600}. Do the same for colors.primary-dark. Nothing else - every primary surface in the file repaints.

Staying on a Tailwind ramp is the safer edit. Hover and pressed states, the foreground colour and the focus ring all stay in proportion, because they come from the same family.

Option two - a colour of your own

If the brand colour is not on the scale, unlink the reference and type the hex into both primary-light and primary-dark. Two things are worth checking afterwards, because nothing checks them for you: that colors.primary-foreground still reads against the new colour, and that destructive and the chart colours do not now clash with it.

A literal is a dead end - it can no longer follow the ramp. That is fine for a brand colour and a poor idea for anything else.

The neutrals

Background, foreground, card, muted, accent, border and input all resolve to one neutral family. Swapping neutral for slate or stone changes the temperature of the whole kit and takes about a minute. Make the swap in theme, not in the mode sets: the mode sets decide which end of the ramp light and dark reach for, and leaving that alone keeps both modes working.

States and opacity

Hover, pressed and disabled are usually the same colour at a lower opacity rather than a different colour.

The same idea, two mechanics
TailwindThe slash is part of the class - bg-primary/90 carries both the colour and the alpha.
PenpotThe token binds the colour and opacity is a separate property on the fill, so setting fillOpacity leaves the binding intact.

That is why the focus ring in this kit is base.ring at reduced opacity rather than a lighter token of its own. One value moves and every ring follows it.

Type

The family is a token. font.sans holds Geist and font.mono holds Geist Mono, both in the tailwind set - change the value and the text follows. Sizes and weights are tokenised too, and are worth leaving alone: they are the Tailwind scale, and every component in the file is spaced against it. Line height is the exception, for the reason set out on the Design tokens page.

Corners

Radius is the quickest way to change how the kit feels and the least risky edit on this page. The scale lives in tailwind; there is no semantic radius layer in between, so you are editing the steps directly.

TokenValueWhere it lands
radius.sm6Tooltips and the smallest surfaces
radius.lg10Buttons, inputs, selects, textareas, alerts
radius.xl14Dialogs and the larger overlays
radius.4xl26Badges - a pill at their height

Not every corner is bound. Card and Popover sit at a measured 12, which is not a step on the scale, so they will not move when the token does. If a corner stays put after an edit, that is usually the reason.

Light and dark

Two sets hold the resolved values, and only one is active at a time. Switching them re-themes the file at once.

The switch is a set, not a shape. Nothing is selected and nothing is recoloured by hand.
A dark-mode fix belongs in mode-dark. If you are picking a colour on a layer to make dark read correctly, the value underneath it is wrong.
The example frames are light only. That is deliberate. The components carry both modes; the examples simply do not duplicate themselves to show it.

A second brand

Five sets is not a fixed number. A second brand is another set that redefines the semantic layer and leaves the Tailwind scale untouched.

1
Duplicate theme

Copy the theme set and name it for the brand.

2
Change only what differs

Usually primary, the neutral family, and the radius steps. Everything else keeps working because it was never brand-specific.

3
Activate it

Turn the brand set on alongside one of the mode sets.

Keep the names identical across sets and change values only, never structure. A brand set that introduces a name the others do not have will break the moment you switch away from it.

All of this is one panel and a handful of values. When a change does not travel, the cause is almost always a colour that was picked by hand instead of bound.