The Editable Design System

A shared starting point for Editable. Simple styles, ready to use and adapt.

Foundations

Colors, fonts, and corner radii come from the shared tokens in src/app.css. These specimens follow the current token values.

Colors and surfaces

Keep each surface with its foreground color. Neutral controls use the muted surface on hover and a 10% foreground tint on press. Primary actions and editing actions use their respective accent treatments.

Page content

--background / --foreground

Secondary surface

Supporting text

--muted / --muted-foreground

Primary action or highlight

--accent / --accent-foreground

Active editing

--editing / --editing-foreground

Passive editing highlight

--editing-muted / --editing

Borders and dividers


--stroke

Font families

Clear words.

font-sans · Inter

Clear words.

font-serif · Libertinos Serif Display

Clear words.

font-mono · IBM Plex Mono

Corner radii

Buttons and pill shells use the button radius. Popovers cap it at 1rem; their inner rows and pill controls subtract 4px padding and a 1px border, clamped at zero. Images use their own radius. Set either token to zero for square corners.

Button

--button-border-radius

Pill interior

Button radius with an inset interior.

Popover row

Button radius capped at 1rem, with an inset row.

Image corners

--image-border-radius

Page limiter

Center each block with mx-auto max-w-7xl, then add px-5 sm:px-7 inside it. The width limit is 80rem (1280px), including side padding: 1.25rem (20px) on small screens and 1.75rem (28px) from the 40rem (640px) breakpoint, at the default root font size.

Page content aligns here.

The shaded edges show the shared page padding. Resize the window to compare.

<div class="mx-auto max-w-7xl">
	<div class="px-5 sm:px-7">
		Page content
	</div>
</div>

Keep full-width backgrounds outside the limiter and choose vertical spacing per block. Narrower reading columns can sit inside this shared page width. Apply the side padding once so adjacent blocks line up.

Content tracks

A track controls how much of the page limiter a block occupies and where it sits. Prose and descriptive listings share narrow left, center, and right tracks, plus a wide layout. Alternating their positions adds variation while keeping shared alignment edges.

Narrow tracks use max-w-4xl (56rem / 896px) inside the max-w-7xl page limiter (80rem / 1280px). These are maximum widths, not fixed proportions. Both include the shared side padding.

Narrow left · max-w-4xl
Content starts at the left page edge.
Narrow center · mx-auto max-w-4xl
Content sits in the center of the page.
Narrow right · ml-auto max-w-4xl
Content ends at the right page edge.
Wide · use the full available content width
Content spans the limiter, inside the shared side padding.
Two columns · descriptive listings · 50:50 after the gap
First column
Second column

Vertical block spacing

Generous spacing separates sections. Compact spacing pulls related blocks together. Each block has its own top and bottom padding, chosen independently.

  • A standalone block has generous padding above and below.
  • In a section, the first block has generous top padding and compact bottom padding.
  • Middle blocks have compact padding above and below.
  • The last block has compact top padding and generous bottom padding.
  • A section containing just one block has generous padding above and below.

Padding per edge

Responsive generous and compact padding values
Viewport widthGenerousCompact
Below 640px2.5rem · 40px1rem · 16px
640–767px3.5rem · 56px1rem · 16px
768–1023px4rem · 64px1rem · 16px
1024px and above7rem · 112px1.75rem · 28px

Pixel equivalents assume the default 16px root font size. Adjacent padding adds up: two compact edges create a 32px gap, or 56px from 1024px. Two generous edges create an 80px, 112px, 128px, or 224px gap across the same viewport ranges.

Standalone block

Generous

Independent content

Generous

Three blocks in one section

Generous

First block

Compact
Compact

Middle block

Compact
Compact

Last block

Generous

Shaded bands show the padding at its actual size. Resize the window to compare the scale. Spacing within a block, such as the gap between a heading and a paragraph, is a separate choice.

Sample block implementation

A top-level block receives its section context through mark, aliased to section. As in Prose.svelte, the block derives its top and bottom padding from that context. No extra padding props are needed.

Sample prose block

