万物皆点集,交互即映射。给个人网站与公开发布的 WebGL 动画使用的设计系统:页面底下是一张点阵,名字、模型、定理、证明全部由点组成,所有交互都是从一个点集到另一个点集的映射。世界为 夜 Night。

包含什么

部件文件说明
点场 Field(签名)src/gl/field.jsGPU 模拟 65,536 点(手机 25,600);弹簧入集、ABC 流过渡、指针场、按住熔化、点击冲击波、拖拽旋转 3D 集
点集 Setssrc/gl/sets.js点阵、5×7 点阵字、洛伦兹吸引子、三叶结、面心立方晶体、克莱因瓶、斐波那契球
定理之瀑 Cascade(签名)src/gl/cascade.js依赖 DAG 以瀑布倾泻;悬停显示上游(橙)与下游(冰蓝);点击生长证明树。展示页有两个版本:自由探索(小而透明的说明)与巡游(随滚动按依赖顺序逐个悬停 16 个关键结果,每两格滚轮一个,无侧栏)
证明树 ProofTree(签名)src/gl/prooftree.js把 DAG 展开成以结论为根、公理为叶的证明树;相机到达时开始生长,旁边进度条同步结晶;swap(id) 旋转转场,展示页用它随滚动连播 6 棵证明树
舞台 Stagesrc/gl/stage.js单一 WebGL 上下文、滚动驱动的相机站点、辉光、自适应分辨率、不可见时停机
光标光环src/dom/cursor.js光标的点集在可操作控件轮廓上重组,兼作键盘焦点指示
控件src/dom/controls.js标签页(点群指示器)、开关(气态/晶态)、滑块(点列)、进度(结晶)
点阵字与加载器src/dom/dottext.js字符串之间逐点重排;洛伦兹轨迹加载器
命令面板与消息src/dom/command.js⌘K / Ctrl+K;消息带点阵标签
声音src/core/sound.js合成音色,默认关闭
数据src/data/analysis.js43 条实分析结果的依赖图(ZFC → Picard–Lindelöf / Peano)
令牌与样式src/tokens.css · src/components.css颜色、字体、间距、组件样式

开发与构建

Set-Location lattice
npm install
node serve.mjs 4187        # http://127.0.0.1:4187/showcase/
node build.mjs             # 生成 dist/lattice-showcase.html,并刷新 project/ 与 dist/catalog/

依赖只在本目录:three@0.186.1(运行时,被打包进单文件)、esbuild、playwright-core(仅截图与测试,使用本机 Chrome/Edge)。

接入示例

import { Stage } from "./src/gl/stage.js";
import { Field } from "./src/gl/field.js";
import * as SETS from "./src/gl/sets.js";
import { WORLDS } from "./src/core/theme.js";

const stage = new Stage(canvas, [{ id: "hero", el: ".hero", pos: [0, 0, 10], look: [0, 0, 0] }], WORLDS.night);
const field = new Field(stage);
field.useSets(SETS);
stage.add(field);
field.onResize(stage);
// 任意点集:返回 N×4 的 Float32Array(xyz + 类别 w:0 隐藏 · 0.35 点阵 · 1 点亮)
field.keep((L) => L.lit([{ map: SETS.matrixText("HELLO", 2), col: 10, row: 12 }]), { dur: 1.5 });
field.keep((L) => L.shape(SETS.lorenz(field.N, 2)), { is3d: true, alpha: 0.22 });

依赖图数据只需 { id, en, zh, st, deps, kind, topic, leaf? }:new Cascade({ theorems, depth, topicOrder })、new ProofTree({ byId }).grow(id)。换成自己的主题图(课程、项目、因子)即可复用两个签名页面。

DOM 控件保留原生语义,只在上面画点:mountTabs(el)、mountSwitch(btn)、mountSlider(input)、mountProgress(el).set(0.4)、mountDotText(el).set("QED")、mountLoader(el)、mountCommands([...])、toast("…", { tag: "OK" })、mountCursor()。

工具

脚本作用
tools/build-project.mjs从源码生成 project/(令牌解析自 src/tokens.css、window.Lattice 经典脚本包、组件预览来自 catalog/),再调用 ds-viewer
tools/author-catalog.py组件卡的源文件(预览与说明)写入 catalog/components/
tools/smoke.mjs交互冒烟测试(30 项,含减少动态)
tools/check-dist.mjs · tools/check-catalog.mjs单文件与查看页的无头检查
tools/capture.mjs逐帧确定的截图与对比图

