Skip to content

Commit d1336d5

Browse files
committed
integrate accent color selection into app settings
1 parent 65ed368 commit d1336d5

6 files changed

Lines changed: 58 additions & 61 deletions

File tree

app/components/AccentColorPicker.vue

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,34 @@
11
<script setup lang="ts">
2-
import { ACCENT_COLORS, useAccentColor, type ColorId } from '~/composables/useAccentColor'
2+
import { useAccentColor, type AppSettings } from '~/composables/useSettings'
33
4-
const { accentColorId, setAccentColor } = useAccentColor()
4+
const { accentColors, selectedAccentColor, setAccentColor } = useAccentColor()
55
66
const popoverRef = ref<HTMLElement | null>(null)
77
8-
function selectColor(id: ColorId) {
8+
function applyColor(id: AppSettings['accentColorId']) {
99
setAccentColor(id)
1010
popoverRef.value?.hidePopover()
1111
}
12-
13-
function clearColor() {
14-
setAccentColor(null)
15-
popoverRef.value?.hidePopover()
16-
}
1712
</script>
1813

1914
<template>
2015
<div class="flex items-center justify-between">
2116
<button
22-
v-for="color in ACCENT_COLORS"
17+
v-for="color in accentColors"
2318
:key="color.id"
2419
type="button"
2520
role="option"
26-
:aria-selected="accentColorId === color.id"
21+
:aria-selected="selectedAccentColor === color.id"
2722
:aria-label="color.name"
28-
class="size-6 rounded-full transition-transform duration-150 hover:scale-110 focus-ring"
29-
:class="{
30-
'ring-2 ring-fg ring-offset-2 ring-offset-bg-subtle': accentColorId === color.id,
31-
}"
23+
class="size-6 rounded-full transition-transform duration-150 hover:scale-110 focus-ring aria-selected:(ring-2 ring-fg ring-offset-2 ring-offset-bg-subtle)"
3224
:style="{ backgroundColor: color.value }"
33-
@click="selectColor(color.id)"
25+
@click="applyColor(color.id)"
3426
/>
3527
<button
3628
type="button"
3729
aria-label="Clear accent color"
3830
class="size-6 rounded-full transition-transform duration-150 hover:scale-110 focus-ring flex items-center justify-center bg-accent-fallback"
39-
@click="clearColor"
31+
@click="applyColor(null)"
4032
>
4133
<span class="i-carbon-error size-4 text-bg" />
4234
</button>

app/composables/useAccentColor.ts

Lines changed: 0 additions & 42 deletions
This file was deleted.

app/composables/useSettings.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import type { RemovableRef } from '@vueuse/core'
22
import { useLocalStorage } from '@vueuse/core'
3+
import { ACCENT_COLORS } from '#shared/utils/constants'
4+
5+
type AccentColorId = keyof typeof ACCENT_COLORS
36

47
/**
58
* Application settings stored in localStorage
@@ -9,11 +12,14 @@ export interface AppSettings {
912
relativeDates: boolean
1013
/** Include @types/* package in install command for packages without built-in types */
1114
includeTypesInInstall: boolean
15+
/** Accent color theme */
16+
accentColorId: AccentColorId | null
1217
}
1318

1419
const DEFAULT_SETTINGS: AppSettings = {
1520
relativeDates: false,
1621
includeTypesInInstall: true,
22+
accentColorId: null,
1723
}
1824

1925
const STORAGE_KEY = 'npmx-settings'
@@ -45,3 +51,32 @@ export function useRelativeDates() {
4551
const { settings } = useSettings()
4652
return computed(() => settings.value.relativeDates)
4753
}
54+
55+
/**
56+
* Composable for managing accent color.
57+
*/
58+
export function useAccentColor() {
59+
const { settings } = useSettings()
60+
61+
const accentColors = Object.entries(ACCENT_COLORS).map(([id, value]) => ({
62+
id: id as AccentColorId,
63+
name: id,
64+
value,
65+
}))
66+
67+
function setAccentColor(id: AccentColorId | null) {
68+
const color = id ? ACCENT_COLORS[id] : null
69+
if (color) {
70+
document.documentElement.style.setProperty('--accent-color', color)
71+
} else {
72+
document.documentElement.style.removeProperty('--accent-color')
73+
}
74+
settings.value.accentColorId = id
75+
}
76+
77+
return {
78+
accentColors,
79+
selectedAccentColor: computed(() => settings.value.accentColorId),
80+
setAccentColor,
81+
}
82+
}

nuxt.config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
import { ACCENT_COLORS } from './shared/utils/constants'
2+
3+
const accentInitScript = `(function(){var s=JSON.parse(localStorage.getItem('npmx-settings'));if(s&&s.accentColorId){document.documentElement.style.setProperty('--accent-color',${JSON.stringify(ACCENT_COLORS)}[s.accentColorId])}})()`
4+
15
export default defineNuxtConfig({
26
modules: [
37
function (_, nuxt) {
@@ -33,8 +37,7 @@ export default defineNuxtConfig({
3337
],
3438
script: [
3539
{
36-
innerHTML: `(function(){var c={rose:'#e9aeba',amber:'#fbbf24',emerald:'#34d399',sky:'#38bdf8',violet:'#a78bfa',coral:'#fb7185'};var s=localStorage.getItem('npmx-accent');document.documentElement.style.setProperty('--accent-color',s&&c[s]||'#666666')})()`,
37-
type: 'text/javascript',
40+
innerHTML: accentInitScript,
3841
},
3942
],
4043
},

shared/utils/constants.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,13 @@ export const NPM_MISSING_README_SENTINEL = 'ERROR: No README data found!'
1616
export const ERROR_JSR_FETCH_FAILED = 'Failed to fetch package from JSR registry.'
1717
export const ERROR_NPM_FETCH_FAILED = 'Failed to fetch package from npm registry.'
1818
export const ERROR_SUGGESTIONS_FETCH_FAILED = 'Failed to fetch suggestions.'
19+
20+
// Theming
21+
export const ACCENT_COLORS = {
22+
rose: '#e9aeba',
23+
amber: '#fbbf24',
24+
emerald: '#34d399',
25+
sky: '#38bdf8',
26+
violet: '#a78bfa',
27+
coral: '#fb7185',
28+
} as const

uno.config.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ export default defineConfig({
4949
accent: {
5050
DEFAULT: 'var(--accent-color, #666666)',
5151
fallback: '#666666',
52-
muted: '#e5e5e5',
5352
},
5453
// Syntax highlighting colors (inspired by GitHub Dark)
5554
syntax: {

0 commit comments

Comments
 (0)