managarten/packages/shared-theme
Till JS 68c2442419
Some checks are pending
CD Mac Mini / Detect Changes (push) Waiting to run
CD Mac Mini / Deploy (push) Blocked by required conditions
CI / Detect Changes (push) Waiting to run
CI / Validate (push) Waiting to run
CI / Auth flow integration test (push) Waiting to run
CI / Build mana-auth (push) Blocked by required conditions
CI / Build mana-search (push) Blocked by required conditions
CI / Build mana-sync (push) Blocked by required conditions
CI / Build mana-notify (push) Blocked by required conditions
CI / Build mana-api-gateway (push) Blocked by required conditions
CI / Build mana-crawler (push) Blocked by required conditions
CI / Build mana-media (push) Blocked by required conditions
CI / Build mana-credits (push) Blocked by required conditions
CI / Build mana-web (push) Blocked by required conditions
CI / Build chat-backend (push) Blocked by required conditions
CI / Build chat-web (push) Blocked by required conditions
CI / Build todo-backend (push) Blocked by required conditions
CI / Build todo-web (push) Blocked by required conditions
CI / Build calendar-backend (push) Blocked by required conditions
CI / Build calendar-web (push) Blocked by required conditions
CI / Build clock-web (push) Blocked by required conditions
CI / Build contacts-backend (push) Blocked by required conditions
CI / Build contacts-web (push) Blocked by required conditions
CI / Build presi-web (push) Blocked by required conditions
CI / Build storage-backend (push) Blocked by required conditions
CI / Build storage-web (push) Blocked by required conditions
CI / Build telegram-stats-bot (push) Blocked by required conditions
CI / Build nutriphi-backend (push) Blocked by required conditions
CI / Build nutriphi-web (push) Blocked by required conditions
CI / Build skilltree-web (push) Blocked by required conditions
Docker Validate / Validate Dockerfiles (push) Waiting to run
Docker Validate / Build calendar-web (push) Blocked by required conditions
Docker Validate / Build todo-backend (push) Blocked by required conditions
Docker Validate / Build todo-web (push) Blocked by required conditions
Docker Validate / Build zitare-web (push) Blocked by required conditions
Docker Validate / Build mana-auth (push) Blocked by required conditions
Docker Validate / Build mana-sync (push) Blocked by required conditions
Docker Validate / Build mana-media (push) Blocked by required conditions
Mirror to Forgejo / Push to Forgejo (push) Waiting to run
feat(workbench): paper-grain polish — blend-mode, border, stone palette
Switch PageShell's per-theme paper overlay from a ::before +
mix-blend-mode + opacity stack to direct background-blend-mode on the
element itself. The old approach had invisibility issues in dark mode
and stacking-context quirks that made the grain disappear entirely.
background-blend-mode against background-color is the simpler, more
reliable primitive.

utils.ts auto-switches multiply → overlay in dark mode (dark × dark is
essentially invisible) while leaving other blend modes as-is. The
opacityLight/opacityDark knobs are gone from the paper config since
background-blend-mode has no opacity slot — tune via blendMode choice
instead.

Visual tuning pass:
- Card border bumped from 1px box-shadow ring to a real 2px border
  with background-clip: border-box so the paper texture reads
  continuously across the edge. Alpha 0.12 light / 0.28 dark (black).
- Drop shadow deepened (0 8px 24px + 0 3px 8px) for more card lift.
- Stone theme cooled toward real slate-blue: hue 200 → 212, saturation
  bumped ~10pts across the palette. Stone was reading as warm-neutral
  grey, now it's a proper cold blue.
- Texture remap: Lume → paper-004 (strongest grain, 480px tile for
  coarser fiber), Stone → cardboard-002 (linen), Lavender → paper-001
  (freed up after Stone claimed cardboard-002).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 23:38:30 +02:00
..
src feat(workbench): paper-grain polish — blend-mode, border, stone palette 2026-04-11 23:38:30 +02:00
package.json feat: rename ManaCore to Mana across entire codebase 2026-04-05 20:00:13 +02:00
README.md chore: complete ManaCore → Mana rename (docs, go modules, plists, images) 2026-04-07 12:26:10 +02:00
tsconfig.json style: auto-format codebase with Prettier 2025-11-27 18:33:16 +01:00

@mana/shared-theme

Unified theme system for all Mana web applications. Provides a consistent theming experience with HSL-based colors, multiple theme variants, and light/dark mode support.

Features

  • 4 Theme Variants: Lume (Gold), Nature (Green), Stone (Blue Gray), Ocean (Blue)
  • 3 Theme Modes: Light, Dark, System (auto-detect)
  • HSL-based Colors: 18 semantic color tokens for flexible theming
  • App-specific Primary Colors: Each app can override the primary color
  • Svelte 5 Runes: Modern reactive state management
  • localStorage Persistence: Theme preferences are saved per app
  • System Preference Detection: Automatically follows OS dark mode setting

