Skip to content

Commit

Permalink
Update adds default dynamic light/dark theme support.
Browse files Browse the repository at this point in the history
  • Loading branch information
kristoferjoseph committed Oct 25, 2023
1 parent c8fb2dc commit 0472f04
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 45 deletions.
13 changes: 6 additions & 7 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,14 @@
"mono": "Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace"
},
"theme": {
"light": "#f8f9fa",
"dark": "#343a40",
"accent": "#007aff",
"primary": "#007aff"
"light": {
"accent": "#0075db",
"error": "#d60606",
"back": "#fefefe",
"fore": "#222222"
}
},
"color": {
"error": "#ff3b2f",
"warn": "#ffcc02",
"success": "#35c759"
},
"properties": {
},
Expand Down
109 changes: 71 additions & 38 deletions theme-color.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,47 @@ import hextohsl from './hex-to-hsl.mjs'

export default function themeColor({ config }) {
const { color={}, theme={} } = config
const defaultLight = '#f8f9fa'
const defaultDark = '#343a40'
const lightParts = hextohsl(theme['light'] || defaultLight);
const defaultAccent = '#007aff'
const defaultAccentContrast = defaultDark
theme['accent'] = theme['accent'] || defaultAccent
theme['accent-contrast'] = theme['accent-contrast'] || defaultAccentContrast

const defaultAccent = '#0075db'
const defaultError = '#d60606'
const defaultLight = '#fefefe'
const defaultDark = '#222222'
const light = color.light || defaultLight
const dark = color.dark || defaultDark
const lightParts = hextohsl(light);
const lightTheme = theme?.light || {}
const darkTheme = theme?.dark || {}
const lightAccent = lightTheme?.accent || defaultAccent
const lightError = lightTheme?.error || defaultError
const accentParts = hextohsl(lightAccent)
const errorParts = hextohsl(lightError)
const darkThemeColors = Object.keys(darkTheme).map(name => {
if ( name === 'accent' ||
name === 'back' ||
name === 'fore') {
return
}
return `--${name}: ${darkTheme[name]}`;
}).join('\n')
const lightThemeColors = Object.keys(lightTheme).map(name => {
if ( name === 'accent' ||
name === 'error' ||
name === 'back' ||
name === 'fore') {
return
}
return `--${name}: ${lightTheme[name]}`;
}).join('\n')
const themeColors = Object.keys(theme).map(name => {
if ((name === 'light' && typeof theme[name] === 'object') ||
(name === 'dark' && typeof theme[name] === 'object')) {
return
}
else {
return colorSteps(hextohsl(theme[name]), name)
}
}).join('\n')
const colors = Object.keys(color).map(name => ` --${name}: ${color[name]};`).join('\n')
const grayScale = colorSteps({ h: lightParts.h, s: 0, l: 50}, 'gray')

function colorSteps(color, name) {
const hue = color.h
Expand All @@ -33,25 +66,24 @@ export default function themeColor({ config }) {
return /*css*/`
/*** Theme Colors ***/
:root {
${Object.keys(theme).map(name => {
if (name === 'light' ||
name === 'dark' ||
name === 'accent' ||
name === 'accent-contrast') {
return ` --${name}: ${theme[name]};`
}
else {
return colorSteps(hextohsl(theme[name]), name)
}
}).join('\n')}
${Object.keys(color).map(name => ` --${name}: ${color[name]};`).join('\n')}
--back: var(--light, ${defaultLight});
--fore: var(--dark, ${defaultDark});
${colorSteps({ h: lightParts.h, s: 0, l: 50}, 'grey')}
--focus-size: 1px;
--focus-offset: 1px;
accent-color: var(--accent);
--accent-h: ${accentParts.h};
--accent-s: ${accentParts.s}%;
--accent-l: ${accentParts.l}%;
--accent: hsl(var(--accent-h), var(--accent-s), var(--accent-l));
--light: ${light};
--dark: ${dark};
--fore: var(--dark, currentColor);
--back: var(--light);
--error-h: ${errorParts.h};
--error-s: ${errorParts.s}%;
--error-l: ${errorParts.l}%;
--error: hsl(var(--error-h), var(--error-s), var(--error-l));
${lightThemeColors}
${themeColors}
${colors}
${grayScale}
--focus-l: 30%;
accent-color: var(--accent, royalblue);
color-scheme: light dark;
}
Expand All @@ -60,24 +92,25 @@ ${Object.keys(color).map(name => ` --${name}: ${color[name]};`).join('\n')}
}
:is(a, button, input, textarea, summary):focus-visible {
outline: max(var(--focus-size), 1px) solid var(--accent);
outline-offset: var(--focus-offset);
}
:is(a, button, input, textarea, summary):not(:focus):not(:placeholder-shown):invalid {
outline: max(var(--focus-size), 1px) solid var(--error);
outline-offset: var(--focus-offset);
outline: max(var(--focus-size, 1px), 1px) solid var(--accent, royalblue);
outline-offset: var(--focus-offset, 0);
box-shadow: 0 0 0 max(var(--focus-size, 3px), 3px) hsl(var(--accent-h), var(--accent-s), calc(var(--accent-l) + var(--focus-l)))
;
}
:is(a, button, input, textarea, summary):not(:focus):not(:placeholder-shown):invalid {
outline: max(var(--focus-size), 1px) solid var(--error);
outline-offset: var(--focus-offset);
outline: max(var(--focus-size, 1px), 1px) solid var(--error, crimson);
outline-offset: var(--focus-offset, 0);
box-shadow: 0 0 0 3px hsl(var(--error-h), var(--error-s), calc(var(--error-l) + var(--focus-l)));
}
@media (prefers-color-scheme: dark) {
:root {
--back: var(--dark, ${defaultDark});
--fore: var(--light, ${defaultLight});
--accent-l: 62%;
--focus-l: -30%;
--fore: var(--light);
--back: var(--dark);
${darkThemeColors}
}
}
`
Expand Down

0 comments on commit 0472f04

Please sign in to comment.