Skip to content

Customize the look

Every surface of <sealpixel-editor> reads CSS custom properties, forwards its inner elements as ::part() names and picks one of six shipped locales from the locale attribute. Open the Customize pane at the bottom right, change what you like, and copy the CSS it prints. The same controls work on any page of these docs that shows an editor.

What the pane changes

ControlWhat it sets
PresetLoads one of @sealpixel/ui/themes/{nocturne,studio,minimal,high-contrast}.css (the default look needs no stylesheet)
ModeThe `theme="dark
Accent--sealpixel-color-accent, a matching --sealpixel-color-accent-fg for contrast, --sealpixel-color-accent-soft and --sealpixel-color-focus
Radius, spacing, font size--sealpixel-radius(-sm), --sealpixel-space, --sealpixel-font-size
LanguageThe locale attribute; shipped dictionaries resolve automatically
Pill buttonsA sealpixel-editor::part(button) rule that reaches into the nested shadow roots

Every token

css
sealpixel-editor {
  --sealpixel-color-bg: #0f1117;          /* page behind the stage */
  --sealpixel-color-surface: #161923;     /* nav, panel, toolbar */
  --sealpixel-color-surface-2: #1f2330;   /* buttons, inputs */
  --sealpixel-color-surface-3: #2a2f3d;   /* hover, tracks */
  --sealpixel-color-border: #2b3040;
  --sealpixel-color-fg: #eef0f6;
  --sealpixel-color-fg-muted: #a3a9b8;
  --sealpixel-color-accent: #ff6f4c;
  --sealpixel-color-accent-fg: #1c0d08;   /* text on the accent */
  --sealpixel-color-accent-soft: rgba(255, 111, 76, 0.16); /* pressed and active tints */
  --sealpixel-color-danger: #ef5a5a;
  --sealpixel-color-focus: #ff9b7e;
  --sealpixel-shadow: 0 10px 30px rgba(0, 0, 0, 0.35); /* under the canvas */
  --sealpixel-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);     /* resting buttons */
  --sealpixel-shadow-raised: 0 4px 12px rgba(0, 0, 0, 0.32); /* hovered and grabbed */
  --sealpixel-radius: 12px;
  --sealpixel-radius-sm: 8px;
  --sealpixel-space: 8px;
  --sealpixel-font: 'Inter', system-ui, sans-serif;
  --sealpixel-font-size: 14px;
  --sealpixel-toolbar-size: 72px;  /* width of the tool rail */
  --sealpixel-panel-size: 112px;   /* height of the control bar under the stage */
  --sealpixel-touch-target: 44px;  /* a finger's target, and the control height on touch */
  --sealpixel-control-height: 32px; /* a control in the bar, with a pointer */
  --sealpixel-radius-pill: 999px;
  --sealpixel-stage-checker-a: #1a1d27;
  --sealpixel-stage-checker-b: #13161e;
  --sealpixel-duration-fast: 120ms;       /* hover, press */
  --sealpixel-duration: 200ms;            /* the default for a state change */
  --sealpixel-duration-slow: 320ms;       /* the stage gliding to a fit */
  --sealpixel-ease: cubic-bezier(0.3, 0, 0.2, 1);        /* standard */
  --sealpixel-ease-out: cubic-bezier(0.16, 1, 0.3, 1);   /* something arriving */
  --sealpixel-ease-spring: cubic-bezier(0.34, 1.4, 0.64, 1); /* a control under the finger */
  --sealpixel-transition: var(--sealpixel-duration-fast) var(--sealpixel-ease);
}

Motion

Three durations and three curves carry every animation. --sealpixel-ease is for a state change the pointer already explains, such as hover or press. --sealpixel-ease-out decelerates hard and suits something that arrives: a tool panel, a toast, the stage settling after a fit. --sealpixel-ease-spring overshoots a little and is reserved for a control the finger is on, such as the dial needle, where the overshoot reads as give.

To slow the whole editor down, or to speed it up, set the durations:

css
sealpixel-editor {
  --sealpixel-duration-fast: 80ms;
  --sealpixel-duration: 140ms;
  --sealpixel-duration-slow: 200ms;
}

To remove animation completely, set all three to 0s. The editor already does this for a visitor whose system asks for reduced motion, including the glide the stage uses when it fits the image, so you do not have to handle that case.

--sealpixel-transition is the older single shorthand. It still works and still feeds the hover and press transitions, but it no longer covers everything; the durations above do.

Parts

root, nav, stage, panel, toolbar, undo, redo, history, export, download, dimensions, tool, button, dial, stepper, step-up, step-down, input, viewport, canvas, overlay, status, toast, empty.

css
sealpixel-editor::part(export) { display: none; }          /* download only */
sealpixel-editor::part(tool) { font-size: 0; }              /* icons without labels */
sealpixel-editor::part(nav) { background: transparent; }

Icons

Tool icons are Lit templates in the icons export of @sealpixel/ui. Replace one by handing the editor a tool with your own icon:

ts
import { cropTool } from '@sealpixel/ui';
import { html } from 'lit';

editor.tools = { crop: { ...cropTool, icon: html`<svg viewBox="0 0 24 24">…</svg>` } };

Layout

Tool controls sit in a bar under the stage at every width, so a control is in the same place on a phone and on a desktop. The bar keeps a fixed height, set by --sealpixel-panel-size, because a bar that grew and shrank between tools would resize the stage under the image. Its blocks lay out across the width and wrap; chips, filter presets and asset libraries take a full row of their own. Above 48rem the tool rail runs the full height beside both the stage and the bar, so every tool stays in reach while a tool is open.

Raise --sealpixel-panel-size to give a busy panel more room, or lower it to give the image more. A panel taller than the bar scrolls, and its bottom row stays pinned.

Controls in the bar are 32 px tall for a pointer and the full --sealpixel-touch-target under @media (pointer: coarse), so a finger gets 44 px and a mouse gets a bar that does not shout. Set --sealpixel-control-height to var(--sealpixel-touch-target) to have 44 px everywhere.

A tool panel has two kinds of control, and the bar separates them. The choice of what to work with, such as a shape, a frame style or a parameter, goes on the bottom row where it continues the tool rail; the settings for whatever is chosen appear above it. Mark that row with class="choice" and the bar places it, so a panel's source stays in reading order and a third-party tool joins in with one class.

Tools with many controls show one at a time: finetune is one dial plus a row of parameter chips, where a chip carries a dot once its parameter has been moved. Filter presets are live thumbnails of the current image, with the untouched image first and a rule separating it from the presets.

Below 48rem the editor stacks nav, stage, the bar and a horizontal toolbar. Above 48rem the toolbar moves to the left edge and --sealpixel-toolbar-size sets its width; the bar stays where it is.

Photo on this page by Jeremy Bishop on Unsplash.