You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/CLAUDE.md

7.1 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Build/Test Commands

npm run dev          # Start dev server
npm run build        # Production build (static site via adapter-static)
npm run test         # Run all tests once
npm run test:unit    # Run tests in watch mode
npx vitest run src/lib/ling/test/ling.test.ts  # Run single test file
npx vitest run -t "describe name"              # Run tests matching pattern
npm run check        # Type check with svelte-check
npm run lint         # Check formatting with Prettier
npm run format       # Auto-format with Prettier

Code Style

  • Tabs for indentation, single quotes, no trailing commas, 100 char print width (Prettier)
  • Spanish comments in code are acceptable
  • Svelte 5 runes mode enforced globally (svelte.config.js dynamicCompileOptions)
  • DOM event handlers: lowercase (onclick, onfocus). User callbacks: camelCase (onComplete, onInteractOutside)
  • State fields: $state() without #. Derived: readonly x = $derived.by(...)
  • Boolean attrs: always use helpers (boolToTrueOrUndef, boolToEmptyStrOrUndef, boolToStr) — never ternaries

Path Aliases

Aliases must be synced in BOTH svelte.config.js AND vite.config.ts:

Alias Target
@/ src/
@/ling src/lib/ling (i18n)
@/logr src/lib/logr (logging)
@/glob src/lib/glob (globalization: dates, numbers, locale)
@/actx src/lib/actx (app context)
@/uiux src/lib/uiux
$uix src/uix (UI layers)
$terra src/uix/terra (headless primitives)
$terra/utils src/uix/terra/utils/sound.svelte.ts
$terra/config src/uix/terra/config/exports.ts
$terra/external/dates src/uix/terra/external/dates/sound.svelte.ts
$glob src/lib/glob
$lib src/lib

Vitest Two-Project Structure

vite.config.ts defines two test projects:

  • client: Browser tests via Playwright for *.svelte.{test,spec}.{js,ts}
  • server: Node environment for *.{test,spec}.{js,ts} (excludes svelte tests)

Architecture: Three-Layer UI System

terra  → headless primitives: behavior, accessibility, data-* contracts, context
air    → visual layer on top of terra: tokens, themes, recipes, styled components
glob   → domain logic: dates, numbers, currency, units, locale

The dependency flows one way: air → terra. Terra never imports from air.

terra (src/uix/terra/)

Headless primitive library. Each component follows Element.SubElement pattern (Dialog.Root, Dialog.Trigger, Dialog.Content).

Key patterns:

  • Thin .svelte wrappers + logic in *.svelte.ts State classes
  • State classes use static create() for context registration, createComposed() for internal composition without context
  • Reactive system: Active<T>, State<T>, readableActive(), writableActive() — values travel as boxes with .current
  • Context via createTerraContext() (wraps runed's Context)
  • Props merging: mergeProps(restProps, state.props) in every wrapper
  • data-* attrs are formal public API, validated via assertDataContract() against utils/contracts.ts
  • child snippet replaces the rendered node; children fills the interior

Structure:

  • [component]/components/ — Svelte wrappers
  • [component]/types.ts — public props
  • [component]/*.svelte.ts — State classes
  • [component]/exports.ts + sound.svelte.ts — barrel exports
  • layers/ — shared infra (portal, floating, presence, focus-scope, dismissible, escape, scroll)
  • dom/ — browser-dependent utils (focus, roving focus, arrow navigation)
  • utils/ — pure helpers (state system, attrs, merge-props, events, keyboard, css, datetime)
  • config/ — TerraConfig for cross-cutting services (translator, formatters, logger, dir, portalTo)
  • external/dates/ — adapter boundary for date library

Import rules within terra: use $terra/utils or relative paths internally, never $uix/terra.

air (src/uix/air/)

Visual layer built on terra. Consumes terra's public anatomy and data-* attrs — never internal classes or incidental DOM structure.

Three-level token system:

  1. Primitive tokens (tokens/primitive.css) — absolute scale values, never used directly by components
  2. Semantic tokens (tokens/semantic.css) — theme-aware, switch via [data-theme]
  3. Component tokens (tokens/components/*.css) — scoped per component (--air-button-*), the only level component CSS writes

Token naming:

  • Public: --air-{component}-* (stable, overridable)
  • Private: --_air-{component}-* (implementation detail, may change)

Contracts (contracts/):

  • contract.css — minimum semantic tokens any theme must implement
  • contract-categorical.css — optional categorical color families
  • contract-primitives.css — optional advanced 12-step scales
  • contracts/components/*.css — per-component public token API

CSS rules:

  • Tokens and data-* selectors must be global CSS (imported .css files), not <style scoped>
  • Svelte scoped styles only for properties that don't depend on data-* or terra internals
  • Components respond to terra states purely via data-* selectors: [data-disabled], [data-state='open'], etc.
  • Theme activation via data-theme attribute on any DOM container (supports nesting)
  • Variant dimensions are orthogonal: size → dimensions, variant → appearance, state → transversal overrides

Structure:

  • components/ — styled wrappers over terra primitives
  • tokens/ — token implementation (primitive, semantic, per-component)
  • contracts/ — public token interfaces for theme authors
  • themes/ — theme implementations (base light/dark)
  • icons/ — icon system (Icon + per-icon components in icons/lib/)

Internal Libraries (src/lib/)

  • ling — i18n system (factory: createLing)
  • logr — logging (factory: createLogr, depends on ling)
  • glob — globalization: dates, numbers, currency, locale
  • actx — app context
  • vice — app-level utilities

Important: DateValue and all date utilities come from @/glob/lib, never from @internationalized/date directly. Within terra, use $terra/external/dates.

Test Pages

Component demos live in src/routes/test/. Each terra/air component should have a test page demonstrating its states and variants.

TerraConfig Integration

<TerraConfig {translator} {dateTimeFormatter}>
  <Dialog.Root />
</TerraConfig>

Priority chain for resolved props: explicit component prop → TerraConfig value → internal fallback. TerraConfig supports nesting (child overrides parent partially).

Key Conventions

  • When creating terra components: follow the checklist in src/uix/terra/README.md §21
  • When reading existing modules: start with exports.ts → types.ts → root .svelte → *.svelte.ts → child wrappers → test page
  • $bindable() without fallback when parent might pass undefined; apply defaults via coalescing (see SVELTE5_BINDABLE_PATTERN.md)
  • Components that use Portal: consumer must manage z-index explicitly (layers don't impose z-indices)

Powered by TurnKey Linux.