<script lang="ts">
	import { Node, NodeArrayProperty } from 'svedit';
	import type { DocumentPath, NodeArrayAttachmentContext } from 'svedit';

	let {
		path,
		mark: section = null
	}: {
		path: DocumentPath;
		mark?: NodeArrayAttachmentContext | null;
	} = $props();

	let padding_top_generous = $derived(!section || section.is_start);
	let padding_bottom_generous = $derived(!section || section.is_end);
</script>

<Node {path} class="bg-(--background) text-(--foreground)">
	<div class="mx-auto max-w-7xl">
		<div class={[
			'px-5 sm:px-7',
			padding_top_generous ? 'pt-block-generous' : 'pt-block-compact',
			padding_bottom_generous ? 'pb-block-generous' : 'pb-block-compact'
		]}>
			<NodeArrayProperty
				path={[...path, 'body']}
				class="flex flex-col gap-5 sm:gap-7"
			/>
		</div>
	</div>
</Node>
  • No section mark: both edges are generous.
  • section.is_start: the top edge is generous.
  • section.is_end: the bottom edge is generous.
  • section.is_middle: both edges are compact; the two boundary checks already cover this case.
  • A one-block section is both the start and the end, so both edges are generous.

The app uses shared utilities in src/app.css for the default rhythm: pt-block-generous, pt-block-compact, and their pb- equivalents. They apply the values above to existing elements without adding a wrapper component.

For a custom rhythm, replace the default utility on that edge with explicit responsive classes, such as pt-8 lg:pt-16. Avoid combining a default utility with overrides on the same edge. Keep deliberate exceptions local: flush and full-bleed figures have no vertical padding.

Typography

A shared scale for headings and body text.

display-1

Make room for what matters.

display-2

Make room for what matters.

display-3

Make room for what matters.

display-4

Make room for what matters.

display-5

Make room for what matters.

body-xl

Good design makes everyday things easier to understand. Clear words, comfortable spacing, and a thoughtful hierarchy help people find what they need and decide what to do next.

body-lg

Good design makes everyday things easier to understand. Clear words, comfortable spacing, and a thoughtful hierarchy help people find what they need and decide what to do next.

body-base

Good design makes everyday things easier to understand. Clear words, comfortable spacing, and a thoughtful hierarchy help people find what they need and decide what to do next.

body-sm

Good design makes everyday things easier to understand. Clear words, comfortable spacing, and a thoughtful hierarchy help people find what they need and decide what to do next.

Inline formatting

Emphasis and detail within the flow of a sentence.

Emphasis · em

Start with what people actually need.

Bold · strong

Keep the most important information easy to find.

Code · code

Use font-medium for button labels.

Highlight · mark

Highlight the part worth remembering, not the whole paragraph.

Buttons

Standard size. Hover, press, or tab to explore the states.

Primary

Secondary

Small buttons

For navigation and compact layouts. Small buttons keep a 36px minimum height on all devices.

Primary

Secondary

Disabled buttons

Buttons and pill controls use 40% opacity with the default cursor. Native disabled buttons skip keyboard focus and suppress hover and press feedback. Menu rows instead use muted text to keep unavailable actions legible.

Primary

Secondary

Small primary

Small secondary

Editing pill

Descriptive listing

A linked row with a title, description, and optional metadata. Hover or press anywhere on the row to strengthen the title underline; keyboard focus outlines the whole row. A plain listing uses the same recipe with the description omitted.

Boxed items

Boxed items use a muted surface. Their secondary buttons use the background color at rest and the muted color on hover. This styling applies only to secondary buttons inside the box.

Make it your own

Start with the shared styles and adapt them to your site.

Explore buttons

Editor pills

Compact surfaces for tools, actions, and previews.

Toolbar

Inline call to action

Variant selector and select parent

Editor forms

Link and media prompts use an opaque surface with 4px padding, no shadow, and the button radius capped at 1rem. Fields and actions subtract the padding and border from that radius. Text inputs and textareas use 16px text and an editing-color border on focus.

Page browser

A muted editing fill marks the result Enter will open. Only keyboard-focused rows get a ring, drawn inside the row to keep tree guides and adjacent rows clear. Search focus uses a thin editing-color border. Action menus reuse the list popover recipe.

List popovers

Compact lists with a shared surface and aligned rows.