Skip to content

Commit 2d5f73e

Browse files
authored
feat: Themes (#22)
* feat: shift+enter while editing adds a new line to the node instead of creating a node, shift+enter adds a new line, allowing for multi-line nodes. * feat: themes and their manager! this adds a simple theme manager (ctrl+t) and two themees (default and dark) that the user can select between. It will remmeber your choice between restarts of the application and apply across all your outlines. AI Usage: This update is a weird one. We utilized kiro to build the design plan and then claude code to generate the bulk of the functionality, before hand-editing. I like the process of kiro to generate a more detailed plan that I can go in and tweak before handing it off to claude - it feels more "full featured" than just asking claude to go crazy. * chore: update tauri
1 parent 7ba7439 commit 2d5f73e

16 files changed

Lines changed: 1583 additions & 742 deletions

File tree

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# Design Document
2+
3+
## Overview
4+
5+
The dynamic theming system will extract color values from the existing style.css file and create a modular theme architecture. The system will use CSS custom properties (CSS variables) to enable runtime theme switching without page reloads. The architecture will consist of theme definition files, a theme manager service, and a user interface for theme selection.
6+
7+
## Architecture
8+
9+
### Theme Structure
10+
- **Theme Files**: CSS files containing CSS custom property definitions for each theme
11+
- **Base Variables**: Core CSS custom properties that all themes implement
12+
- **Theme Manager**: TypeScript service that handles theme loading and switching
13+
- **Theme UI**: Interface component for theme selection and preview
14+
15+
### File Organization
16+
```
17+
public/assets/themes/
18+
├── base-variables.css # Base CSS custom properties structure
19+
├── default.css # Default theme extracted from current colors
20+
└── [future-themes].css # Additional themes (e.g., dark.css, light.css)
21+
22+
src/lib/
23+
└── theme-manager.ts # Theme management service
24+
25+
src/modals/
26+
└── theme-selector.ts # Theme selection modal
27+
```
28+
29+
## Components and Interfaces
30+
31+
### Theme CSS Structure
32+
Each theme CSS file will define the same set of CSS custom properties:
33+
```css
34+
/* Example: default.css */
35+
:root {
36+
/* Background colors */
37+
--color-body-background: #eee;
38+
--color-outliner-background: #fff;
39+
--color-modal-background: #fff;
40+
41+
/* Text colors */
42+
--color-primary-text: #222;
43+
--color-secondary-text: #aaa;
44+
--color-link: #098bd9;
45+
--color-link-visited: #b26be4;
46+
47+
/* Interactive states */
48+
--color-cursor-background: #000;
49+
--color-cursor-text: #fff;
50+
--color-selected-background: #000;
51+
--color-selected-text: #fff;
52+
53+
/* UI elements */
54+
--color-border: #ddd;
55+
--color-button-background: #eee;
56+
--color-button-hover: #f4f4f4;
57+
58+
/* Specialized elements */
59+
--color-date-header-background: #547883;
60+
--color-table-header-background: #666;
61+
--color-strikethrough: #808080;
62+
--color-code-background: #eee;
63+
}
64+
```
65+
66+
### Theme Metadata Structure
67+
Theme metadata will be embedded in CSS file headers using comments:
68+
```css
69+
/*
70+
name: Default Theme
71+
author: Original Author
72+
version: 1.0.0
73+
description: The original color scheme extracted from style.css
74+
*/
75+
76+
:root {
77+
/* CSS custom properties... */
78+
}
79+
```
80+
81+
### Theme Metadata Interface
82+
```typescript
83+
interface ThemeInfo {
84+
name: string;
85+
author?: string;
86+
version?: string;
87+
description?: string;
88+
filename: string;
89+
}
90+
```
91+
92+
### Theme Manager Service
93+
```typescript
94+
class ThemeManager {
95+
private currentTheme: string;
96+
private availableThemes: ThemeInfo[];
97+
private currentThemeLink: HTMLLinkElement | null;
98+
99+
async loadTheme(themeName: string): Promise<void>
100+
async switchTheme(themeName: string): Promise<void>
101+
getCurrentTheme(): string
102+
getAvailableThemes(): ThemeInfo[]
103+
private loadThemeCSS(filename: string): Promise<void>
104+
private removeCurrentTheme(): void
105+
private parseThemeMetadata(cssContent: string): ThemeInfo
106+
private discoverAvailableThemes(): Promise<ThemeInfo[]>
107+
private persistThemePreference(themeName: string): void
108+
private loadThemePreference(): string
109+
}
110+
```
111+
112+
## Data Models
113+
114+
### Theme Storage
115+
- **Location**: `public/assets/themes/` directory
116+
- **Format**: CSS files with CSS custom property definitions
117+
- **Naming**: `{theme-name}.css` (e.g., `default.css`, `dark.css`)
118+
119+
### Theme Loading Mechanism
120+
- **Dynamic Loading**: Themes loaded by injecting `<link>` elements into document head
121+
- **Theme Switching**: Remove previous theme link and add new theme link
122+
- **CSS Cascade**: Theme CSS custom properties override base styles automatically
123+
- **Metadata Parsing**: Fetch theme CSS files to extract metadata from header comments
124+
- **Theme Discovery**: Scan themes directory for available CSS files and parse their metadata
125+
126+
### Theme Persistence
127+
- **Storage**: localStorage
128+
- **Key**: `outliner-theme-preference`
129+
- **Value**: Theme name string
130+
131+
## Error Handling
132+
133+
### Theme Loading Failures
134+
- **Fallback**: Always fall back to default theme if requested theme fails to load
135+
- **CSS Load Detection**: Monitor link element load/error events
136+
- **User Feedback**: Display error messages for failed theme operations
137+
138+
### Missing Theme Files
139+
- **Detection**: Handle CSS file 404 errors gracefully
140+
- **Recovery**: Provide list of available themes if requested theme is missing
141+
- **Logging**: Log theme-related errors for debugging
142+
143+
### CSS Variable Support
144+
- **Browser Compatibility**: Detect CSS custom property support
145+
- **Graceful Degradation**: Fall back to static CSS if variables not supported
146+
- **Progressive Enhancement**: Enhance experience for modern browsers
147+
148+
## Testing Strategy
149+
150+
### Unit Tests
151+
- **Theme Manager**: Test theme loading, switching, and persistence
152+
- **CSS Loading**: Test dynamic CSS file loading and error handling
153+
- **Theme Detection**: Test available theme discovery
154+
155+
### Integration Tests
156+
- **Theme Switching**: Test complete theme switching workflow
157+
- **UI Integration**: Test theme selector modal functionality
158+
- **Persistence**: Test theme preference saving and loading
159+
160+
### Visual Testing
161+
- **Theme Consistency**: Verify all UI elements update correctly with theme changes
162+
- **Color Contrast**: Ensure accessibility standards are met for all themes
163+
- **Interactive States**: Test hover, selected, and cursor states across themes
164+
165+
### Browser Compatibility
166+
- **CSS Variables**: Test in browsers with and without CSS custom property support
167+
- **Theme Persistence**: Test localStorage functionality across browsers
168+
- **Performance**: Measure theme switching performance impact
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Requirements Document
2+
3+
## Introduction
4+
5+
This feature will extract color values from the existing style.css file and create a separate theme system that allows for dynamic stylesheet swapping. The system will enable users to switch between different color themes (starting with a "default" theme) without requiring application restarts or page reloads.
6+
7+
## Requirements
8+
9+
### Requirement 1
10+
11+
**User Story:** As a user, I want to be able to switch between different color themes, so that I can customize the visual appearance of the application to my preferences.
12+
13+
#### Acceptance Criteria
14+
15+
1. WHEN the application loads THEN the system SHALL apply the default theme automatically
16+
2. WHEN a user selects a different theme THEN the system SHALL update the visual appearance immediately without requiring a page reload
17+
3. WHEN a theme is changed THEN the system SHALL persist the user's theme preference for future sessions
18+
19+
### Requirement 2
20+
21+
**User Story:** As a developer, I want color values to be centralized in theme files, so that I can easily create and maintain different color schemes.
22+
23+
#### Acceptance Criteria
24+
25+
1. WHEN creating a new theme THEN all color values SHALL be defined in a single theme file
26+
2. WHEN the main stylesheet is loaded THEN it SHALL reference theme variables instead of hardcoded color values
27+
3. WHEN a color needs to be updated THEN it SHALL only require changes in the theme file, not the main stylesheet
28+
29+
### Requirement 3
30+
31+
**User Story:** As a user, I want the theme system to preserve all existing visual functionality, so that changing themes doesn't break the application's appearance or usability.
32+
33+
#### Acceptance Criteria
34+
35+
1. WHEN any theme is applied THEN all existing visual elements SHALL maintain their intended styling and layout
36+
2. WHEN switching themes THEN interactive states (hover, selected, cursor) SHALL continue to work correctly
37+
3. WHEN a theme is applied THEN all color-dependent features (search results, node states, dates) SHALL remain visually distinct and functional
38+
39+
### Requirement 4
40+
41+
**User Story:** As a user, I want a theme selection interface, so that I can easily choose and preview different themes.
42+
43+
#### Acceptance Criteria
44+
45+
1. WHEN accessing theme settings THEN the system SHALL provide a user interface for theme selection
46+
2. WHEN previewing a theme THEN the system SHALL show the theme name and allow immediate application
47+
3. WHEN a theme is selected THEN the interface SHALL provide visual feedback confirming the selection
48+
49+
### Requirement 5
50+
51+
**User Story:** As a developer, I want the theme system to be extensible, so that new themes can be added easily in the future.
52+
53+
#### Acceptance Criteria
54+
55+
1. WHEN adding a new theme THEN it SHALL only require creating a new theme file following the established structure
56+
2. WHEN a new theme file is added THEN the system SHALL automatically detect and make it available for selection
57+
3. WHEN defining theme variables THEN the system SHALL use a consistent naming convention that maps clearly to CSS properties
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Implementation Plan
2+
3+
- [x] 1. Extract colors from existing style.css and create base theme structure
4+
- Analyze current style.css to identify all color values used throughout the application
5+
- Create themes directory structure at `public/assets/themes/`
6+
- Create default.css theme file with metadata header and CSS custom properties extracted from style.css
7+
- _Requirements: 2.1, 2.2_
8+
9+
- [x] 2. Modify main stylesheet to use CSS custom properties
10+
- Update style.css to replace hardcoded color values with CSS custom property references
11+
- Ensure all color-dependent styles use the new CSS variables
12+
- Test that visual appearance remains identical with the new variable-based approach
13+
- _Requirements: 2.2, 3.1, 3.2_
14+
15+
- [x] 3. Implement theme manager service
16+
- Create ThemeManager class in `src/lib/theme-manager.ts`
17+
- Implement theme metadata parsing from CSS file headers
18+
- Implement dynamic CSS loading and switching functionality
19+
- Add theme preference persistence using localStorage
20+
- _Requirements: 1.1, 1.3, 2.1_
21+
22+
- [ ] 4. Add theme discovery and initialization
23+
- Implement theme discovery mechanism to scan available theme files
24+
- Add theme manager initialization to main client.ts
25+
- Implement automatic default theme loading on application startup
26+
- Add error handling for theme loading failures with fallback to default
27+
- _Requirements: 1.1, 5.2_
28+
29+
- [ ] 5. Create theme selection modal interface
30+
- Create theme selector modal component in `src/modals/theme-selector.ts`
31+
- Implement theme list display with metadata (name, author, version)
32+
- Add theme preview and selection functionality
33+
- Integrate theme selector with existing modal system
34+
- _Requirements: 4.1, 4.2, 4.3_
35+
36+
- [ ] 6. Add keyboard shortcut for theme selection
37+
- Add new keyboard shortcut definition for opening theme selector
38+
- Integrate theme selector shortcut with existing keyboard shortcut system
39+
- Update help modal to include theme selection shortcut
40+
- _Requirements: 4.1_
41+
42+
- [ ] 7. Implement theme switching functionality
43+
- Connect theme selector UI to theme manager service
44+
- Implement immediate theme application without page reload
45+
- Add visual feedback for successful theme changes
46+
- Ensure theme persistence works correctly across sessions
47+
- _Requirements: 1.2, 1.3, 4.3_
48+
49+
- [ ] 8. Add comprehensive error handling and validation
50+
- Implement CSS file loading error detection and handling
51+
- Add validation for theme metadata format
52+
- Implement graceful fallback to default theme on errors
53+
- Add user-friendly error messages for theme-related issues
54+
- _Requirements: 3.1, 3.2, 3.3_
55+
56+
- [ ] 9. Create unit tests for theme system
57+
- Write tests for ThemeManager class methods
58+
- Test theme metadata parsing functionality
59+
- Test theme switching and persistence mechanisms
60+
- Test error handling and fallback scenarios
61+
- _Requirements: 2.1, 1.2, 1.3_
62+
63+
- [ ] 10. Verify theme system integration and functionality
64+
- Test complete theme switching workflow end-to-end
65+
- Verify all UI elements update correctly with theme changes
66+
- Test theme persistence across browser sessions
67+
- Ensure all interactive states (hover, selected, cursor) work with new themes
68+
- _Requirements: 3.1, 3.2, 3.3, 1.2_

0 commit comments

Comments
 (0)