Skip to content

Commit 315d143

Browse files
authored
Merge pull request #6 from semanticdata/feat/new-color-system
2 parents bd76df6 + b302bd9 commit 315d143

9 files changed

Lines changed: 412 additions & 26 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ packages/sidebar/script.js
66
packages/sidebar/icon.svg
77
packages/sidebar/preload.js
88
packages/sidebar/export.js
9+
packages/sidebar/colors.js
910
packages/newtab/styles.css
1011
packages/newtab/script.js
1112
packages/newtab/icon.svg
1213
packages/newtab/preload.js
1314
packages/newtab/export.js
15+
packages/newtab/colors.js
1416
web-ext-artifacts

packages/newtab/newtab.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@
5656
<div class="col-right" style="position: relative;">
5757
<!-- Settings Menu Popover -->
5858
<div id="settings-menu" class="settings-menu" hidden>
59+
<div class="setting-row">
60+
<label for="theme-selector">Theme</label>
61+
</div>
62+
<select id="theme-selector">
63+
<option value="default">Default</option>
64+
<option value="catppuccin">Catppuccin</option>
65+
<option value="nord">Nord</option>
66+
<option value="solarized">Solarized</option>
67+
<option value="dracula">Dracula</option>
68+
</select>
69+
5970
<div class="setting-row">
6071
<label for="font-slider">Font Size</label>
6172
<span id="font-display">18px</span>
@@ -99,6 +110,7 @@
99110
</div>
100111
</footer>
101112

113+
<script type="text/javascript" src="colors.js"></script>
102114
<script type="text/javascript" src="script.js"></script>
103115
<script type="text/javascript" src="export.js"></script>
104116
</body>

packages/sidebar/panel.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@
5656
<div class="col-right" style="position: relative;">
5757
<!-- Settings Menu Popover -->
5858
<div id="settings-menu" class="settings-menu" hidden>
59+
<div class="setting-row">
60+
<label for="theme-selector">Theme</label>
61+
</div>
62+
<select id="theme-selector">
63+
<option value="default">Default</option>
64+
<option value="catppuccin">Catppuccin</option>
65+
<option value="nord">Nord</option>
66+
<option value="solarized">Solarized</option>
67+
<option value="dracula">Dracula</option>
68+
</select>
69+
5970
<div class="setting-row">
6071
<label for="font-slider">Font Size</label>
6172
<span id="font-display">18px</span>
@@ -99,6 +110,7 @@
99110
</div>
100111
</footer>
101112

113+
<script type="text/javascript" src="colors.js"></script>
102114
<script type="text/javascript" src="script.js"></script>
103115
<script type="text/javascript" src="export.js"></script>
104116
</body>

scripts/copy-shared.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const path = require('path');
66
// Configuration
77
const sharedDir = path.join(__dirname, '../shared');
88
const packagesDir = path.join(__dirname, '../packages');
9-
const sharedFiles = ['script.js', 'styles.css', 'icon.svg', 'preload.js', 'export.js'];
9+
const sharedFiles = ['script.js', 'styles.css', 'icon.svg', 'preload.js', 'export.js', 'colors.js'];
1010
const targets = ['newtab', 'sidebar'];
1111

1212
// Colors for console output

scripts/watch-shared.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ const { build } = require('./copy-shared.js');
88

99
// Configuration
1010
const sharedDir = path.join(__dirname, '../shared');
11-
const sharedFiles = ['script.js', 'styles.css', 'icon.svg', 'preload.js', 'export.js'];
11+
const sharedFiles = ['script.js', 'styles.css', 'icon.svg', 'preload.js', 'export.js', 'colors.js'];
1212

