mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-27 02:12:51 +08:00
🚀 Sync 2026-08-03 08:34:06
This commit is contained in:
1 parent
0c1a7fb257
commit
964b8924bc
11 files changed
+32
-249
No files matched your search
@@ -103,8 +103,8 @@ This will be compiled to standard CSS that works in all browsers.
|
||||
|
||||
The theme has two independent Tailwind CSS v4 entry points, both sourced from `.dev/src/media/`:
|
||||
|
||||
- **`main.css`** — the LuCI admin UI. It is an import manifest that disables Tailwind's automatic source scan (`source(none)`) and pulls in (in order) `_tokens.css` (OKLCH theme tokens, mapped via `@theme inline`), shared `_icons.css`, `_base.css`, `_elements.css`, `_layout.css`, every file in `components/` (one partial per UI component — buttons, cards, modals, tables, etc.), and `_utilities.css`.
|
||||
- **`login.css`** — the standalone login page (`sysauth.ut`). Self-contained: imports Tailwind theme/utilities with `source(none)`, omits full Preflight in favor of a tiny local reset, and imports `_tokens.css` directly. At build time the `login-css-prune` plugin (`vite.config.ts`) strips every custom property the page's var() chains never reach, so the admin-sized token sheet ships login-sized.
|
||||
- **`main.css`** — the LuCI admin UI. It is an import manifest that disables Tailwind's automatic source scan (`source(none)`) and pulls in (in order) `@eamonxg/luci-theme-tokens/dist/aurora/tokens.css` (OKLCH theme tokens, mapped via `@theme inline`), shared `_icons.css`, `_base.css`, `_elements.css`, `_layout.css`, every file in `components/` (one partial per UI component — buttons, cards, modals, tables, etc.), and `_utilities.css`.
|
||||
- **`login.css`** — the standalone login page (`sysauth.ut`). Self-contained: imports Tailwind theme/utilities with `source(none)`, omits full Preflight in favor of a tiny local reset, and imports `@eamonxg/luci-theme-tokens/dist/aurora/tokens.css` directly. At build time the `login-css-prune` plugin (`vite.config.ts`) strips every custom property the page's var() chains never reach, so the admin-sized token sheet ships login-sized.
|
||||
|
||||
Third-party compatibility patches are **not** bundled into `main.css` — they are split into per-page files under `media/patches/` and loaded on demand (see [On-Demand Third-Party Patches](#on-demand-third-party-patches) below).
|
||||
|
||||
@@ -210,18 +210,19 @@ Style a third-party app's page — write or adjust its `patches/*.css`, or check
|
||||
|
||||
### Design Tokens
|
||||
|
||||
`src/media/_tokens.css` is **generated** — its header says "DO NOT EDIT". The source of truth is the standalone [`@eamonxg/aurora-tokens`](https://github.com/eamonxg/aurora-tokens) npm package, consumed here as a devDependency:
|
||||
There is no local `_tokens.css` and no generation step: `main.css`/`login.css` `@import "@eamonxg/luci-theme-tokens/dist/aurora/tokens.css"` directly, resolved straight out of `node_modules` at build time. The source of truth lives in the standalone [`@eamonxg/luci-theme-tokens`](https://github.com/eamonxg/luci-theme-tokens) npm package, consumed here as a devDependency:
|
||||
|
||||
- **`defaults.js`** — the 10 editable input colors (`bg`, `surface`, `text`, `brand`, `on_brand`, `link`, `info`, `warning`, `success`, `danger`) for light and dark mode, as OKLCH strings.
|
||||
- **`spec.js`** — `DERIVATIONS` (how every other token — `text_muted`, `surface_sunken`, `hairline`, `brand_hover`, `brand_subtle`, `focus_ring`, `progress_start`/`progress_end`, `*_surface`, `scrim`, `mega_menu_bg`, …) is computed from the inputs via `mix`/`shade`/`set`/`alpha`/`const` operators, and `FIXED` (mode-specific literals such as shadows that bypass derivation).
|
||||
- **`aurora/defaults.js`** — the 10 editable input colors (`bg`, `surface`, `text`, `brand`, `on_brand`, `link`, `info`, `warning`, `success`, `danger`) for light and dark mode, as OKLCH strings.
|
||||
- **`aurora/spec.js`** — `DERIVATIONS` (how every other token — `text_muted`, `surface_sunken`, `hairline`, `brand_hover`, `brand_subtle`, `focus_ring`, `progress_start`/`progress_end`, `*_surface`, `scrim`, `mega_menu_bg`, …) is computed from the inputs via `mix`/`shade`/`set`/`alpha`/`const` operators, and `FIXED` (mode-specific literals such as shadows that bypass derivation).
|
||||
- **`engine.js`** — the OKLCH/OKLAB color math behind those operators, via [colorjs.io](https://colorjs.io/).
|
||||
- **`resolve.js`** — `resolveMode(mode)` walks `DERIVATIONS` and returns a flat `{token: oklchString}` map with no `color-mix()`/`var()` left in it. `.dev/scripts/gen-tokens.js` imports `resolveMode`/`FIXED` straight from the package root.
|
||||
- **`resolve.js`** — `createResolver` walks a `DERIVATIONS` spec and returns a flat `{token: oklchString}` map with no `color-mix()`/`var()` left in it; `aurora/index.js` pre-binds this to Aurora's own spec as `resolveMode(mode)`, exported from the package's `/aurora` entry point.
|
||||
- **`dist/aurora/tokens.css`** — built by the package's own `build.mjs` (its `prepublishOnly`) and shipped in the published tarball; nothing in this repo regenerates it.
|
||||
|
||||
**Changing a color:**
|
||||
|
||||
1. Edit `spec.js`/`defaults.js` in the [`aurora-tokens`](https://github.com/eamonxg/aurora-tokens) repo (derivation rules, fixed literals, base input colors), tag a release so CI publishes the package, then bump the `@eamonxg/aurora-tokens` devDependency version here and run `npm install`. For unreleased iteration against a local checkout, run `npm link ../../aurora-tokens` from `.dev` instead of bumping/publishing.
|
||||
2. Run `pnpm gen:tokens` (also runs automatically as part of `pnpm build`) to rewrite `src/media/_tokens.css` — it emits `:root` (light) and `[data-darkmode="true"]` (dark) blocks plus the `@theme inline` mapping, in that order.
|
||||
3. Run `pnpm test` to check the color-math operators and derived-token invariants (`tests/engine.test.js`, `tests/resolve.test.js`, `tests/surfaces.test.js`) — e.g. hue families, lightness ordering between `bg`/`surface_sunken`/`surface`, and translucency of menu backgrounds.
|
||||
1. Edit `aurora/spec.js`/`aurora/defaults.js` in the [`luci-theme-tokens`](https://github.com/eamonxg/luci-theme-tokens) repo (derivation rules, fixed literals, base input colors), tag a release so CI tests, builds `dist/`, and publishes the package, then bump the `@eamonxg/luci-theme-tokens` devDependency version here and run `pnpm install`. For unreleased iteration against a local checkout, run `pnpm link ../../luci-theme-tokens` from `.dev` instead of bumping/publishing.
|
||||
2. Run `pnpm build` — Vite resolves `@eamonxg/luci-theme-tokens/dist/aurora/tokens.css` straight from `node_modules`, so a version bump (or `pnpm link`) is all a color change needs on this side.
|
||||
3. Run `pnpm test` to check the color-math and derived-token invariants (`tests/resolve.test.js`, `tests/surfaces.test.js`, both importing `resolveMode` from `@eamonxg/luci-theme-tokens/aurora`) — e.g. hue families, lightness ordering between `bg`/`surface_sunken`/`surface`, and translucency of menu backgrounds.
|
||||
|
||||
**Runtime overrides from UCI:** `header.ut` reads `uci get_all aurora.theme` on each render and re-emits stored tokens as CSS custom-property overrides in an inline `<style>` after `main.css`. Keys are namespaced by prefix — `light_*` and `struct_*` land in `:root`, `dark_*` in `[data-darkmode="true"]` — with the prefix stripped and `_` mapped to `-` (e.g. `light_surface_sunken` → `--surface-sunken`). The template flattens all keys in a single pass into two pre-joined declaration strings (rather than per-key template loops), which halves the iteration work and keeps the emitted `<style>` compact. This is the hook `luci-app-aurora-config` writes through.
|
||||
|
||||
@@ -279,10 +280,9 @@ htdocs/luci-static/
|
||||
|
||||
**Build Process:**
|
||||
|
||||
1. `pnpm gen:tokens` regenerates `src/media/_tokens.css` from `@eamonxg/aurora-tokens` (see [Design Tokens](#design-tokens))
|
||||
2. Vite builds the CSS entry points (`src/media/main.css` and `src/media/login.css`), keeping Tailwind's native `@layer` structure
|
||||
3. Custom Vite plugin (`luci-js-compress`) minifies JS files via Terser
|
||||
4. Static assets copied from `.dev/public/aurora/`
|
||||
1. Vite builds the CSS entry points (`src/media/main.css` and `src/media/login.css`), resolving `@eamonxg/luci-theme-tokens/dist/aurora/tokens.css` straight from `node_modules` (see [Design Tokens](#design-tokens)) and keeping Tailwind's native `@layer` structure
|
||||
2. Custom Vite plugin (`luci-js-compress`) minifies JS files via Terser
|
||||
3. Static assets copied from `.dev/public/aurora/`
|
||||
|
||||
## Package Compilation
|
||||
|
||||
@@ -325,15 +325,13 @@ luci-theme-aurora/
|
||||
│ │ └── images/ # Theme images + PWA icons
|
||||
│ ├── scripts/ # Build scripts + dev-server client helpers
|
||||
│ │ ├── clean.js # Build cleanup utility
|
||||
│ │ ├── gen-tokens.js # Regenerates src/media/_tokens.css from @eamonxg/aurora-tokens
|
||||
│ │ ├── mock-bar.client.js # Injected into device pages and /mocks/ — snapshot bar, capture, link takeover
|
||||
│ │ └── setup.js # pnpm setup:router — .env wizard + passwordless SSH to the router
|
||||
│ ├── src/ # Source code
|
||||
│ │ ├── assets/icons/ # SVG icons
|
||||
│ │ ├── media/ # CSS source (Tailwind CSS v4)
|
||||
│ │ │ ├── main.css # Admin UI entry point (import manifest)
|
||||
│ │ │ ├── main.css # Admin UI entry point (import manifest; tokens via @eamonxg/luci-theme-tokens)
|
||||
│ │ │ ├── login.css # Login page entry point
|
||||
│ │ │ ├── _tokens.css # OKLCH theme tokens -- GENERATED, see @eamonxg/aurora-tokens
|
||||
│ │ │ ├── _base.css # Document foundation (html/body viewport bg)
|
||||
│ │ │ ├── _elements.css # Base element styles (headings, links, …)
|
||||
│ │ │ ├── _layout.css # Page layout/structure
|
||||
@@ -343,8 +341,7 @@ luci-theme-aurora/
|
||||
│ │ └── resource/ # JavaScript resources
|
||||
│ │ └── menu-aurora.js # Menu logic
|
||||
│ ├── tests/ # All test suites (pnpm test)
|
||||
│ │ ├── engine.test.js # Color-math operators
|
||||
│ │ ├── resolve.test.js # Resolved token invariants
|
||||
│ │ ├── resolve.test.js # Resolved token invariants (against @eamonxg/luci-theme-tokens/aurora)
|
||||
│ │ ├── surfaces.test.js # Surface/hue layering invariants
|
||||
│ │ ├── overlay.test.js # Overlay/layout CSS assertions
|
||||
│ │ └── navigation-*.test.js # Navigation model/rendering/styles
|
||||
@@ -386,7 +383,7 @@ luci-theme-aurora/
|
||||
- **[Vite](https://vitejs.dev/)** - Build tool and development server
|
||||
- **[pnpm](https://pnpm.io/)** - Fast, disk space efficient package manager
|
||||
- **[lightningcss](https://lightningcss.dev/)** - CSS minifier
|
||||
- **[colorjs.io](https://colorjs.io/)** - OKLCH/OKLAB color math for design token generation (used by [`@eamonxg/aurora-tokens`](https://github.com/eamonxg/aurora-tokens))
|
||||
- **[colorjs.io](https://colorjs.io/)** - OKLCH/OKLAB color math for design token generation (used by [`@eamonxg/luci-theme-tokens`](https://github.com/eamonxg/luci-theme-tokens))
|
||||
- **[Terser](https://terser.org/)** - JavaScript minifier
|
||||
- **[Prettier](https://prettier.io/)** - Code formatter
|
||||
- **[prettier-plugin-tailwindcss](https://github.com/tailwindlabs/prettier-plugin-tailwindcss)** - Tailwind class sorting
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"setup:router": "node scripts/setup.js",
|
||||
"build": "npm run clean && npm run gen:tokens && vite build",
|
||||
"build": "npm run clean && vite build",
|
||||
"clean": "node scripts/clean.js",
|
||||
"gen:tokens": "node scripts/gen-tokens.js",
|
||||
"test": "node --test tests/*.test.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eamonxg/aurora-tokens": "^1.3.1",
|
||||
"@eamonxg/luci-theme-tokens": "^2.0.0",
|
||||
"@tailwindcss/vite": "^4.1.11",
|
||||
"@types/node": "^24.0.0",
|
||||
"browserslist": "^4.28.2",
|
||||
|
||||
Generated
+6
-6
@@ -8,9 +8,9 @@ importers:
|
||||
|
||||
.:
|
||||
devDependencies:
|
||||
'@eamonxg/aurora-tokens':
|
||||
specifier: ^1.3.1
|
||||
version: 1.3.1
|
||||
'@eamonxg/luci-theme-tokens':
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0
|
||||
'@tailwindcss/vite':
|
||||
specifier: ^4.1.11
|
||||
version: 4.3.2(vite@7.3.1(@types/node@24.10.9)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.0))
|
||||
@@ -44,8 +44,8 @@ importers:
|
||||
|
||||
packages:
|
||||
|
||||
'@eamonxg/aurora-tokens@1.3.1':
|
||||
resolution: {integrity: sha512-G3QC2zmFO+eMKa/zvxINOMs0BMU5sKbx9khW5B+00uEpPjcfoyFH253BYuq8CYCAxERgdxbkT/c9hFOThEyhvw==}
|
||||
'@eamonxg/luci-theme-tokens@2.0.0':
|
||||
resolution: {integrity: sha512-LSPR6fW5iDN0r4eEfLLVirIgjJxUN8L1uJ3hZDHZRPbHtRE8v21pJSMhZoQKerCXUJx3spZc3W3r9f+baw3Jqw==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.27.2':
|
||||
resolution: {integrity: sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==}
|
||||
@@ -768,7 +768,7 @@ packages:
|
||||
|
||||
snapshots:
|
||||
|
||||
'@eamonxg/aurora-tokens@1.3.1':
|
||||
'@eamonxg/luci-theme-tokens@2.0.0':
|
||||
dependencies:
|
||||
colorjs.io: 0.6.1
|
||||
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { resolve } from "node:path";
|
||||
import {
|
||||
resolveMode,
|
||||
FIXED,
|
||||
STRUCTURE,
|
||||
THEME_STRUCTURE,
|
||||
} from "@eamonxg/aurora-tokens";
|
||||
|
||||
const kebab = (s) => s.replace(/_/g, "-");
|
||||
|
||||
function block(selector, colors, fixed) {
|
||||
const lines = [];
|
||||
for (const [k, v] of Object.entries(colors)) {
|
||||
lines.push(` --${kebab(k)}: ${v};`);
|
||||
}
|
||||
for (const [k, v] of Object.entries(fixed)) {
|
||||
lines.push(` --${kebab(k)}: ${v};`);
|
||||
}
|
||||
return `${selector} {\n${lines.join("\n")}\n`;
|
||||
}
|
||||
|
||||
const light = resolveMode("light");
|
||||
const dark = resolveMode("dark");
|
||||
|
||||
// Structural tokens and their @theme mappings come from the shared package,
|
||||
// same as the colours — so spacing, content widths and the radius base have a
|
||||
// single definition instead of one per theme generator.
|
||||
const STRUCTURE_CSS = Object.entries(STRUCTURE)
|
||||
.map(([k, v]) => ` --${kebab(k)}: ${v};`)
|
||||
.join("\n");
|
||||
|
||||
const THEME = `@theme inline {
|
||||
${Object.keys(light)
|
||||
.map((k) => ` --color-${kebab(k)}: var(--${kebab(k)});`)
|
||||
.join("\n")}
|
||||
|
||||
--shadow-sm: var(--app-shadow-sm);
|
||||
--shadow-md: var(--app-shadow-md);
|
||||
--shadow-lg: var(--app-shadow-md);
|
||||
--shadow-xl: var(--app-shadow-lg);
|
||||
--shadow-2xl: var(--app-shadow-lg);
|
||||
|
||||
${Object.entries(THEME_STRUCTURE)
|
||||
.map(([k, v]) => ` --${k}: ${v};`)
|
||||
.join("\n")}
|
||||
}
|
||||
`;
|
||||
|
||||
const HEADER = `/**
|
||||
* luci-theme-aurora: design tokens -- GENERATED, DO NOT EDIT.
|
||||
* Run \`pnpm gen:tokens\`. Source: @eamonxg/aurora-tokens (spec.js + defaults.js)
|
||||
* All color values are flat; lightningcss adds legacy fallbacks.
|
||||
* ORDER MATTERS: [data-darkmode="true"] must stay after :root.
|
||||
*/
|
||||
`;
|
||||
|
||||
const css =
|
||||
HEADER +
|
||||
"\n" +
|
||||
block(":root", light, FIXED.light) +
|
||||
STRUCTURE_CSS +
|
||||
"\n}\n\n" +
|
||||
block('[data-darkmode="true"]', dark, FIXED.dark) +
|
||||
"}\n\n" +
|
||||
THEME;
|
||||
|
||||
await writeFile(
|
||||
resolve(import.meta.dirname, "../src/media/_tokens.css"),
|
||||
css,
|
||||
"utf-8",
|
||||
);
|
||||
console.log("gen-tokens: wrote src/media/_tokens.css");
|
||||
@@ -1,139 +0,0 @@
|
||||
/**
|
||||
* luci-theme-aurora: design tokens -- GENERATED, DO NOT EDIT.
|
||||
* Run `pnpm gen:tokens`. Source: @eamonxg/aurora-tokens (spec.js + defaults.js)
|
||||
* All color values are flat; lightningcss adds legacy fallbacks.
|
||||
* ORDER MATTERS: [data-darkmode="true"] must stay after :root.
|
||||
*/
|
||||
|
||||
:root {
|
||||
--bg: oklch(0.984 0.004 235);
|
||||
--surface: oklch(1 0 0);
|
||||
--text: oklch(0.215 0.02 250);
|
||||
--brand: oklch(0.58 0.14 233);
|
||||
--on-brand: oklch(1 0 0);
|
||||
--link: oklch(0.58 0.14 233);
|
||||
--info: oklch(0.45 0.12 250);
|
||||
--warning: oklch(0.4 0.09 72);
|
||||
--success: oklch(0.38 0.1 172);
|
||||
--danger: oklch(0.42 0.15 22);
|
||||
--text-muted: oklch(50.72% 0.0139 248.4);
|
||||
--text-subtle: oklch(61.49% 0.0116 247.3);
|
||||
--surface-sunken: oklch(97.5% 0.005 235);
|
||||
--surface-overlay: oklch(100% 0.004 235);
|
||||
--hairline: oklch(21.5% 0.02 250 / 0.13);
|
||||
--hover-faint: oklch(95% 0.006 235);
|
||||
--brand-hover: oklch(52% 0.14 233);
|
||||
--brand-subtle: oklch(93.55% 0.0203 233.3);
|
||||
--brand-subtle-hover: oklch(89.55% 0.0203 233.3);
|
||||
--focus-ring: oklch(58% 0.14 233 / 0.6);
|
||||
--progress-start: oklch(71.82% 0.0927 233);
|
||||
--progress-end: oklch(0.58 0.14 233);
|
||||
--info-surface: oklch(94.5% 0.042 250);
|
||||
--warning-surface: oklch(95.5% 0.042 72);
|
||||
--success-surface: oklch(95% 0.042 172);
|
||||
--danger-surface: oklch(95% 0.036 22);
|
||||
--danger-surface-hover: oklch(91% 0.036 22);
|
||||
--control-bg: oklch(100% 0.004 235);
|
||||
--scrim: oklch(0% 0 0 / 0.6);
|
||||
--mega-menu-bg: oklch(97.2% 0.008 235);
|
||||
--mega-menu-scrim: oklch(22% 0.035 250 / 0.38);
|
||||
--app-shadow-sm: 0 1px 3px oklch(0 0 0 / 0.06), 0 1px 2px oklch(0 0 0 / 0.04);
|
||||
--app-shadow-md: 0 4px 16px oklch(0 0 0 / 0.08), 0 1px 3px oklch(0 0 0 / 0.04);
|
||||
--app-shadow-lg: 0 12px 32px oklch(0 0 0 / 0.12);
|
||||
--app-opacity-disabled: 0.4;
|
||||
--font-sans: "Lato", ui-sans-serif, system-ui, sans-serif;
|
||||
--font-mono: ui-monospace, "SF Mono", Menlo, Monaco, Consolas, monospace;
|
||||
--spacing: 0.25rem;
|
||||
--content-width-centered: 80rem;
|
||||
--radius-base: 0.5rem;
|
||||
}
|
||||
|
||||
[data-darkmode="true"] {
|
||||
--bg: oklch(0.13 0.018 264);
|
||||
--surface: oklch(0.21 0.02 264);
|
||||
--text: oklch(0.985 0.002 264);
|
||||
--brand: oklch(0.6 0.13 188.745);
|
||||
--on-brand: oklch(1 0 0);
|
||||
--link: oklch(0.6 0.13 188.745);
|
||||
--info: oklch(0.8 0.11 255);
|
||||
--warning: oklch(0.82 0.13 80);
|
||||
--success: oklch(0.72 0.13 158);
|
||||
--danger: oklch(0.7 0.16 22);
|
||||
--text-muted: oklch(66.01% 0.0081 264);
|
||||
--text-subtle: oklch(48.91% 0.0113 264);
|
||||
--surface-sunken: oklch(16.5% 0.02 264);
|
||||
--surface-overlay: oklch(23% 0.02 264);
|
||||
--hairline: oklch(98.5% 0.002 264 / 0.1);
|
||||
--hover-faint: oklch(98.5% 0.002 264 / 0.05);
|
||||
--brand-hover: oklch(55% 0.13 188.7);
|
||||
--brand-subtle: oklch(20.52% 0.0287 219.4);
|
||||
--brand-subtle-hover: oklch(24.52% 0.0287 219.4);
|
||||
--focus-ring: oklch(60% 0.13 188.7 / 0.6);
|
||||
--progress-start: oklch(44.78% 0.0865 193.2);
|
||||
--progress-end: oklch(0.6 0.13 188.745);
|
||||
--info-surface: oklch(32% 0.05 255);
|
||||
--warning-surface: oklch(33% 0.06 80);
|
||||
--success-surface: oklch(30% 0.05 158);
|
||||
--danger-surface: oklch(32% 0.08 22);
|
||||
--danger-surface-hover: oklch(36% 0.08 22);
|
||||
--control-bg: oklch(16.5% 0.02 264);
|
||||
--scrim: oklch(0% 0 0 / 0.6);
|
||||
--mega-menu-bg: oklch(16.5% 0.02 264);
|
||||
--mega-menu-scrim: oklch(0% 0 0 / 0.5);
|
||||
--app-shadow-sm: 0 4px 12px oklch(0 0 0 / 0.3);
|
||||
--app-shadow-md: 0 10px 28px oklch(0 0 0 / 0.42);
|
||||
--app-shadow-lg: 0 20px 48px oklch(0 0 0 / 0.55);
|
||||
--app-opacity-disabled: 0.3;
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-bg: var(--bg);
|
||||
--color-surface: var(--surface);
|
||||
--color-text: var(--text);
|
||||
--color-brand: var(--brand);
|
||||
--color-on-brand: var(--on-brand);
|
||||
--color-link: var(--link);
|
||||
--color-info: var(--info);
|
||||
--color-warning: var(--warning);
|
||||
--color-success: var(--success);
|
||||
--color-danger: var(--danger);
|
||||
--color-text-muted: var(--text-muted);
|
||||
--color-text-subtle: var(--text-subtle);
|
||||
--color-surface-sunken: var(--surface-sunken);
|
||||
--color-surface-overlay: var(--surface-overlay);
|
||||
--color-hairline: var(--hairline);
|
||||
--color-hover-faint: var(--hover-faint);
|
||||
--color-brand-hover: var(--brand-hover);
|
||||
--color-brand-subtle: var(--brand-subtle);
|
||||
--color-brand-subtle-hover: var(--brand-subtle-hover);
|
||||
--color-focus-ring: var(--focus-ring);
|
||||
--color-progress-start: var(--progress-start);
|
||||
--color-progress-end: var(--progress-end);
|
||||
--color-info-surface: var(--info-surface);
|
||||
--color-warning-surface: var(--warning-surface);
|
||||
--color-success-surface: var(--success-surface);
|
||||
--color-danger-surface: var(--danger-surface);
|
||||
--color-danger-surface-hover: var(--danger-surface-hover);
|
||||
--color-control-bg: var(--control-bg);
|
||||
--color-scrim: var(--scrim);
|
||||
--color-mega-menu-bg: var(--mega-menu-bg);
|
||||
--color-mega-menu-scrim: var(--mega-menu-scrim);
|
||||
|
||||
--shadow-sm: var(--app-shadow-sm);
|
||||
--shadow-md: var(--app-shadow-md);
|
||||
--shadow-lg: var(--app-shadow-md);
|
||||
--shadow-xl: var(--app-shadow-lg);
|
||||
--shadow-2xl: var(--app-shadow-lg);
|
||||
|
||||
--font-sans: var(--font-sans);
|
||||
--font-mono: var(--font-mono);
|
||||
--spacing: var(--spacing);
|
||||
--radius-sm: calc(var(--radius-base) * 0.25);
|
||||
--radius: calc(var(--radius-base) * 0.5);
|
||||
--radius-md: calc(var(--radius-base) * 0.75);
|
||||
--radius-lg: var(--radius-base);
|
||||
--radius-xl: calc(var(--radius-base) * 1.5);
|
||||
--radius-2xl: calc(var(--radius-base) * 2);
|
||||
--radius-3xl: calc(var(--radius-base) * 3);
|
||||
--radius-4xl: calc(var(--radius-base) * 4);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
@layer theme, base, components, utilities;
|
||||
@import "tailwindcss/theme.css" layer(theme);
|
||||
@import "tailwindcss/utilities.css" layer(utilities) source(none);
|
||||
@import "./_tokens.css";
|
||||
@import "@eamonxg/luci-theme-tokens/dist/aurora/tokens.css";
|
||||
|
||||
@import "./_reduced-motion.css";
|
||||
@import "./_base.css";
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
@custom-variant dark (&:where([data-darkmode=true], [data-darkmode=true] *));
|
||||
|
||||
@import "./_tokens.css";
|
||||
@import "@eamonxg/luci-theme-tokens/dist/aurora/tokens.css";
|
||||
@import "./_icons.css";
|
||||
|
||||
@import "./_base.css";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { resolveMode } from "@eamonxg/aurora-tokens";
|
||||
import { resolveMode } from "@eamonxg/luci-theme-tokens/aurora";
|
||||
|
||||
test("resolveMode(light) returns flat oklch for all tokens", () => {
|
||||
const out = resolveMode("light");
|
||||
|
||||
@@ -2,7 +2,7 @@ import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import Color from "colorjs.io";
|
||||
import { resolveMode } from "@eamonxg/aurora-tokens";
|
||||
import { resolveMode } from "@eamonxg/luci-theme-tokens/aurora";
|
||||
|
||||
// [L, C, H] in oklch; alpha separate.
|
||||
const lch = (s) => {
|
||||
|
||||
@@ -10,8 +10,7 @@ All dev commands run from `.dev/`:
|
||||
cd .dev/
|
||||
pnpm setup:router # One-shot dev setup: all .env values (router IP, dev host/port) → .env, installs SSH key on device ([ip] to run non-interactively; safe to re-run after a reflash)
|
||||
pnpm dev # Start Vite dev server (proxies to OpenWrt device)
|
||||
pnpm build # Clean + regenerate tokens + build production assets to htdocs/luci-static/
|
||||
pnpm gen:tokens # Regenerate src/media/_tokens.css from tokens/ (also runs as part of build)
|
||||
pnpm build # Clean + build production assets to htdocs/luci-static/
|
||||
pnpm test # Run tests/*.test.js (node:test)
|
||||
pnpm clean # Remove build output only
|
||||
```
|
||||
@@ -27,9 +26,9 @@ No linter CLI. Formatting uses Prettier with format-on-save (`.vscode/settings.j
|
||||
- `.dev/public/aurora/` → `htdocs/luci-static/aurora/` (copied as-is)
|
||||
- `ucode/template/themes/aurora/*.ut` — server-side templates, not processed by Vite
|
||||
|
||||
**CSS**: two Tailwind CSS v4 entry points in `.dev/src/media/` — `main.css` (admin UI; a pure import manifest over `_tokens.css`, `_base.css`, `_elements.css`, `_layout.css`, `components/*.css`, `_utilities.css`) and `login.css` (standalone login page; imports `_base.css`). Third-party compatibility patches are not bundled into `main.css`; each lives in `media/patches/<data-page>.css`, builds to its own `htdocs/luci-static/aurora/patches/<data-page>.css`, and is linked on demand by `header.ut`, which discovers installed patches at render time via `fs.lsdir()` and matches them on path-segment-boundary prefixes (dynamic subpages inherit their prefix's patch; third-party packages may drop their own patch into the directory). The same sweep also loads `patches/<data-page>.js` payloads as deferred scripts (theme-owned JS patches live in `.dev/src/resource/patches/`; `PATCH_ALIASES` in `vite.config.ts` duplicates one built payload under several page names) — see "On-Demand Third-Party Patches" in `.dev/docs/DEVELOPMENT.md`. All styling MUST use TailwindCSS v4 utility classes via `@apply` — no raw CSS properties (e.g. write `@apply text-sm font-semibold;` not `font-size: 14px; font-weight: 600;`). The one deliberate exception is `media/patches/*.css`, which is plain native CSS by design (smaller standalone output, and third-party patch authors need no Tailwind) — reach theme values through the `:root` custom properties (`var(--surface)`, `var(--radius-base)`, …). Use [CSS Nesting syntax](https://drafts.csswg.org/css-nesting/) for selectors. Theme colors defined as OKLCH custom properties in `_tokens.css` and mapped via `@theme inline`. Built CSS keeps Tailwind's native `@layer` structure (theme partials are unlayered, so they outrank layered utilities); the OKLCH requirement already gates browsers to ones with `@layer` support. See `.dev/docs/DEVELOPMENT.md` for the full CSS file layout.
|
||||
**CSS**: two Tailwind CSS v4 entry points in `.dev/src/media/` — `main.css` (admin UI; a pure import manifest over `@eamonxg/luci-theme-tokens/dist/aurora/tokens.css`, `_base.css`, `_elements.css`, `_layout.css`, `components/*.css`, `_utilities.css`) and `login.css` (standalone login page; imports `_base.css`). Third-party compatibility patches are not bundled into `main.css`; each lives in `media/patches/<data-page>.css`, builds to its own `htdocs/luci-static/aurora/patches/<data-page>.css`, and is linked on demand by `header.ut`, which discovers installed patches at render time via `fs.lsdir()` and matches them on path-segment-boundary prefixes (dynamic subpages inherit their prefix's patch; third-party packages may drop their own patch into the directory). The same sweep also loads `patches/<data-page>.js` payloads as deferred scripts (theme-owned JS patches live in `.dev/src/resource/patches/`; `PATCH_ALIASES` in `vite.config.ts` duplicates one built payload under several page names) — see "On-Demand Third-Party Patches" in `.dev/docs/DEVELOPMENT.md`. All styling MUST use TailwindCSS v4 utility classes via `@apply` — no raw CSS properties (e.g. write `@apply text-sm font-semibold;` not `font-size: 14px; font-weight: 600;`). The one deliberate exception is `media/patches/*.css`, which is plain native CSS by design (smaller standalone output, and third-party patch authors need no Tailwind) — reach theme values through the `:root` custom properties (`var(--surface)`, `var(--radius-base)`, …). Use [CSS Nesting syntax](https://drafts.csswg.org/css-nesting/) for selectors. Theme colors defined as OKLCH custom properties, imported from the published tokens package, and mapped via `@theme inline`. Built CSS keeps Tailwind's native `@layer` structure (theme partials are unlayered, so they outrank layered utilities); the OKLCH requirement already gates browsers to ones with `@layer` support. See `.dev/docs/DEVELOPMENT.md` for the full CSS file layout.
|
||||
|
||||
**Design tokens**: `_tokens.css` is GENERATED — do not hand-edit (see its header comment). Source of truth is `.dev/tokens/`: `defaults.js` holds the 10 editable input colors per mode (`bg`, `surface`, `text`, `brand`, `on_brand`, `link`, `info`, `warning`, `success`, `danger`); `spec.js` declares how every other token derives from those via `mix`/`shade`/`set`/`alpha`/`const` operators plus `FIXED` literals (shadows); `engine.js`/`resolve.js` do the OKLCH math and flatten everything to plain `oklch(...)` values. After changing inputs or derivations, run `pnpm gen:tokens` to rewrite `_tokens.css`, and `pnpm test` to check the color-math and token invariants.
|
||||
**Design tokens**: `_tokens.css` 已随 @eamonxg/luci-theme-tokens 上移——main.css/login.css 直接 @import 包内 dist/aurora/tokens.css。改配色/推导请到 luci-theme-tokens 仓库(aurora/defaults.js、aurora/spec.js),发版后在此 bump 依赖重新构建。
|
||||
|
||||
**JavaScript**: LuCI `E()` DOM API (not React/Vue). Minified but not bundled.
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ LUCI_TITLE:=Aurora Theme (A modern browser theme built with Vite and Tailwind CS
|
||||
LUCI_DEPENDS:=+luci-base
|
||||
|
||||
PKG_VERSION:=1.1.13
|
||||
PKG_RELEASE:=62
|
||||
PKG_RELEASE:=63
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
LUCI_MINIFY_CSS:=
|
||||
|
||||
Reference in new issue
Block a user