Installation

pnpm add @mana/shared-theme

Quick Start

1. Create a theme store for your app

// src/lib/stores/theme.ts
import { createThemeStore } from '@mana/shared-theme';

export const theme = createThemeStore({
  appId: 'myapp',
  defaultVariant: 'lume',
  primaryColor: {
    light: '47 95% 58%',  // Gold
    dark: '47 95% 58%',
  },
});

2. Initialize in your layout

<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { theme } from '$lib/stores/theme';
  import { onMount } from 'svelte';

  onMount(() => {
    const cleanup = theme.initialize();
    return cleanup;
  });
</script>

{@render children()}

3. Import theme CSS

/* src/app.css */
@import '@mana/shared-tailwind/themes.css';

@tailwind base;
@tailwind components;
@tailwind utilities;

API Reference

createThemeStore(config)

Creates a theme store instance for your app.

Config Options

Option Type Default Description
appId string required Unique app identifier for localStorage
defaultMode 'light' | 'dark' | 'system' 'system' Default theme mode
defaultVariant ThemeVariant 'lume' Default theme variant
primaryColor { light: HSLValue; dark: HSLValue } - App-specific primary color override

Store Properties

Property Type Description
mode ThemeMode Current mode (light/dark/system)
variant ThemeVariant Current variant (lume/nature/stone/ocean)
effectiveMode 'light' | 'dark' Resolved mode (accounts for system preference)
isDark boolean Whether dark mode is active
variants ThemeVariant[] All available variants

Store Methods

Method Description
initialize() Initialize theme, returns cleanup function
setMode(mode) Set theme mode
setVariant(variant) Set theme variant
toggleMode() Toggle between light and dark
cycleMode() Cycle through light → dark → system

Theme Variants

Lume (Gold)

  • Primary: hsl(47 95% 58%) - #f8d62b
  • Warm, energetic feel
  • Best for: Creative apps, productivity tools

Nature (Green) 🌿

  • Primary: hsl(122 39% 49%) - #4CAF50
  • Calm, organic feel
  • Best for: Health apps, environmental themes

Stone (Blue Gray) 🪨

  • Primary: hsl(200 18% 46%) - #607D8B
  • Professional, neutral feel
  • Best for: Business apps, enterprise tools

Ocean (Blue) 🌊

  • Primary: hsl(199 98% 45%) - #039BE5
  • Fresh, trustworthy feel
  • Best for: Tech apps, communication tools

Color Tokens

The theme system provides 18 semantic color tokens:

/* Primary */
--color-primary
--color-primary-foreground

/* Secondary */
--color-secondary
--color-secondary-foreground

/* Backgrounds */
--color-background
--color-foreground

/* Surfaces */
--color-surface
--color-surface-hover
--color-surface-elevated

/* Muted */
--color-muted
--color-muted-foreground

/* Borders */
--color-border
--color-border-strong

/* Semantic */
--color-error
--color-success
--color-warning

/* Form */
--color-input
--color-ring

Usage with Tailwind

The @mana/shared-tailwind preset maps all CSS variables to Tailwind classes:

<!-- Backgrounds -->
<div class="bg-background">Page background</div>
<div class="bg-surface">Card surface</div>
<div class="bg-surface-hover">Hover state</div>

<!-- Text -->
<p class="text-foreground">Main text</p>
<p class="text-muted-foreground">Secondary text</p>

<!-- Primary -->
<button class="bg-primary text-primary-foreground">
  Primary Button
</button>

<!-- Borders -->
<div class="border border-border">Normal border</div>
<div class="border border-border-strong">Strong border</div>

<!-- Semantic -->
<span class="text-error">Error message</span>
<span class="text-success">Success message</span>

Pre-defined App Configs

import { APP_THEME_CONFIGS } from '@mana/shared-theme';

// Use pre-defined config
export const theme = createThemeStore(APP_THEME_CONFIGS.memoro);

// Available configs:
// - APP_THEME_CONFIGS.memoro (Gold)
// - APP_THEME_CONFIGS.mana (Indigo)
// - APP_THEME_CONFIGS.cards (Indigo)
// - APP_THEME_CONFIGS.maerchenzauber (Purple)

TypeScript Types

import type {
  ThemeMode,        // 'light' | 'dark' | 'system'
  ThemeVariant,     // 'lume' | 'nature' | 'stone' | 'ocean'
  EffectiveMode,    // 'light' | 'dark'
  ThemeState,       // Full theme state object
  ThemeColors,      // Color token definitions
  AppThemeConfig,   // Store configuration
  ThemeStore,       // Store interface
  HSLValue,         // HSL string format
} from '@mana/shared-theme';
  • @mana/shared-tailwind - Tailwind preset with theme CSS variables
  • @mana/shared-theme-ui - Theme toggle and selector components