1313
// Colors for console output
1414
const colors = {

shared/colors.js

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,291 @@
1+
// Color Management System for NoteKeeper
2+
const colorManager = {
3+
// Default themes (original)
4+
defaults: {
5+
light: {
6+
name: 'Default Light',
7+
bg: '#ffffff',
8+
fg: '#1a1a1a',
9+
accent: '#27ae60',
10+
border: '#e0e0e0',
11+
subtle: '#666',
12+
shadow: 'rgba(0, 0, 0, 0.1)'
13+
},
14+
dark: {
15+
name: 'Default Dark',
16+
bg: '#111111',
17+
fg: '#f0f0f0',
18+
accent: '#27ae60',
19+
border: '#333333',
20+
subtle: '#888',
21+
shadow: 'rgba(0, 0, 0, 0.5)'
22+
}
23+
},
24+
25+
// Catppuccin
26+
catppuccin: {
27+
latte: {
28+
name: 'Catppuccin Latte',
29+
bg: '#eff1f5',
30+
fg: '#4c4f69',
31+
accent: '#1e66f5',
32+
border: '#dce0e8',
33+
subtle: '#8c8fa1',
34+
shadow: 'rgba(220, 224, 232, 0.5)'
35+
},
36+
frappe: {
37+
name: 'Catppuccin Frappé',
38+
bg: '#303446',
39+
fg: '#c6d0f5',
40+
accent: '#8caaee',
41+
border: '#51576d',
42+
subtle: '#838ba7',
43+
shadow: 'rgba(30, 32, 48, 0.5)'
44+
}
45+
},
46+
47+
// Nord theme
48+
nord: {
49+
light: {
50+
name: 'Nord Light',
51+
bg: '#eceff4',
52+
fg: '#4c566a',
53+
accent: '#5e81ac',
54+
border: '#d8dee9',
55+
subtle: '#81a1c1',
56+
shadow: 'rgba(216, 222, 233, 0.5)'
57+
},
58+
dark: {
59+
name: 'Nord Dark',
60+
bg: '#2e3440',
61+
fg: '#d8dee9',
62+
accent: '#88c0d0',
63+
border: '#4c566a',
64+
subtle: '#81a1c1',
65+
shadow: 'rgba(46, 52, 64, 0.5)'
66+
}
67+
},
68+
69+
// Solarized
70+
solarized: {
71+
light: {
72+
name: 'Solarized Light',
73+
bg: '#fdf6e3',
74+
fg: '#657b83',
75+
accent: '#268bd2',
76+
border: '#93a1a1',
77+
subtle: '#586e75',
78+
shadow: 'rgba(147, 161, 161, 0.5)'
79+
},
80+
dark: {
81+
name: 'Solarized Dark',
82+
bg: '#002b36',
83+
fg: '#839496',
84+
accent: '#2aa198',
85+
border: '#073642',
86+
subtle: '#586e75',
87+
shadow: 'rgba(7, 54, 66, 0.5)'
88+
}
89+
},
90+
91+
// Dracula
92+
dracula: {
93+
dark: {
94+
name: 'Dracula',
95+
bg: '#282A36',
96+
fg: '#F8F8F2',
97+
accent: '#FF79C6',
98+
border: '#44475A',
99+
subtle: '#6272A4',
100+
shadow: 'rgba(40, 42, 54, 0.5)'
101+
},
102+
light: {
103+
name: 'Alucard',
104+
bg: '#FFFBEB',
105+
fg: '#1F1F1F',
106+
accent: '#A3144D',
107+
border: '#CFCFDE',
108+
subtle: '#6C664B',
109+
shadow: 'rgba(255, 251, 235, 0.5)'
110+
}
111+
},
112+
113+
// Initialize color system
114+
init() {
115+
const savedTheme = localStorage.getItem('notekeeper-theme') || 'default';
116+
this.applyTheme(savedTheme);
117+
},
118+
119+
// Apply theme colors
120+
applyTheme(themeName) {
121+
let theme;
122+
let isDarkMode = false;
123+
124+
// Handle theme selection
125+
if (themeName === 'default') {
126+
// Use original light/dark toggle behavior
127+
const currentMode = localStorage.getItem('theme') || 'light';
128+
theme = this.defaults[currentMode];
129+
isDarkMode = currentMode === 'dark';
130+
} else if (themeName === 'catppuccin') {
131+
// Use Catppuccin behavior
132+
const currentVariant = localStorage.getItem('catppuccin-variant') || 'latte';
133+
theme = this.catppuccin[currentVariant];
134+
isDarkMode = currentVariant === 'frappe';
135+
} else if (themeName === 'nord') {
136+
// Use Nord behavior
137+
const currentVariant = localStorage.getItem('nord-variant') || 'light';
138+
theme = this.nord[currentVariant];
139+
isDarkMode = currentVariant === 'dark';
140+
} else if (themeName === 'solarized') {
141+
// Use Solarized behavior
142+
const currentVariant = localStorage.getItem('solarized-variant') || 'light';
143+
theme = this.solarized[currentVariant];
144+
isDarkMode = currentVariant === 'dark';
145+
} else if (themeName === 'dracula') {
146+
// Use Dracula behavior
147+
const currentVariant = localStorage.getItem('dracula-variant') || 'dark';
148+
theme = this.dracula[currentVariant];
149+
isDarkMode = currentVariant === 'dark';
150+
} else {
151+
// Direct theme selection
152+
if (themeName.startsWith('catppuccin-')) {
153+
const catppuccinVariant = themeName.replace('catppuccin-', '');
154+
theme = this.catppuccin[catppuccinVariant];
155+
isDarkMode = catppuccinVariant === 'frappe';
156+
} else if (themeName.startsWith('nord-')) {
157+
const nordVariant = themeName.replace('nord-', '');
158+
theme = this.nord[nordVariant];
159+
isDarkMode = nordVariant === 'dark';
160+
} else if (themeName.startsWith('solarized-')) {
161+
const solarizedVariant = themeName.replace('solarized-', '');
162+
theme = this.solarized[solarizedVariant];
163+
isDarkMode = solarizedVariant === 'dark';
164+
} else if (themeName.startsWith('dracula-')) {
165+
const draculaVariant = themeName.replace('dracula-', '');
166+
theme = this.dracula[draculaVariant];
167+
isDarkMode = draculaVariant === 'dark';
168+
} else {
169+
theme = this.defaults[themeName];
170+
isDarkMode = themeName === 'dark';
171+
}
172+
}
173+
174+
if (!theme) return;
175+
176+
// Apply colors to CSS custom properties
177+
Object.entries(theme).forEach(([key, value]) => {
178+
if (key !== 'name') {
179+
document.documentElement.style.setProperty(`--user-${key}`, value);
180+
}
181+
});
182+
183+
// Update theme attribute for existing CSS
184+
document.documentElement.setAttribute('data-theme', isDarkMode ? 'dark' : 'light');
185+
186+
// Save preference
187+
localStorage.setItem('notekeeper-theme', themeName);
188+
189+
// Update theme toggle aria-label
190+
const themeToggle = document.getElementById('theme-toggle');
191+
if (themeToggle) {
192+
const isCurrentDark = isDarkMode;
193+
themeToggle.setAttribute('aria-label', `Switch to ${isCurrentDark ? 'light' : 'dark'} theme`);
194+
}
195+
},
196+
197+
// Toggle between themes
198+
toggleTheme() {
199+
const currentTheme = localStorage.getItem('notekeeper-theme') || 'default';
200+
201+
if (currentTheme === 'default') {
202+
// Toggle light/dark in default mode
203+
const currentMode = localStorage.getItem('theme') || 'light';
204+
const nextMode = currentMode === 'light' ? 'dark' : 'light';
205+
localStorage.setItem('theme', nextMode);
206+
this.applyTheme('default');
207+
} else if (currentTheme === 'catppuccin') {
208+
// Toggle latte/frappe in catppuccin mode
209+
const currentVariant = localStorage.getItem('catppuccin-variant') || 'latte';
210+
const nextVariant = currentVariant === 'latte' ? 'frappe' : 'latte';
211+
localStorage.setItem('catppuccin-variant', nextVariant);
212+
this.applyTheme('catppuccin');
213+
} else if (currentTheme === 'nord') {
214+
// Toggle light/dark in nord mode
215+
const currentVariant = localStorage.getItem('nord-variant') || 'light';
216+
const nextVariant = currentVariant === 'light' ? 'dark' : 'light';
217+
localStorage.setItem('nord-variant', nextVariant);
218+
this.applyTheme('nord');
219+
} else if (currentTheme === 'solarized') {
220+
// Toggle light/dark in solarized mode
221+
const currentVariant = localStorage.getItem('solarized-variant') || 'light';
222+
const nextVariant = currentVariant === 'light' ? 'dark' : 'light';
223+
localStorage.setItem('solarized-variant', nextVariant);
224+
this.applyTheme('solarized');
225+
} else if (currentTheme === 'dracula') {
226+
// Toggle light/dark in dracula mode
227+
const currentVariant = localStorage.getItem('dracula-variant') || 'dark';
228+
const nextVariant = currentVariant === 'light' ? 'dark' : 'light';
229+
localStorage.setItem('dracula-variant', nextVariant);
230+
this.applyTheme('dracula');
231+
} else {
232+
// Direct theme selection - toggle between default themes
233+
const nextTheme = currentTheme === 'light' ? 'dark' : 'light';
234+
localStorage.setItem('notekeeper-theme', nextTheme);
235+
localStorage.setItem('theme', nextTheme);
236+
this.applyTheme('default');
237+
}
238+
},
239+
240+
// Get next theme for aria-label (informational only)
241+
getNextTheme(currentTheme) {
242+
if (currentTheme === 'default') {
243+
const currentMode = localStorage.getItem('theme') || 'light';
244+
return currentMode === 'light' ? 'dark' : 'light';
245+
} else if (currentTheme === 'catppuccin') {
246+
const currentVariant = localStorage.getItem('catppuccin-variant') || 'latte';
247+
return currentVariant === 'latte' ? 'frappe' : 'latte';
248+
} else if (currentTheme === 'nord') {
249+
const currentVariant = localStorage.getItem('nord-variant') || 'light';
250+
return currentVariant === 'light' ? 'dark' : 'light';
251+
} else if (currentTheme === 'solarized') {
252+
const currentVariant = localStorage.getItem('solarized-variant') || 'light';
253+
return currentVariant === 'light' ? 'dark' : 'light';
254+
} else if (currentTheme === 'dracula') {
255+
const currentVariant = localStorage.getItem('dracula-variant') || 'dark';
256+
return currentVariant === 'light' ? 'dark' : 'light';
257+
}
258+
return currentTheme === 'light' ? 'dark' : 'light';
259+
},
260+
261+
// Get current theme
262+
getCurrentTheme() {
263+
return localStorage.getItem('notekeeper-theme') || 'default';
264+
}
265+
};
266+
267+
// Initialize theme selector dropdown value
268+
const initThemeSelector = () => {
269+
const currentTheme = colorManager.getCurrentTheme();
270+
const themeSelector = document.getElementById('theme-selector');
271+
if (themeSelector) {
272+
themeSelector.value = currentTheme;
273+
}
274+
};
275+
276+
// Initialize on DOM load
277+
document.addEventListener('DOMContentLoaded', () => {
278+
// Initialize default variants for new themes if not set
279+
if (!localStorage.getItem('nord-variant')) {
280+
localStorage.setItem('nord-variant', 'light');
281+
}
282+
if (!localStorage.getItem('solarized-variant')) {
283+
localStorage.setItem('solarized-variant', 'light');
284+
}
285+
if (!localStorage.getItem('dracula-variant')) {
286+
localStorage.setItem('dracula-variant', 'dark');
287+
}
288+
289+
colorManager.init();
290+
initThemeSelector();
291+
});

0 commit comments

Comments
 (0)