11import type { RemovableRef } from '@vueuse/core'
22import { 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
1419const DEFAULT_SETTINGS : AppSettings = {
1520 relativeDates : false ,
1621 includeTypesInInstall : true ,
22+ accentColorId : null ,
1723}
1824
1925const STORAGE_KEY = 'npmx-settings'
@@ -45,3 +51,56 @@ 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+ }
83+
84+ /**
85+ * Applies accent color before hydration to prevent flash of default color.
86+ * Call this from app.vue to ensure accent color is applied on every page.
87+ */
88+ export function initAccentOnPrehydrate ( ) {
89+ // Callback is stringified by Nuxt - external variables won't be available.
90+ // Colors must be hardcoded since ACCENT_COLORS can't be referenced.
91+ onPrehydrate ( ( ) => {
92+ const colors : Record < AccentColorId , string > = {
93+ rose : '#e9aeba' ,
94+ amber : '#fbbf24' ,
95+ emerald : '#34d399' ,
96+ sky : '#38bdf8' ,
97+ violet : '#a78bfa' ,
98+ coral : '#fb7185' ,
99+ }
100+ const settings = JSON . parse ( localStorage . getItem ( 'npmx-settings' ) || '{}' )
101+ const color = settings . accentColorId ? colors [ settings . accentColorId as AccentColorId ] : null
102+ if ( color ) {
103+ document . documentElement . style . setProperty ( '--accent-color' , color )
104+ }
105+ } )
106+ }
0 commit comments