Skip to main content

max / makeover

4.5 KB · 115 lines History Blame Raw
1 # makeover
2
3 Shared theme loading for the make-family apps. Parses theme metadata and color values from `.toml` files on disk, resolves them into intent-based tokens, and derives the rest perceptually (OKLab) with WCAG contrast checks.
4
5 The crate ships the theme set it loads, in `themes/`. Consumers get working themes from a clean checkout without depending on any sibling repo.
6
7 Used by MNW server, GoingsOn, Balanced Breakfast, audiofiles, and Alloy.
8
9 ## Usage
10
11 ```rust
12 use makeover::{load_theme, list_themes_from_dirs, bundled_themes_dir};
13 use std::path::PathBuf;
14
15 // Set up theme directories (later entries override earlier ones)
16 let bundled = bundled_themes_dir().expect("makeover ships themes/");
17 let custom = PathBuf::from("/path/to/user/custom-themes");
18 let dirs = vec![(bundled, false), (custom, true)];
19
20 // List available themes (sorted by name)
21 let themes = list_themes_from_dirs(&dirs);
22 for t in &themes {
23 println!("{} ({}, {})", t.name, t.id, t.variant);
24 }
25
26 // Load a specific theme by ID
27 let theme = load_theme(&dirs, "catppuccin-mocha").unwrap();
28 println!("Name: {}", theme.meta.name); // "Catppuccin Mocha"
29 println!("Variant: {}", theme.meta.variant); // "dark"
30 println!("BG: {}", theme.colors["background.primary"]); // "#181825"
31
32 // Build-from-source fallback: the themes this crate ships
33 if let Some(dir) = bundled_themes_dir() {
34 // dir = <makeover checkout>/themes
35 }
36 ```
37
38 ## Theme File Format
39
40 Theme files are TOML with four color sections. See `themes/` for the 31 bundled themes.
41
42 ```toml
43 # Attribution comment (optional, for credit)
44 # Based on Catppuccin by Catppuccin Org -- MIT License
45
46 [meta]
47 name = "Theme Name" # Display name (required)
48 variant = "dark" # "dark", "light", or "high-contrast" (default: "dark")
49
50 [background]
51 primary = "#181825" # Main background
52 secondary = "#11111b" # Sidebar / panel background (optional)
53 tertiary = "#313244" # Hover / selection background (optional)
54 surface = "#1e1e2e" # Card / elevated surface (optional)
55
56 [foreground]
57 primary = "#cdd6f4" # Main text
58 secondary = "#bac2de" # Secondary text (optional)
59 muted = "#9399b2" # Placeholder / disabled text (optional)
60
61 [accent]
62 red = "#f38ba8" # Error, destructive actions
63 green = "#a6e3a1" # Success, positive actions
64 blue = "#89b4fa" # Links, primary accent
65 yellow = "#f9e2af" # Warnings
66 purple = "#cba6f7" # Tags, special elements
67 cyan = "#89dceb" # Info, secondary accent
68
69 [border]
70 default = "#45475a" # Default border color
71 ```
72
73 ### Color Key Flattening
74
75 Colors are loaded into a flat `HashMap<String, String>` with dotted keys:
76
77 ```
78 "background.primary" -> "#181825"
79 "foreground.muted" -> "#9399b2"
80 "accent.blue" -> "#89b4fa"
81 "border.default" -> "#45475a"
82 ```
83
84 Apps map these keys to CSS variables or egui color values.
85
86 ### Theme ID
87
88 The theme ID is the filename without `.toml` (e.g., `catppuccin-mocha.toml` has ID `catppuccin-mocha`). IDs must contain only alphanumeric characters, hyphens, and underscores. Path traversal characters are rejected.
89
90 ## API
91
92 | Function | Description |
93 |----------|-------------|
94 | `list_themes_from_dirs(dirs)` | Scan directories for `.toml` files, return sorted `Vec<ThemeMeta>` |
95 | `load_theme(dirs, id)` | Load a theme by ID, returning `ThemeColors` (metadata + color map) |
96 | `find_theme_path(dirs, id)` | Find the file path for a theme ID (highest-priority directory wins) |
97 | `parse_meta(id, table, is_custom)` | Parse `[meta]` from a TOML table into `ThemeMeta` |
98 | `extract_colors(table)` | Flatten color sections into a `HashMap<String, String>` |
99 | `validate_theme_id(id)` | Check that an ID contains only safe characters |
100 | `bundled_themes_dir()` | The `themes/` directory this crate ships, for build-from-source fallback |
101
102 ## Directory Priority
103
104 `list_themes_from_dirs` and `load_theme` accept a list of `(PathBuf, bool)` pairs. Later directories override earlier ones by theme ID. The `bool` marks whether the directory contains user-custom themes (`is_custom` on `ThemeMeta`).
105
106 Typical setup for a Tauri app:
107 1. Bundled themes, packaged by the app or from `bundled_themes_dir()` (is_custom = false)
108 2. User themes from an app data directory (is_custom = true)
109
110 ## License
111
112 MIT.
113
114 The themes in `themes/` are adapted from third-party color schemes (Catppuccin, Dracula, Nord, gruvbox, Tokyo Night, Rose Pine, and others), each MIT-licensed. Every adapted file carries an attribution comment naming its source and author; keep those in place when editing or redistributing.
115