feat(themes): colour families with light/dark, follow system, corners, frames, accent
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m30s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m30s
- Fjord (new), Polarized Hell and Suri Hell complete the families Klassik, Fjord, Terrakotta, Polarized, Suri - settings: family table, follow-system, corners, button frames and an own accent colour (per device); compact quick picker in the user menus - code colours in index.css are fallbacks only chore(release): v0.14.0 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2c9b4762fc
commit
3f0e596356
16 files changed
+949
-58
No files matched your search
@@ -1,5 +1,19 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { setActiveTheme, initThemeOnBoot, customThemeOption, getActiveTheme } from '../theme';
|
||||
import {
|
||||
setActiveTheme,
|
||||
initThemeOnBoot,
|
||||
customThemeOption,
|
||||
getActiveTheme,
|
||||
themeCounterpart,
|
||||
setCornerStyle,
|
||||
getCornerStyle,
|
||||
THEME_FAMILIES,
|
||||
AVAILABLE_THEMES,
|
||||
setFollowSystem,
|
||||
resolveTheme,
|
||||
setAccentColor,
|
||||
setButtonBorders,
|
||||
} from '../theme';
|
||||
|
||||
const lightCss = `:root[data-theme="papier"] { --bg-app: #fafafa; --accent-primary: #15803d; --radius-card: 8px; }`;
|
||||
|
||||
@@ -83,3 +97,62 @@ describe('built-in themes', () => {
|
||||
expect(document.documentElement.classList.contains('dark')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('theme families and corners', () => {
|
||||
beforeEach(() => localStorage.clear());
|
||||
|
||||
it('pairs every family with an existing light and dark theme', () => {
|
||||
for (const f of THEME_FAMILIES) {
|
||||
expect(AVAILABLE_THEMES.find((t) => t.id === f.light)?.mode).toBe('light');
|
||||
expect(AVAILABLE_THEMES.find((t) => t.id === f.dark)?.mode).toBe('dark');
|
||||
}
|
||||
expect(themeCounterpart('fjord')).toBe('fjord-night');
|
||||
expect(themeCounterpart('polarized')).toBe('polarized-light');
|
||||
expect(themeCounterpart('custom:x')).toBeNull();
|
||||
});
|
||||
|
||||
it('forces round or square corners and keeps the choice', () => {
|
||||
setCornerStyle('square');
|
||||
expect(document.documentElement.getAttribute('data-corners')).toBe('square');
|
||||
expect(getCornerStyle()).toBe('square');
|
||||
setCornerStyle('theme');
|
||||
expect(document.documentElement.hasAttribute('data-corners')).toBe(false);
|
||||
expect(getCornerStyle()).toBe('theme');
|
||||
});
|
||||
});
|
||||
|
||||
describe('follow system, accent and button frames', () => {
|
||||
beforeEach(() => localStorage.clear());
|
||||
|
||||
it('picks the family variant that matches the system when following it', () => {
|
||||
const original = window.matchMedia;
|
||||
window.matchMedia = ((q: string) => ({ matches: q.includes('dark'), media: q, addEventListener() {}, removeEventListener() {} })) as unknown as typeof window.matchMedia;
|
||||
try {
|
||||
expect(resolveTheme('fjord')).toBe('fjord');
|
||||
setFollowSystem(true);
|
||||
expect(resolveTheme('fjord')).toBe('fjord-night');
|
||||
expect(resolveTheme('suri-light')).toBe('suri');
|
||||
expect(resolveTheme('custom:x')).toBe('custom:x');
|
||||
} finally {
|
||||
window.matchMedia = original;
|
||||
}
|
||||
});
|
||||
|
||||
it('sets the accent variables and removes them again', () => {
|
||||
setActiveTheme('dark');
|
||||
setAccentColor('#c2410c');
|
||||
const style = document.documentElement.style;
|
||||
expect(style.getPropertyValue('--accent-primary')).toBe('#c2410c');
|
||||
expect(style.getPropertyValue('--text-on-accent')).toBe('#ffffff');
|
||||
expect(style.getPropertyValue('--accent-dim')).toBe('rgba(194, 65, 12, 0.16)');
|
||||
setAccentColor(null);
|
||||
expect(style.getPropertyValue('--accent-primary')).toBe('');
|
||||
});
|
||||
|
||||
it('switches button frames off and on', () => {
|
||||
setButtonBorders('off');
|
||||
expect(document.documentElement.getAttribute('data-button-borders')).toBe('off');
|
||||
setButtonBorders('on');
|
||||
expect(document.documentElement.hasAttribute('data-button-borders')).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user