xlayer-ui
xlayer-ui
Base design-system layer for Nuxt 4. Provides two variable fonts, 60+ CSS custom properties (design tokens), utility classes, a useXUI() composable, and app.config.ts defaults. All other xlayers extend this layer — consuming layers inherit fonts, tokens, and utility classes without importing anything manually.
Installation
npm install xlayer-ui
// nuxt.config.ts
export default defineNuxtConfig({
extends: ["xlayer-ui"],
});
What This Layer Provides
- 2 variable fonts — Mona Sans (display/body) and Hubot Sans (mono), bundled and preloaded
- 60+ CSS custom properties — typography scale, spacing, content widths, radius, shadows, glow, glass morphism, z-index, animation durations/easings
- Utility classes —
x-font-*,x-text-*,x-glass,x-hover-lift,x-fade-up,x-focus-ring useXUI()composable — runtime access to design tokens fromapp.config.ts- Dark mode — automatic via
@media (prefers-color-scheme: dark)and.darkclass
Fonts
| Font | Usage | Weight Range | Stretch Range |
|---|---|---|---|
| Mona Sans | Display + body text | 200–900 | 75%–125% |
| Hubot Sans | Monospace / code | 200–900 | 75%–125% |
Both fonts use font-display: swap and are preloaded via <link rel="preload"> in the document <head>.
Design Tokens (CSS Custom Properties)
All tokens are defined on :root and can be overridden by consumer layers via app.config.ts.
Font Families
| Token | Default |
|---|---|
--x-font-display | Mona Sans, system fallbacks |
--x-font-body | Mona Sans, system fallbacks |
--x-font-mono | Hubot Sans, monospace fallbacks |
Typography Scale
| Scale | Size | Line Height | Tracking | Weight |
|---|---|---|---|---|
--x-text-display | 3.75rem | 1 | -0.025em | 800 |
--x-text-headline | 2.25rem | 1.1 | -0.02em | 700 |
--x-text-title | 1.5rem | 1.25 | -0.01em | 600 |
--x-text-body | 1rem | 1.625 | 0 | 400 |
--x-text-small | 0.875rem | 1.5 | 0 | 400 |
--x-text-caption | 0.75rem | 1.5 | 0.01em | 400 |
Each scale exposes three tokens: --x-text-{scale} (size), --x-text-{scale}-leading, --x-text-{scale}-tracking.
Spacing
| Token | Value |
|---|---|
--x-space-xs | 0.25rem |
--x-space-sm | 0.5rem |
--x-space-md | 1rem |
--x-space-lg | 1.5rem |
--x-space-xl | 2rem |
--x-space-2xl | 3rem |
--x-space-3xl | 4rem |
Content Widths
| Token | Value |
|---|---|
--x-content-sm | 640px |
--x-content-md | 768px |
--x-content-lg | 1024px |
--x-content-xl | 1280px |
Section Padding
| Token | Value |
|---|---|
--x-section-py | 4rem |
--x-section-py-lg | 6rem |
Border Radius
| Token | Value |
|---|---|
--x-radius-sm | 0.375rem |
--x-radius-md | 0.5rem |
--x-radius-lg | 0.75rem |
--x-radius-xl | 1rem |
--x-radius-full | 9999px |
Animation Durations
| Token | Value |
|---|---|
--x-duration-instant | 100ms |
--x-duration-fast | 150ms |
--x-duration-normal | 250ms |
--x-duration-slow | 400ms |
--x-duration-slower | 700ms |
Easing Curves
| Token | Value |
|---|---|
--x-ease-out | cubic-bezier(0.16, 1, 0.3, 1) |
--x-ease-in-out | cubic-bezier(0.65, 0, 0.35, 1) |
--x-ease-bounce | cubic-bezier(0.34, 1.56, 0.64, 1) |
Shadows & Glow
| Token | Description |
|---|---|
--x-shadow-sm | Subtle shadow |
--x-shadow-md | Medium shadow |
--x-shadow-lg | Large shadow |
--x-shadow-xl | Extra large shadow |
--x-glow-primary | Blue glow effect |
--x-glow-subtle | Muted glow effect |
Glass Morphism
| Token | Light | Dark |
|---|---|---|
--x-glass-bg | rgb(255 255 255 / 0.7) | rgb(15 23 42 / 0.7) |
--x-glass-border | rgb(255 255 255 / 0.2) | rgb(255 255 255 / 0.08) |
--x-glass-blur | 12px | 12px |
Z-Index Scale
| Token | Value |
|---|---|
--x-z-dropdown | 50 |
--x-z-sticky | 100 |
--x-z-overlay | 200 |
--x-z-modal | 300 |
--x-z-toast | 400 |
Utility Classes
| Class | Description |
|---|---|
.x-font-display | Apply display font family |
.x-font-body | Apply body font family |
.x-font-mono | Apply monospace font family |
.x-text-display | Display typography (3.75rem, weight 800) |
.x-text-headline | Headline typography (2.25rem, weight 700) |
.x-text-title | Title typography (1.5rem, weight 600) |
.x-text-body | Body typography (1rem) |
.x-text-small | Small text (0.875rem) |
.x-text-caption | Caption text (0.75rem) |
.x-glass | Glass morphism (blur + translucent background) |
.x-fade-up | Fade-up entrance animation |
.x-hover-lift | Lift on hover with shadow transition |
.x-focus-ring | Accessible focus ring on :focus-visible |
useXUI() Composable
Returns the xUI namespace from app.config.ts, providing runtime access to design token values in JavaScript.
<script setup>
const { fonts, typography, spacing, radius, duration } = useXUI()
</script>
Configuration (app.config.ts)
All token defaults can be overridden by consumer layers:
export default defineAppConfig({
xUI: {
fonts: {
display: "Inter",
body: "Inter",
mono: "JetBrains Mono",
},
spacing: {
md: "1.25rem",
},
},
});
Environment Variables
None required.
How It Works
nuxt.config.ts loads x-ui.css globally via css: [...] and preloads both variable fonts via <link rel="preload"> in the document <head> (using fileURLToPath for layer-safe path resolution). x-ui.css declares @font-face rules, defines all CSS custom properties on :root, provides dark mode overrides via @media (prefers-color-scheme: dark) and .dark, sets the base html font, and includes all utility classes. app.config.ts exposes the same token values in the xUI namespace so consumer layers can override them and composables can read them at runtime. useXUI() reads from useAppConfig().xUI.
Layer Files
| File | Purpose |
|---|---|
nuxt.config.ts | Loads CSS, preloads fonts |
assets/css/x-ui.css | Font faces, design tokens, utility classes |
app/app.config.ts | Default token values (overridable) |
app/composables/useXUI.js | Runtime access to design tokens |
app/types/x-ui.ts | TypeScript type definitions |
public/Mona Sans/ | Mona Sans variable font files |
public/Hubot Sans/ | Hubot Sans variable font files |
