PathLogs UI
Русский

Getting started

Themes and tokens

CSS variables, light and dark themes, and a palette of your own.

The entire theme is a flat set of CSS variables. Components only ever read var() and contain no colours of their own, so you can recolour them without touching a single line inside the package.

Tokens

--backgroundPage background
--surfaceCards, panels, dialogs
--surface-2Inputs, nested surfaces
--borderBorders (the utility is called border-edge)
--foregroundPrimary text
--mutedSecondary text
--accentAccent: buttons, links, focus
--accent-hoverAccent on hover
--accent-2, --accent-3, --accent-pinkExtra accents for gradients
--accent-foregroundText on an accent fill
--danger, --success, --warning, --infoState semantics

Besides colours there are radii (--radius-sm --radius-2xl), shadows (--shadow --shadow-2xl), timings (--duration, --ease-out-expo) and a scale of layers.

Light and dark

Dark is the default value on :root. Light is switched on by an attribute on <html>:

html
<html data-theme="light">

The value system hands the decision to the prefers-color-scheme media query. All of this is what useTheme does:

Выбор пользователя
dark
Что на экране
dark

Меняется тема всего сайта — состояние живёт в атрибуте на <html>, а не внутри компонента.

Your own palette

Redefine the variables after importing the tokens — the cascade does the rest. No component needs to know about it:

css
@import "@toimetdev/pathlogs-tokens/styles/index.css";

:root {
  --accent: #0ea5e9;
  --accent-hover: #38bdf8;
  --accent-2: #06b6d4;
  --radius: 0.25rem;
}

[data-theme="light"] {
  --accent-hover: #0284c7;
}

Tailwind utilities

The bridge in tokens/styles/tailwind.css declares @theme inline, so the utilities point at the variables rather than at values — a theme change cascades into them with no rebuild:

tsx
<div className="rounded-xl border border-edge bg-surface p-4 text-foreground">
  <p className="text-muted">Secondary text</p>
  <button className="bg-accent text-accent-foreground hover:bg-accent-hover">
    Button
  </button>
</div>

The border utility is called border-edge rather than border-border: the latter would read like a stutter.

Working with colour

Label and column colours are chosen by the user, so the package knows how to compute readability and transparency:

tsx
import { alpha, readableTextOn, luminance, backdropCss } from "@toimetdev/pathlogs-tokens";

alpha("#6366f1", 0.3);       // "#6366f14d" — eight-digit hex, safe inside gradients
readableTextOn("#ffff00");   // "#000000" — white on yellow is unreadable
luminance("#1b2233");        // relative luminance per WCAG 2.1

backdropCss({ color: "#6366f1", colorTo: "#ec4899", angle: 45 });
alpha(hex: string, opacity: number) => string

Transparency as eight-digit hex rather than rgba(): such a string can be concatenated into gradients and dropped into CSS variables without being parsed.

readableTextOn(hex: string) => "#000000" | "#ffffff"

Black or white — whichever contrasts better on that background. Computed from luminance, not from «looks dark to me».

backdropCss(bg: SurfaceBackdrop) => string

A translucent backdrop: a single blob or a gradient. One function serves both the backdrop itself and its preview in settings, so the two cannot drift apart.

BOARD_PALETTEreadonly string[]

A muted palette for cards, columns and labels.

SURFACE_PALETTEreadonly string[]

A vivid palette for backdrops: the background is translucent, and muted shades disappear against it.

Layers

A shared z-index scale matters more than it looks: without one, a portal from one component covers a portal from another in arbitrary order.

css
--z-sticky: 20;    /* sticky panels */
--z-header: 30;    /* header, drawer scrim */
--z-drawer: 40;    /* sliding sidebar */
--z-dropdown: 50;  /* dropdown panels, mention menus */
--z-modal: 60;     /* dialogs and the command palette */
--z-toast: 80;
--z-tooltip: 90;   /* tooltips — above everything */