mirror of
https://github.com/purrgrammer/grimoire.git
synced 2026-04-13 17:07:27 +02:00
* feat: Add reusable theme system with Plan 9 proof of concept Implement a comprehensive theme system that: - Defines typed Theme interface with colors, syntax highlighting, scrollbar, and gradient variables - Creates ThemeProvider with React context for runtime theme switching - Persists theme selection to localStorage - Includes 3 built-in themes: dark (default), light, and plan9 Theme structure supports: - Core UI colors (background, foreground, primary, secondary, accent, etc.) - Status colors (success, warning, info) replacing hardcoded Tailwind colors - Syntax highlighting variables for code blocks - Diff highlighting colors (inserted, deleted, meta) - Scrollbar styling variables - Gradient colors for branding Technical changes: - Update CSS to use new theme variables throughout - Update prism-theme.css to use syntax variables instead of hardcoded values - Remove chart colors (unused) - Add success/warning/info to tailwind.config.js - Wire up ThemeProvider in main.tsx For Nostr publishing (future): - d tag: "grimoire-theme" - name tag: theme display name * feat: Add theme selector to user menu, remove configurable border radius - Remove border radius from theme configuration (borders are always square) - Add theme selector dropdown to user menu (available to all users) - Theme selector shows active theme indicator - Theme selection persists via localStorage * fix: Improve theme contrast and persistence - Fix theme persistence: properly check localStorage before using default - Plan9: make blue subtler (reduce saturation), darken gradient colors for better contrast on pale yellow background - Light theme: improve contrast with darker muted foreground and borders - Change theme selector from flat list to dropdown submenu * fix: Replace Plan9 yellow accent with purple, add zap/live theme colors - Replace Plan9's bright yellow accent with purple (good contrast on pale yellow) - Add zap and live colors to theme system (used by ZapReceiptRenderer, StatusBadge) - Make light theme gradient orange darker for better contrast - Update ZapReceiptRenderer to use theme zap color instead of hardcoded yellow-500 - Update StatusBadge to use theme live color instead of hardcoded red-600 - Add CSS variables and Tailwind utilities for zap/live colors * fix: Make gradient orange darker, theme status colors - Make gradient orange darker in light and plan9 themes for better contrast - Make req viewer status colors themeable: - loading/connecting → text-warning - live/receiving → text-success - error/failed → text-destructive - eose → text-info - Update relay status icons to use theme colors - Update tests to expect theme color classes * fix: Use themeable zap color for active user names - Replace hardcoded text-orange-400 with text-zap in UserName component - Replace hardcoded text-orange-400 with text-zap in SpellRenderer ($me placeholder) - Now uses dark amber/gold with proper contrast on light/plan9 themes * feat: Add highlight theme color for active user display Add dedicated 'highlight' color to theme system for displaying the logged-in user's name, replacing the use of 'zap' color which felt semantically incorrect. The highlight color is optimized for contrast on each theme's background. - Add highlight to ThemeColors interface and apply.ts - Add --highlight CSS variable to index.css (light and dark) - Add highlight to tailwind.config.js - Configure appropriate highlight values for dark, light, and plan9 themes - Update UserName.tsx to use text-highlight for active account - Update SpellRenderer.tsx MePlaceholder to use text-highlight * fix: Restore original orange-400 highlight color for dark theme Update dark theme highlight to match original text-orange-400 color (27 96% 61%) for backward compatibility with existing appearance. --------- Co-authored-by: Claude <noreply@anthropic.com>
145 lines
2.6 KiB
CSS
145 lines
2.6 KiB
CSS
/* Grimoire Prism Theme - Uses CSS theme variables */
|
|
|
|
code[class*="language-"],
|
|
pre[class*="language-"] {
|
|
color: hsl(var(--foreground));
|
|
background: none;
|
|
text-shadow: none;
|
|
font-family: "Oxygen Mono", monospace;
|
|
font-size: 0.75rem;
|
|
line-height: 1.5;
|
|
white-space: pre;
|
|
word-spacing: normal;
|
|
word-break: normal;
|
|
tab-size: 4;
|
|
hyphens: none;
|
|
}
|
|
|
|
/* Diff-specific tokens */
|
|
|
|
/* Deleted lines (red) - subtle background, no strikethrough */
|
|
.token.deleted {
|
|
color: hsl(var(--diff-deleted));
|
|
background: hsl(var(--diff-deleted-bg));
|
|
display: block;
|
|
margin: 0 -1rem;
|
|
padding: 0 1rem;
|
|
}
|
|
|
|
/* Added lines (green) - subtle background */
|
|
.token.inserted {
|
|
color: hsl(var(--diff-inserted));
|
|
background: hsl(var(--diff-inserted-bg));
|
|
display: block;
|
|
margin: 0 -1rem;
|
|
padding: 0 1rem;
|
|
}
|
|
|
|
/* Hunk headers (@@ -1,5 +1,7 @@) - cyan/blue */
|
|
.token.diff.coord,
|
|
.token.coord {
|
|
color: hsl(var(--diff-meta));
|
|
background: hsl(var(--diff-meta-bg));
|
|
display: block;
|
|
margin: 0 -1rem;
|
|
padding: 0 1rem;
|
|
font-weight: 600;
|
|
font-style: normal;
|
|
}
|
|
|
|
/* File headers (diff --git, ---, +++) */
|
|
.token.diff.range,
|
|
.token.prefix.unchanged,
|
|
.language-diff .token.unchanged {
|
|
color: hsl(var(--muted-foreground));
|
|
font-weight: normal;
|
|
}
|
|
|
|
/* Prefix characters (+/-) */
|
|
.language-diff .token.prefix {
|
|
font-weight: 700;
|
|
opacity: 0.7;
|
|
}
|
|
|
|
/* General syntax tokens */
|
|
.token.comment,
|
|
.token.prolog,
|
|
.token.doctype,
|
|
.token.cdata {
|
|
color: hsl(var(--syntax-comment));
|
|
}
|
|
|
|
.token.punctuation {
|
|
color: hsl(var(--syntax-punctuation));
|
|
}
|
|
|
|
.token.property,
|
|
.token.tag,
|
|
.token.boolean,
|
|
.token.number,
|
|
.token.constant,
|
|
.token.symbol {
|
|
color: hsl(var(--syntax-property));
|
|
}
|
|
|
|
.token.selector,
|
|
.token.attr-name,
|
|
.token.string,
|
|
.token.char,
|
|
.token.builtin {
|
|
color: hsl(var(--syntax-string));
|
|
}
|
|
|
|
.token.operator,
|
|
.token.entity,
|
|
.token.url,
|
|
.language-css .token.string,
|
|
.style .token.string {
|
|
color: hsl(var(--syntax-operator));
|
|
}
|
|
|
|
.token.atrule,
|
|
.token.attr-value,
|
|
.token.keyword {
|
|
color: hsl(var(--syntax-keyword));
|
|
}
|
|
|
|
.token.function,
|
|
.token.class-name {
|
|
color: hsl(var(--syntax-function));
|
|
font-weight: bold;
|
|
}
|
|
|
|
.token.regex,
|
|
.token.important,
|
|
.token.variable {
|
|
color: hsl(var(--syntax-variable));
|
|
}
|
|
|
|
.token.important,
|
|
.token.bold {
|
|
font-weight: bold;
|
|
}
|
|
|
|
.token.italic {
|
|
font-style: italic;
|
|
}
|
|
|
|
.token.entity {
|
|
cursor: help;
|
|
}
|
|
|
|
/* Line highlighting */
|
|
pre[class*="language-"] > code {
|
|
display: block;
|
|
}
|
|
|
|
/* Optional: Line numbers support */
|
|
.line-numbers .line-numbers-rows {
|
|
border-right: 1px solid hsl(var(--border));
|
|
}
|
|
|
|
.line-numbers-rows > span:before {
|
|
color: hsl(var(--muted-foreground));
|
|
}
|