project/ 与 dist/ 都是生成物,不要手改。

录制动画(配合 Video Gen)

在地址后加 ?record,时间只由 lattice.renderAt(t) 推进,逐帧确定。tools/capture.mjs 是可直接改写的逐帧截图示例:

node tools/capture.mjs              # 夜间世界的 6 个场景 + 对比图,输出到 outputs/captures/

需要替换的内容

  • 联系按钮的 mailto:you@example.com(带 data-placeholder)。
  • 「标签页」与「证明树」旁的项目简介为根据会话整理的示意文字,请改成正式文案与链接。
  • 定理之瀑使用真实的实分析依赖数据;如需换成自己的课程或项目图,替换 src/data/analysis.js。

已知限制

  • 字体来自 Google Fonts;完全离线时回退到系统字体(点阵字 5×7 位图不受影响)。
  • 已在无头 Chrome(Intel Arc 140T,D3D11)上验证;尚未在 iPhone、Android 实机与 Safari 上验证。
  • 声音未经人工试听验收;视觉由用户选定方向,最终视觉验收待用户确认。
  • ?world=paper / ?world=ultramarine 仍可用于实验,但不是本系统的承诺世界。

Guideline · design.md

Design System: 点阵 Lattice

Overview

Creative North Star: "The Living Lattice"

Every page stands on one lattice of dots. Nothing is decoration: a name is a set of lit lattice sites, a theorem is a cluster of points, a dependency is a stream of points falling from a premise into what it proves, a proof is a tree of points growing from its conclusion up to its axioms. Interaction is always a map from one set to another. Points are released one by one into a divergence-free ABC flow and then pulled into their new set by springs, so every transition pours instead of cutting.

The system was built for a personal site and for publishable WebGL clips. It speaks to professionals (quant, AI and agent engineering, mathematics, games) who judge depth quickly, so the spectacle always carries real content: the Lorenz attractor with its real parameters, a real dependency graph of real analysis, real proof trees. Night is the committed world: points of light on deep ink, with one warm signal and one cool signal.

It rejects the dark dev-portfolio default (a floating blob, a neon accent, a grid of project cards) and the generic "particles morph into random models" demo. Two worlds were explored and set aside: the bronze luopan formation (符阵) and the paper and ultramarine renditions of this lattice.

Key Characteristics:

  • One GPU point field under the hero; smaller canvases of the same physics inside every control.
  • Two signal colours with fixed meanings: orange for what a thing needs (and for action), ice blue for what it enables.
  • Dot-matrix lettering (5×7 matrix, Doto) against a hyperlegible reading face.
  • Real 3D: perspective camera stations, drag-to-rotate sets, depth-ordered streams.
  • Sound is synthesized, quiet and opt-in: clicks, pentatonic plucks, filtered-noise whooshes, a chord when a proof completes.

Colors

Near-black ink carries points of warm bone light; two signal hues mark direction and never mix roles.

