@jdcpuwiz/homelab-ui 0.6.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -43
- package/dist/index.cjs +14 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +51 -24
- package/dist/index.d.ts +51 -24
- package/dist/index.js +13 -7
- package/dist/index.js.map +1 -1
- package/globals.css +56 -18
- package/package.json +3 -2
- package/starter/README.md +132 -0
- package/starter/next-layout.tsx +60 -0
- package/starter/vite-fonts.ts +41 -0
- package/tailwind-preset.cjs +21 -10
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# homelab-ui starter — the three-face font wiring (BuildPlan #57)
|
|
2
|
+
|
|
3
|
+
Copy-paste templates for loading the fleet's sanctioned faces and binding them
|
|
4
|
+
to `@jdcpuwiz/homelab-ui`'s CSS vars. **Loading is per-app** — a `next/font`
|
|
5
|
+
loader can't be re-exported from the package (Next's SWC plugin scans your own
|
|
6
|
+
source for literal `const Foo = Font({...})` calls), so each app self-hosts its
|
|
7
|
+
faces. The package only owns the `--hl-font-*` wiring.
|
|
8
|
+
|
|
9
|
+
## The standard (settled, Wiz 2026-07-24)
|
|
10
|
+
|
|
11
|
+
| Role | Face | Where |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Body / UI / headings / labels | **Poppins** (`--hl-font-sans`) | everything you read |
|
|
14
|
+
| Big display numbers (**≥ ~1.5rem**) | **Orbitron** (`--hl-font-display`) | stat-card heroes, clock, large KPIs |
|
|
15
|
+
| Small values + code/logs (**< 1.5rem**) | **JetBrains Mono** (`--hl-font-mono`) | table figures, inline values, version stamps, code |
|
|
16
|
+
|
|
17
|
+
The ~1.5rem line is the hard boundary — Orbitron is a display face and must
|
|
18
|
+
NEVER land in a dense small cell. If a number is small, it's JetBrains Mono.
|
|
19
|
+
|
|
20
|
+
Text is two colors only: flat **`#f0f1f4`** for everything you read (no opacity
|
|
21
|
+
ramp — hierarchy is size/weight), **`#ff9900`** for numeric values. Status pills
|
|
22
|
+
keep their solid semantic bg + white text.
|
|
23
|
+
|
|
24
|
+
The app-side variable names are a convention (`FONT_APP_VARIABLES` in the
|
|
25
|
+
package): `--font-poppins`, `--font-orbitron`, `--font-jetbrains-mono`. The
|
|
26
|
+
package's `globals.css` reads exactly these, so following the naming means zero
|
|
27
|
+
extra config.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Next apps (`next/font/google`)
|
|
32
|
+
|
|
33
|
+
See [`next-layout.tsx`](./next-layout.tsx). The shape:
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { Poppins, Orbitron, JetBrains_Mono } from "next/font/google";
|
|
37
|
+
import "@jdcpuwiz/homelab-ui/globals.css";
|
|
38
|
+
import "./globals.css"; // your own overrides, AFTER the package
|
|
39
|
+
|
|
40
|
+
const poppins = Poppins({
|
|
41
|
+
subsets: ["latin"],
|
|
42
|
+
weight: ["300", "400", "500", "600", "700", "800"],
|
|
43
|
+
display: "swap",
|
|
44
|
+
variable: "--font-poppins",
|
|
45
|
+
});
|
|
46
|
+
const orbitron = Orbitron({
|
|
47
|
+
subsets: ["latin"],
|
|
48
|
+
weight: ["400", "500", "600", "700", "800", "900"],
|
|
49
|
+
display: "swap",
|
|
50
|
+
variable: "--font-orbitron",
|
|
51
|
+
});
|
|
52
|
+
const jetbrainsMono = JetBrains_Mono({
|
|
53
|
+
subsets: ["latin"],
|
|
54
|
+
weight: ["400", "500", "600", "700"],
|
|
55
|
+
display: "swap",
|
|
56
|
+
variable: "--font-jetbrains-mono",
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
60
|
+
return (
|
|
61
|
+
<html
|
|
62
|
+
lang="en"
|
|
63
|
+
className={`dark ${poppins.variable} ${orbitron.variable} ${jetbrainsMono.variable}`}
|
|
64
|
+
>
|
|
65
|
+
<body className="antialiased">{children}</body>
|
|
66
|
+
</html>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
That's it. The three `.variable` classes put `--font-poppins` /
|
|
72
|
+
`--font-orbitron` / `--font-jetbrains-mono` on the tree; `globals.css` already
|
|
73
|
+
references them, so `font-sans` / `font-display` / `font-mono` resolve to the
|
|
74
|
+
real faces. Body text is Poppins with no extra style — the package sets
|
|
75
|
+
`font-family: var(--hl-font-sans)` on `body`.
|
|
76
|
+
|
|
77
|
+
**Use the faces by job:**
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
<h1 className="text-xl font-semibold text-[#f0f1f4]">Dashboard</h1> {/* Poppins */}
|
|
81
|
+
<span className="font-display text-4xl tabular-nums" style={{ color: "#ff9900" }}>42</span> {/* Orbitron */}
|
|
82
|
+
<span className="font-mono text-xs tabular-nums" style={{ color: "#ff9900" }}>v0.7.0</span> {/* JetBrains Mono */}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Vite apps (`@fontsource`)
|
|
88
|
+
|
|
89
|
+
wiz3dtools and timesheet. See [`vite-fonts.ts`](./vite-fonts.ts):
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
npm install @fontsource/poppins @fontsource/orbitron @fontsource/jetbrains-mono
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// src/main.tsx — import once, before your app
|
|
97
|
+
import "@fontsource/poppins/300.css";
|
|
98
|
+
import "@fontsource/poppins/400.css";
|
|
99
|
+
import "@fontsource/poppins/500.css";
|
|
100
|
+
import "@fontsource/poppins/600.css";
|
|
101
|
+
import "@fontsource/poppins/700.css";
|
|
102
|
+
import "@fontsource/poppins/800.css";
|
|
103
|
+
import "@fontsource/orbitron/400.css";
|
|
104
|
+
import "@fontsource/orbitron/500.css";
|
|
105
|
+
import "@fontsource/orbitron/600.css";
|
|
106
|
+
import "@fontsource/orbitron/700.css";
|
|
107
|
+
import "@fontsource/jetbrains-mono/400.css";
|
|
108
|
+
import "@fontsource/jetbrains-mono/500.css";
|
|
109
|
+
import "@fontsource/jetbrains-mono/600.css";
|
|
110
|
+
import "@jdcpuwiz/homelab-ui/globals.css";
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
`@fontsource` registers the plain family names (`Poppins`, `Orbitron`,
|
|
114
|
+
`JetBrains Mono`). The package's `--hl-font-*` vars fall back to those literal
|
|
115
|
+
names after the (unset) next/font vars, so no CSS variable wiring is needed —
|
|
116
|
+
importing the CSS is the whole setup.
|
|
117
|
+
|
|
118
|
+
**Kill the runtime `<link href="fonts.googleapis.com">`** if the app has one —
|
|
119
|
+
self-hosted only.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Verify after deploy
|
|
124
|
+
|
|
125
|
+
Open DevTools on the running app:
|
|
126
|
+
|
|
127
|
+
```js
|
|
128
|
+
getComputedStyle(document.body).fontFamily // → should name "Poppins"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
If it names Geist, system-ui, or nothing, the app is off-standard — the loader
|
|
132
|
+
didn't land or the CSS import is missing.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STARTER — Next.js root layout wiring the three sanctioned faces
|
|
3
|
+
* (BuildPlan #57). Copy into your app's `app/layout.tsx` and adjust the
|
|
4
|
+
* metadata / body content. Do NOT import this file from the package — a
|
|
5
|
+
* next/font loader can't be re-exported (Next scans your own source for the
|
|
6
|
+
* literal `const Foo = Font({...})` call), so the loaders must live in YOUR
|
|
7
|
+
* app source. This file is a template, shipped for copy-paste only.
|
|
8
|
+
*
|
|
9
|
+
* SANS Poppins — body / UI / headings / labels
|
|
10
|
+
* DISPLAY Orbitron — big numbers only (≥ ~1.5rem): stat heroes, clock
|
|
11
|
+
* MONO JetBrains Mono — small values, version stamps, code (< ~1.5rem)
|
|
12
|
+
*
|
|
13
|
+
* The `variable` names below MUST match the package convention
|
|
14
|
+
* (`FONT_APP_VARIABLES`): --font-poppins / --font-orbitron /
|
|
15
|
+
* --font-jetbrains-mono. `@jdcpuwiz/homelab-ui/globals.css` reads exactly
|
|
16
|
+
* these, so following the naming means zero extra config.
|
|
17
|
+
*/
|
|
18
|
+
import type { Metadata } from "next";
|
|
19
|
+
import { Poppins, Orbitron, JetBrains_Mono } from "next/font/google";
|
|
20
|
+
import "@jdcpuwiz/homelab-ui/globals.css";
|
|
21
|
+
import "./globals.css"; // optional: your own overrides, AFTER the package
|
|
22
|
+
|
|
23
|
+
const poppins = Poppins({
|
|
24
|
+
subsets: ["latin"],
|
|
25
|
+
weight: ["300", "400", "500", "600", "700", "800"],
|
|
26
|
+
display: "swap",
|
|
27
|
+
variable: "--font-poppins",
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const orbitron = Orbitron({
|
|
31
|
+
subsets: ["latin"],
|
|
32
|
+
weight: ["400", "500", "600", "700", "800", "900"],
|
|
33
|
+
display: "swap",
|
|
34
|
+
variable: "--font-orbitron",
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const jetbrainsMono = JetBrains_Mono({
|
|
38
|
+
subsets: ["latin"],
|
|
39
|
+
weight: ["400", "500", "600", "700"],
|
|
40
|
+
display: "swap",
|
|
41
|
+
variable: "--font-jetbrains-mono",
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
export const metadata: Metadata = { title: "My App" };
|
|
45
|
+
|
|
46
|
+
export default function RootLayout({
|
|
47
|
+
children,
|
|
48
|
+
}: Readonly<{ children: React.ReactNode }>) {
|
|
49
|
+
return (
|
|
50
|
+
<html
|
|
51
|
+
lang="en"
|
|
52
|
+
className={`dark ${poppins.variable} ${orbitron.variable} ${jetbrainsMono.variable}`}
|
|
53
|
+
>
|
|
54
|
+
{/* Body font is Poppins with no extra style — the package sets
|
|
55
|
+
`font-family: var(--hl-font-sans)` on `body`. Reach for the other
|
|
56
|
+
faces by job with the `font-display` / `font-mono` classes. */}
|
|
57
|
+
<body className="antialiased">{children}</body>
|
|
58
|
+
</html>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* STARTER — Vite app font wiring (BuildPlan #57). For the two Vite apps in
|
|
3
|
+
* the fleet (wiz3dtools, timesheet). Copy these imports into your app entry
|
|
4
|
+
* (`src/main.tsx` / `src/main.ts`), BEFORE your app mounts.
|
|
5
|
+
*
|
|
6
|
+
* First install the faces:
|
|
7
|
+
* npm install @fontsource/poppins @fontsource/orbitron @fontsource/jetbrains-mono
|
|
8
|
+
*
|
|
9
|
+
* @fontsource registers the plain family names (Poppins, Orbitron, JetBrains
|
|
10
|
+
* Mono). The package's `--hl-font-*` vars fall back to those literal names, so
|
|
11
|
+
* NO CSS-variable wiring is needed — importing these stylesheets + the
|
|
12
|
+
* package's globals.css is the whole setup.
|
|
13
|
+
*
|
|
14
|
+
* Then DELETE any runtime `<link href="https://fonts.googleapis.com/...">`
|
|
15
|
+
* from index.html — self-hosted only, no runtime Google Fonts.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
// Poppins — body / UI / headings / labels (weights 300–800)
|
|
19
|
+
import "@fontsource/poppins/300.css";
|
|
20
|
+
import "@fontsource/poppins/400.css";
|
|
21
|
+
import "@fontsource/poppins/500.css";
|
|
22
|
+
import "@fontsource/poppins/600.css";
|
|
23
|
+
import "@fontsource/poppins/700.css";
|
|
24
|
+
import "@fontsource/poppins/800.css";
|
|
25
|
+
|
|
26
|
+
// Orbitron — big display numbers only (≥ ~1.5rem)
|
|
27
|
+
import "@fontsource/orbitron/400.css";
|
|
28
|
+
import "@fontsource/orbitron/500.css";
|
|
29
|
+
import "@fontsource/orbitron/600.css";
|
|
30
|
+
import "@fontsource/orbitron/700.css";
|
|
31
|
+
|
|
32
|
+
// JetBrains Mono — small values, version stamps, code (< ~1.5rem)
|
|
33
|
+
import "@fontsource/jetbrains-mono/400.css";
|
|
34
|
+
import "@fontsource/jetbrains-mono/500.css";
|
|
35
|
+
import "@fontsource/jetbrains-mono/600.css";
|
|
36
|
+
import "@fontsource/jetbrains-mono/700.css";
|
|
37
|
+
|
|
38
|
+
// The package's token stylesheet — brings in --hl-font-* + the flat #f0f1f4
|
|
39
|
+
// foreground. Import AFTER the faces so the family names are already
|
|
40
|
+
// registered.
|
|
41
|
+
import "@jdcpuwiz/homelab-ui/globals.css";
|
package/tailwind-preset.cjs
CHANGED
|
@@ -82,21 +82,32 @@ module.exports = {
|
|
|
82
82
|
DEFAULT: "rgba(0,0,0,0.9)",
|
|
83
83
|
chip: "rgba(0,0,0,0.6)",
|
|
84
84
|
},
|
|
85
|
+
// Reading text is ONE flat shade (BP #57). The old /60·/40·/30
|
|
86
|
+
// opacity ramp is dead — hierarchy comes from size/weight, not a
|
|
87
|
+
// dimmer grey. `primary`/`secondary`/`tertiary` are kept as
|
|
88
|
+
// back-compat aliases but now ALL resolve to the one flat
|
|
89
|
+
// foreground, so a consumer still on `text-ink-secondary` renders
|
|
90
|
+
// the standard automatically. `disabled` stays a genuine dim — it
|
|
91
|
+
// marks a disabled affordance, not reading text.
|
|
85
92
|
ink: {
|
|
86
|
-
primary: "
|
|
87
|
-
secondary: "
|
|
88
|
-
tertiary: "
|
|
93
|
+
primary: "var(--hl-foreground)",
|
|
94
|
+
secondary: "var(--hl-foreground)",
|
|
95
|
+
tertiary: "var(--hl-foreground)",
|
|
89
96
|
disabled: "rgba(255,255,255,0.30)",
|
|
90
97
|
},
|
|
91
98
|
},
|
|
92
|
-
// Typography —
|
|
93
|
-
//
|
|
94
|
-
//
|
|
95
|
-
//
|
|
99
|
+
// Typography — three self-hosted faces by job (Wiz ruling 2026-07-24,
|
|
100
|
+
// BuildPlan #57): Poppins (sans), Orbitron (display / big numbers),
|
|
101
|
+
// JetBrains Mono (mono / small values + code). The `--hl-font-*` vars
|
|
102
|
+
// come from `@jdcpuwiz/homelab-ui/globals.css` and reference each app's
|
|
103
|
+
// own next/font loader; the literal face names after them keep these
|
|
104
|
+
// classes correct even if a consumer skips that stylesheet or loads via
|
|
105
|
+
// @fontsource. Each app self-hosts its faces — see the package README
|
|
106
|
+
// and starter/.
|
|
96
107
|
fontFamily: {
|
|
97
|
-
sans: ["var(--hl-font-sans)", "system-ui", "sans-serif"],
|
|
98
|
-
mono: ["var(--hl-font-mono)", "ui-monospace", "monospace"],
|
|
99
|
-
display: ["var(--hl-font-display)", "var(--hl-font-sans)", "system-ui", "sans-serif"],
|
|
108
|
+
sans: ["var(--hl-font-sans)", "Poppins", "system-ui", "sans-serif"],
|
|
109
|
+
mono: ["var(--hl-font-mono)", "JetBrains Mono", "ui-monospace", "monospace"],
|
|
110
|
+
display: ["var(--hl-font-display)", "Orbitron", "var(--hl-font-sans)", "system-ui", "sans-serif"],
|
|
100
111
|
},
|
|
101
112
|
fontSize: {
|
|
102
113
|
"2xs": ["10px", { lineHeight: "14px" }],
|