Primary

  • Signal Orange (#ff5a1f): the only action colour and the "needs / upstream" colour. Accent buttons, active tab swarms, crystallised progress, hot (fast or melting) points, premises lit on hover, the heat ring. 5.9:1 on Ink Night.
  • Signal Orange Hover (#ff7440): the accent button's hover state only.

Secondary

  • Ice Blue (#7fd8ff): "enables / downstream" only: descendants in the waterfall, sap flowing down a finished proof tree. 11:1 on Ink Night.

Neutral

  • Ink Night (#07080b): the page and the field's background.
  • Raised Ink (#0d0f14): component specimens and the command palette surface.
  • Bone Point (#ece7da): points at rest, headlines, primary button fill, body text.
  • Dim Point (#9d988c): secondary text and leads (7:1 on Ink Night).
  • Faint Point (#6c685f): disabled text and decoration only (3.6:1; never for body copy).
  • Hover White (#ffffff): the primary button's hover state only (see The Bone-Not-White Rule).
  • Shadow Black (#000000): only inside the two overlay shadows at 70–90% alpha, and as a mask colour.
  • Hairline (rgb(236 231 218 / 0.14)) and Strong Hairline (/ 0.3): 1px insets on panels, ghost buttons, dotted rules.

Named Rules

The Two Directions Rule. Orange means "needs" (upstream, premise, action); ice blue means "enables" (downstream, consequence). Never swap them and never introduce a third signal hue.

The Bone-Not-White Rule. Points and text are warm bone (#ece7da), never #fff; pure white appears only as the primary button's hover.

Typography

Matrix Font: Doto 900 (5×7-style dot-matrix face), and the system's own 5×7 bitmap for text drawn as points Body Font: Atkinson Hyperlegible Next (with Noto Sans SC, system-ui) Chinese: Noto Sans SC 700

Character: The dot-matrix voice is the lattice speaking: captions, counters, gesture names, status lines. The reading voice was chosen for legibility at 12 px over moving points (the waterfall and tree labels), not for fashion.

Hierarchy

  • Hero wordmark (drawn as a particle set, 5×7 matrix at ×2): the name only. It is not a font and is always backed by an <h1> in the DOM.
  • Headline (600, clamp(28px, 3vw, 40px), 1.1, −0.02em): section titles, with the Chinese title above in Noto Sans SC 700 orange at 0.6em.
  • Title (600, 21px, 1.3): component and card titles.
  • Body (400, 17px, 1.6): leads and prose, max 60ch.
  • UI (500, 15px, 1.2): buttons, tabs, switches, navigation.
  • Note (400, 14px, 1.45): specimen notes, card statements, hints.
  • Small (400, 13px, 1.4): legends, footers, secondary metadata.
  • Label (500, 12px): labels pinned to 3D points.
  • Matrix (Doto 900, 15–16px, 0.06em): captions, statuses, gesture names.

Named Rules

The Matrix Size Rule. Doto only at 15px and above. Below that, dot-matrix lettering turns to noise; use the body face.

The Text-in-DOM Rule. Text never lives only inside WebGL. Particle lettering is aria-hidden and mirrored by real text; 3D labels are DOM elements positioned over their points.

The No-Stray-Selection Rule. Dragging on the field never selects text: field sections are user-select: none and a drag the field claims cancels selection; panels and readable copy stay selectable.

Layout

Full-bleed field stations alternate with scrolling content. The hero is one viewport: particle wordmark in the upper third, thesis and gesture legend lower-left, set caption with a matrix index and "Next set" lower-right. While the hero scrolls away, its lattice scrolls 1:1 with the page (the camera follows the section), so the wordmark never slides under the text; only after that do its points rain down into the waterfall. The page then runs: waterfall to explore (300vh, a small transparent note on the left), the tour (16 landmark results, one per two wheel notches, about 200px of scroll), the proof tree (grows when the camera arrives, with a progress bar in its panel), the proof sequence (one tree per ~110vh, a half-turn between trees), the instruments and the close. 3D subjects are shifted right with a camera view offset (0.17–0.2 of the width) so text and subject never overlap. The instruments section is an opaque two-column bench (1200px container, 18px gaps) that hides the field (the GPU pauses whenever no field section is on screen).

Spacing steps are 4, 8, 12, 16, 24, 32, 48, 64 and 96px, with more space above a heading than below. Below 760px: panels stop being sticky and scroll away so the waterfall and tree get the whole screen (the proof-sequence HUD stays sticky on a panel backing and the stand sits lower), the tour card moves below the node, the wordmark breaks onto two lines, the lattice is 46 columns and the field drops to 25,600 points.

Elevation & Depth

Depth is spatial, not shadowed. It comes from the perspective camera, parallax on the pointer, points lifting off the lattice, and bloom on hot points (UnrealBloom, strength 0.55, threshold 0.62). Panels float on the field with a 1px hairline inset and a 10px backdrop blur. The only shadows are deep ambient ones under overlays (card: 0 18px 40px -20px rgb(0 0 0 / 0.7); command palette: 0 30px 80px -30px rgb(0 0 0 / 0.9)).

Named Rules

The Light-Is-Heat Rule. Glow is earned by energy: a point glows orange because it is fast, melting, lit or on a highlighted path, never as a resting decoration.

Shapes

Actions are pills (999px). Panels and specimens have gently rounded corners (12px); small targets 6px. Every mark inside the field is a round point; lines exist only as dotted strands of points (dependencies, branches, dotted rules under inputs). Nodes carry their kind in shape: foundations are square blocks of dots, definitions are rings, theorems are filled Fibonacci discs, axiom leaves are five-petal rosettes.

Named Rules

The Point Rule. If it is visible, it is made of points. No gradients, blobs or solid strokes as decoration; a line is a sequence of dots.

Components

The Field (signature)

  • What: 65,536 points (25,600 on phones) simulated on the GPU. Each has a target in the current set; morphs release points in a sweep into an ABC flow, then springs pull them into the new set.
  • Sets: the resting lattice, lit sites (dot-matrix text as living swarms), and 3D sets (Lorenz attractor, trefoil knot, FCC crystal, Klein bottle); any Float32Array of targets works.
  • Interaction: the pointer is a field (push, swirl, wake). Holding melts the points around it (the cursor ring heats); letting go after melting maps to the next set. A tap is a shockwave. Dragging turns a 3D set.

Waterfall (signature)

  • A dependency DAG laid out by longest-path depth, premises above consequences, topics as depth lanes. Each edge is a strand of static dots plus falling droplets; background mist keeps falling between streams.
  • Hover: premises light orange, consequences ice blue, everything else dims; a card shows the statement. Click: grow that result's proof tree.

Waterfall tour (signature)

  • The same waterfall, no side panel. Scrolling walks 16 landmark results in dependency order (depth, then left to right), one per two wheel notches (about 200px): each is "hovered" once, its premises light orange and its consequences ice blue, the camera glides to it and a card beside it gives the statement. A matrix counter (01–16) marks the place.

Proof tree (signature)

  • The DAG unfolded into a proof tree from a chosen conclusion (root at the base) up to its axioms (leaves). Shared lemmas appear once; later uses are ↺ references.
  • Branch thickness is proportional to √leaves; growth runs by depth with bright tips; each bloom plucks a pentatonic note; when complete, sap runs back down in ice blue and a chord sounds. Drag to turn; click a node to re-root. It grows when the camera arrives (and again after you leave and return), and a progress bar beside it crystallises as the nodes bloom (tree.progress()).
  • Proof sequence: in a scroll-driven section each scroll step shows the next theorem's proof with a rotation transition (tree.swap(id)): the stand turns half a revolution, the old tree falls as dust, the new one grows.

Cursor halo

  • A point with a set of 30 points around it. Over anything actionable (and on keyboard focus) the set re-forms along the control's rounded outline, which doubles as the focus indicator; pressing bursts it; holding on the field heats the ring. Fine pointers only; touch gets a plain ring for the heat.

Buttons

  • Shape: pills (999px), 44px tall, 0 20px padding, 15px/600 label.
  • Primary: Bone Point fill, Ink Night text; hover goes to white.
  • Accent: Signal Orange fill, near-black text. One per view.
  • Ghost: transparent with a strong hairline inset; hover strengthens the inset.
  • Disabled: transparent, Faint Point text, plain hairline.
  • Active: scale(0.96).

Tabs

  • Real role=tab buttons with arrow-key support. The indicator is a 14×2 swarm under the selected tab; on change it pours to the new tab with a stagger and a short burst of flow.

Switch

  • role=switch. Off: 19 points float as a gas across the whole track, each on its own slow Lissajous path. On: they converge on the right and lock into an orange hexagonal crystal (each flashes as it locks), with an orange inset on the track. Turning off melts the crystal outward. A large variant (.lx-switch--lg, 136×54) is for demonstrations; mountSwitch() returns { set(on, { quiet }), on }.

Slider

  • A native range input (invisible, on top) drawn as a row of dots: filled dots orange, unfilled dim, a seven-point orbiting thumb that pushes its neighbours aside.

Progress

  • role=progressbar, three rows of dots. Unfinished work is a gas floating loosely around the bar (smooth Lissajous drift). Each newly finished part is built from it: its points converge, lock into the lattice with a white flash, and stay fixed in orange. Indeterminate: a band of order sweeps through. Completion plays a chord.

Matrix text & loader

  • Matrix text reflows dot by dot between strings (shared strokes slide, the rest fly off or arrive). The loader is a single Lorenz trajectory drawn as a fading trail.

Inputs / Fields

  • Style: no box; a dotted rule (1px dots every 9px) under the text.
  • Focus: the dots turn orange and flow along the rule.
  • Error: the dots tighten to a 5px pitch in orange and the message below turns orange and says what is missing.

Cards / Panels

  • Corner Style: 12px. Background: Ink Night at 78% with a 10px backdrop blur. Border: 1px hairline inset. Padding: 26px (20px on phones).

Command palette & toast

  • ⌘K / Ctrl+K dialog on Raised Ink; the active row is marked by a small swarm that flows between rows. Toasts carry a dot-matrix tag that reflows into place.

Navigation

  • Fixed header: matrix monogram, section links with a Chinese character each (orange when current), sound and ⌘K ghost pills. It gains an ink gradient once the page scrolls; below 760px only the monogram and tools remain.

Do's and Don'ts

Do:

  • Do make every visible effect out of points, and every transition a map from one set to another (release, flow, spring).
  • Do keep orange for "needs / action" and ice blue for "enables" (The Two Directions Rule).
  • Do use real mathematics or real data for every set and graph, labelled with its parameters (σ = 10, ρ = 28, β = 8/3).
  • Do mirror all particle text in the DOM and keep controls' native roles and keyboard behaviour.
  • Do keep the GPU idle when no field section is visible, and respect prefers-reduced-motion (morphs snap, the pointer field and auto-advance stop).

Don't:

  • Don't add decorative glow, gradients or blobs; glow is heat (The Light-Is-Heat Rule).
  • Don't set Doto below 15px or use it for body copy.
  • Don't use pure white for points or text.
  • Don't put the reading text on top of the 3D subject; shift the subject with the camera view offset instead.
  • Don't reintroduce the bronze formation or paper/ultramarine renditions as the default look; Night is the committed world.

Colors

11 tokens · Night. One committed world: points of light on deep ink. Orange means needs/action, ice blue means enables; never swap them.

bg #07080b

Ink Night · page and field background.

bg-2 #0d0f14

Raised Ink · component specimens and the command palette surface.

ink #ece7da

Bone Point · points at rest, the primary button fill.

text #ece7da

Headlines and body text (≥ 12:1 on bg).

text-dim #9d988c

Leads, secondary text, labels (7:1 on bg).

text-faint #6c685f

Disabled text and decoration only (3.6:1, never body copy).

hot #ff5a1f

Signal Orange · action, and 'what it needs' (upstream). 5.9:1 on bg.

hot-2 #7fd8ff

Ice Blue · 'what it enables' (downstream) only. 11:1 on bg.

line rgb(236 231 218 / 0.14)

Hairline · 1px insets on panels and specimens.

line-strong rgb(236 231 218 / 0.3)

Strong hairline · ghost buttons, dotted rules, switch tracks.

panel rgb(7 8 11 / 0.78)

Panel · ink at 78% under a 10px backdrop blur, over the field.

Typography

--font-uiAa 永 123"Atkinson Hyperlegible Next", "Noto Sans SC", system-ui, sans-serif
--font-dotAa 永 123"Doto", "Atkinson Hyperlegible Next", monospace
--font-zhAa 永 123"Noto Sans SC", "Microsoft YaHei", "PingFang SC", sans-serif

Matrix

.matrix-caption15px / 1.3 · 900Captions, statuses, gesture names. Never below 15px.
LORENZ ATTRACTOR · σ = 10

Reading

.headlineclamp(28px, 3vw, 40px) / 1.1 · 600Section titles, with the Chinese title inline before it.
A waterfall of theorems
.title21px / 1.3 · 600Component and card titles.
Bolzano–Weierstrass
.body17px / 1.6 · 400Leads and prose, max 60ch.
Every bounded sequence of reals has a convergent subsequence.
.ui15px / 1.2 · 500Buttons, tabs, switches, navigation.
Next set
.small13px / 1.4 · 400Legends, footers, metadata.
Illustrative summaries; replace with final copy.
.label12px / 1 · 500Labels pinned to 3D points.
Monotone convergence

Chinese

.zh-titleclamp(24px, 2.4vw, 30px) / 1.3 · 700Chinese titles and the thesis line.
万物皆点集,交互即映射。

Spacing

s-14px
Spacing step 1.
s-28px
Spacing step 2.
s-312px
Spacing step 3.
s-416px
Spacing step 4.
s-524px
Spacing step 5.
s-632px
Spacing step 6.
s-748px
Spacing step 7.
s-864px
Spacing step 8.
s-996px
Spacing step 9.

Radius

r-16px
Small targets, focus outlines.
r-212px
Panels, specimens, cards, command palette.
r-pill999px
Buttons, switch tracks, chips.

Duration

t-fast160ms
CSS transitions; the field and dots run on the shared clock.
t-mid320ms
CSS transitions; the field and dots run on the shared clock.
t-slow700ms
CSS transitions; the field and dots run on the shared clock.

Easing

easecubic-bezier(0.16, 1, 0.3, 1)
Default settle.
ease-in-outcubic-bezier(0.65, 0, 0.35, 1)
Exits.

Dot Pitch

pitch9px
Dot pitch for DOM dot patterns (dotted rules, underlines).

Components

14 components

Signature 3

Cascade

A dependency DAG poured as a waterfall

定理之瀑:一张依赖图(DAG)按最长路径深度排成瀑布,前提在上、结论在下。每条依赖是一股从前提落进结论的水滴流,背景的雾点持续下落。

Guidelines

使用

  • 数据:{ id, en, zh, st, deps, kind, topic },kind 决定节点形状(foundation 方块、definition 环、theorem 实心圆)。
  • new Cascade({ theorems, depth: depths(), topicOrder }),放进 stage,相机站点 id 用 fallTop / fallBottom。
  • 事件:hover(id 或 null)、pick(点击的 id)、frame(每帧节点的屏幕坐标,用于摆放 DOM 标签)。
  • cascade.focus(id) 让键盘或列表也能点亮同样的上下游。

规则

  • 橙色只表示「它需要什么」(上游),冰蓝只表示「它推出什么」(下游),不要互换。
  • 文字标签必须是 DOM(LabelLayer),并提供一个可键盘访问的完整列表。

Field

65,536 GPU points that pour from set to set

GPU 点场:每个点都被弹簧拴在当前点集里的一个目标上。换集时,点按扫描顺序逐个松开,先进入 ABC 流(一个无散度的欧拉方程解)再被新集拉回,所以过渡是「倒」过去的,而不是跳过去。

Guidelines

使用

  • new Field(stage) → field.useSets(Lattice.sets) → stage.add(field) → field.onResize(stage)。
  • field.keep(build, opts):build(lattice) 返回 N×4 的 Float32Array(xyz + 类别 w:0 隐藏、0.35 点阵、1 点亮)。窗口尺寸变化时会用同一个 build 重建。
  • 现成的集:L.rest()、L.lit([{map: sets.matrixText('HI', 2), col, row}])、L.shape(sets.lorenz(N, 2))(以及 torusKnot、crystal、klein、sphere)。
  • opts:is3d(随集旋转、可拖拽)、sweep(释放扫描方向)、dur、flow、lit(点亮点的尺寸倍数)、alpha。
  • 事件:press、tap、heat(0–1)、release(detail.melted)。

规则

  • 3D 集必须是真实的数学对象,并在说明里写出参数(如 σ = 10, ρ = 28, β = 8/3)。
  • 按住熔化后松开,才映射到下一个集;单击只是冲击波。
  • prefers-reduced-motion 下过渡瞬间完成,指针场停止。

ProofTree

A proof grows from its conclusion to its axioms

证明树:把依赖图从一个结论展开成证明树。结论是树根(在下),前提逐层向上长成枝,叶子是公理;同一引理只长一次,之后出现处标 ↺。枝的粗细与其下叶子数的平方根成正比。

Guidelines

使用

  • new ProofTree({ byId }) 放进 stage(站点 id tree),tree.grow(id) 开始生长,旧树会像落叶一样凋落。
  • 事件:grow、hover(节点或 null)、pick(点击节点的定理 id,可用来以它为根重新生长)、frame(节点屏幕坐标与开花时刻)。
  • 在数据中用 leaf: true 标出证明止步的地方(例如 ℝ 的完备性)。

规则

  • 生长按深度推进,枝头为橙色;每次开花可拨一个五声音阶的音;全部长成后冰蓝色的汁液从叶流回根,表示证明闭合。
  • tree.progress() 返回生长进度(0–1),适合接一个 mountProgress 进度条放在旁边。
  • tree.swap(id) 是旋转转场:展台转半圈,旧树落叶,新树生长;用于随滚动逐个展示证明树。
  • 标签默认只显示结论、直接前提和公理叶,其余在悬停路径上出现,避免遮挡。

Interaction 1

CursorHalo

The cursor's points re-form around whatever you can press

光标由一个点和它周围的 30 个点组成。经过任何可操作的元素(以及键盘聚焦时),这组点会离开指针,沿控件的圆角轮廓重组并缓慢绕行;按下时向外迸散;在点场上按住时,环会逐渐变成橙色。

Guidelines

使用

  • mountCursor() 一次即可;返回 { setHeat(v) },点场的 heat 事件接到这里。
  • 只在精细指针(鼠标、触控板)上启用;触屏回退为页面自带的热度环。
  • 加 data-no-halo 可以让某个区域不被吸附;加 data-halo 让非交互元素也能吸附。

规则

  • 光环同时是焦点指示:有光标时隐藏浏览器默认焦点框,没有光标时恢复。
  • 不要在光标上加文字标签;它只描轮廓。

Controls 5

Button

Pills: primary, accent, ghost, disabled

按钮是 44px 高的胶囊。主按钮用骨白底、墨色字;强调按钮用信号橙,每个视图最多一个;幽灵按钮是透明底加描边;禁用按钮只剩淡色字和细线。

Guidelines

规则

  • 按下时缩放到 0.96;点阵光标负责悬停与按压的点状反馈,按钮本身不加额外动效。
  • 图标用点阵绘制的 SVG(.lx-icon),不要用字符 → 或 @ 代替图标。

Slider

A row of dots; the thumb pushes its neighbours

滑块:一排点。已选部分为橙色,其余为淡色;七个点组成的拇指绕行,并把相邻的点推开。

Guidelines

使用

  • 原生 <input type="range"> 放在 .lx-slider 里(透明,负责交互与无障碍),mountSlider(input) 负责绘制。

Switch

Off: free-floating gas. On: the points converge and lock

开关:关闭时,点作为气体在整条轨道里自由游离;打开时,点汇聚到右端并锁定成橙色的六边形晶体(每个点落位时闪一下)。同一组点,不同的相。

Guidelines

使用

  • <button class="lx-switch" aria-checked="false"><span class="lx-switch__track"></span>…</button>,mountSwitch(btn)。
  • 事件:switch:change(detail 为布尔值)。

Tabs

The indicator is a swarm that pours to the chosen tab

标签页的指示器是一个 14×2 的点群。切换时点群按顺序松开,带着一小段湍流流向新的标签。

Guidelines

使用

  • 标准 role="tablist" / role="tab" 结构;mountTabs(listEl),方向键切换。
  • 事件:tabs:change(detail.index、detail.value)。

TextField

A dotted rule that flows while you type

文本框:没有边框,只有一条每 9px 一个点的虚线。聚焦时点变成橙色并沿线流动;出错时点距收紧到 5px,下方文字说明缺了什么。

Guidelines

规则

  • 错误信息写清楚问题和补救方式,例如「需要用户名、@ 和域名」。

Feedback 2

Loader

One Lorenz trajectory as a fading trail

加载器:一条洛伦兹轨迹,画成渐隐的点迹,并缓慢旋转。它是系统里「正在思考」的状态。

Guidelines

使用

  • mountLoader(el);元素自动获得 role="status"。

Progress

New progress is built from the gas: points converge and lock

进度条:三行点。未完成的部分是在整条进度条里自由游离的气态点;每完成一段,就从气体里抽出点,汇聚到该段的格点上,落位时闪一下并固定为橙色。不定进度是一道有序的带子扫过;全部完成时奏一个和弦。

Guidelines

使用

  • mountProgress(el) 返回 { set(v), indeterminate(on) };元素带 role="progressbar" 与 aria-valuenow。

Type 1

DotText

5×7 matrix lettering that reflows dot by dot

点阵字:5×7 位图字形画成点。换字符串时,新字仍需要的点滑到新位置,多余的飞走,缺的补进来。适合计数器、编号和短标签。

Guidelines

使用

  • mountDotText(el, { pitch }) 返回 { set(text) };原文本写入 aria-label。
  • 字符集:A–Z、0–9、空格、.、-、·。

规则

  • 只用于短字符串;段落用阅读字体。

Overlays 2

CommandPalette

⌘K: every action on the page, marked by a small swarm

命令面板:⌘K / Ctrl+K 打开的模态对话框。当前行由一小群点标出,上下移动时点群流到新行;输入按子序列过滤。

Guidelines

使用

  • mountCommands([{ id, key, en, zh?, hint?, run }]) 返回 { open, close }。
  • key 用一个汉字或字母作为行首标记,不要用符号字符代替图标。

Toast

Messages with a dot-matrix tag

消息:右下角出现,带一个会逐点重排的点阵标签,几秒后模糊淡出。容器是 role="status" 的礼貌播报区域。

Guidelines

使用

  • toast(message, { tag = 'OK', ms = 2800 })。