Skip to content

Commit 3c84708

Browse files
authored
feat: light theme (#172)
1 parent 1da4592 commit 3c84708

12 files changed

Lines changed: 606 additions & 478 deletions

File tree

app/app.vue

Lines changed: 0 additions & 424 deletions
Large diffs are not rendered by default.

app/assets/main.css

Lines changed: 470 additions & 0 deletions
Large diffs are not rendered by default.

app/components/PackageWeeklyDownloadStats.vue

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,22 +56,45 @@ const config = computed(() => ({
5656
style: {
5757
backgroundColor: 'transparent',
5858
animation: { show: false },
59-
area: { color: '#6A6A6A', useGradient: false, opacity: 10 },
60-
dataLabel: { offsetX: -10, fontSize: 28, bold: false, color: '#FAFAFA' },
59+
area: {
60+
color: 'oklch(0.5243 0 0)', // css variable doesn't seem to work here
61+
useGradient: false,
62+
opacity: 10,
63+
},
64+
dataLabel: {
65+
offsetX: -10,
66+
fontSize: 28,
67+
bold: false,
68+
color: 'var(--fg)',
69+
},
6170
line: {
62-
color: '#6A6A6A',
71+
color: 'var(--fg-subtle)',
6372
pulse: {
6473
show: true,
65-
loop: true,
74+
loop: true, // runs only once if false
6675
radius: 2,
67-
color: '#8A8A8A',
76+
color: 'var(--fg-muted)',
6877
easing: 'ease-in-out',
69-
trail: { show: true, length: 6 },
78+
trail: {
79+
show: true,
80+
length: 6,
81+
},
7082
},
7183
},
72-
plot: { radius: 6, stroke: '#FAFAFA' },
73-
title: { text: lastDatapoint.value, fontSize: 12, color: '#8A8A8A', bold: false },
74-
verticalIndicator: { strokeDasharray: 0, color: '#FAFAFA' },
84+
plot: {
85+
radius: 6,
86+
stroke: 'var(--fg)',
87+
},
88+
title: {
89+
text: lastDatapoint.value,
90+
fontSize: 12,
91+
color: 'var(--fg)',
92+
bold: false,
93+
},
94+
verticalIndicator: {
95+
strokeDasharray: 0,
96+
color: 'var(--fg-muted)',
97+
},
7598
},
7699
}))
77100
</script>

app/components/SettingsMenu.vue

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { onKeyStroke, onClickOutside } from '@vueuse/core'
33
44
const { settings } = useSettings()
55
const { locale, locales, setLocale } = useI18n()
6+
const colorMode = useColorMode()
67
78
const availableLocales = computed(() =>
89
locales.value.map(l => (typeof l === 'string' ? { code: l, name: l } : l)),
@@ -96,14 +97,16 @@ onKeyStroke(',', e => {
9697
>
9798
<span class="text-sm text-fg select-none">{{ $t('settings.relative_dates') }}</span>
9899
<span
99-
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none"
100-
:class="settings.relativeDates ? 'bg-fg' : 'bg-bg-subtle'"
100+
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none shadow"
101+
:class="settings.relativeDates ? 'bg-fg' : 'bg-bg'"
101102
aria-hidden="true"
102103
>
103104
<span
104105
class="pointer-events-none inline-block h-4 w-4 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none"
105106
:class="
106-
settings.relativeDates ? 'translate-x-4 bg-bg' : 'translate-x-0 bg-fg-muted'
107+
settings.relativeDates
108+
? 'translate-x-4 bg-bg-subtle'
109+
: 'translate-x-0 bg-fg-muted'
107110
"
108111
/>
109112
</span>
@@ -121,21 +124,47 @@ onKeyStroke(',', e => {
121124
$t('settings.include_types')
122125
}}</span>
123126
<span
124-
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none"
125-
:class="settings.includeTypesInInstall ? 'bg-fg' : 'bg-bg-subtle'"
127+
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none border border-border shadow"
128+
:class="settings.includeTypesInInstall ? 'bg-fg' : 'bg-bg'"
126129
aria-hidden="true"
127130
>
128131
<span
129132
class="pointer-events-none inline-block h-4 w-4 rounded-full shadow-sm ring-0 transition-transform duration-200 ease-in-out motion-reduce:transition-none"
130133
:class="
131134
settings.includeTypesInInstall
132-
? 'translate-x-4 bg-bg'
135+
? 'translate-x-4 bg-bg-subtle'
133136
: 'translate-x-0 bg-fg-muted'
134137
"
135138
/>
136139
</span>
137140
</button>
138141

142+
<!-- Theme selector -->
143+
<div class="pt-2 mt-2 border-t border-border">
144+
<div class="px-2 py-1">
145+
<label for="theme-select" class="text-xs text-fg-subtle uppercase tracking-wider">
146+
{{ $t('settings.theme') }}
147+
</label>
148+
</div>
149+
<div class="px-2 py-1">
150+
<select
151+
id="theme-select"
152+
:value="colorMode.preference"
153+
class="w-full bg-bg-muted border border-border rounded-md px-2 py-1.5 text-sm text-fg focus:outline-none focus:ring-2 focus:ring-fg/50 cursor-pointer"
154+
@change="
155+
colorMode.preference = ($event.target as HTMLSelectElement).value as
156+
| 'light'
157+
| 'dark'
158+
| 'system'
159+
"
160+
>
161+
<option value="system">{{ $t('settings.theme_system') }}</option>
162+
<option value="light">{{ $t('settings.theme_light') }}</option>
163+
<option value="dark">{{ $t('settings.theme_dark') }}</option>
164+
</select>
165+
</div>
166+
</div>
167+
139168
<!-- Language selector -->
140169
<div class="pt-2 mt-2 border-t border-border">
141170
<div class="px-2 py-1">

app/composables/useSettings.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ export function initAccentOnPrehydrate() {
9090
// Colors must be hardcoded since ACCENT_COLORS can't be referenced.
9191
onPrehydrate(() => {
9292
const colors: Record<AccentColorId, string> = {
93-
rose: '#e9aeba',
94-
amber: '#fbbf24',
95-
emerald: '#34d399',
96-
sky: '#38bdf8',
97-
violet: '#a78bfa',
98-
coral: '#fb7185',
93+
rose: 'oklch(0.797 0.084 11.056)',
94+
amber: 'oklch(0.828 0.165 84.429)',
95+
emerald: 'oklch(0.792 0.153 166.95)',
96+
sky: 'oklch(0.787 0.128 230.318)',
97+
violet: 'oklch(0.714 0.148 286.067)',
98+
coral: 'oklch(0.704 0.177 14.75)',
9999
}
100100
const settings = JSON.parse(localStorage.getItem('npmx-settings') || '{}')
101101
const color = settings.accentColorId ? colors[settings.accentColorId as AccentColorId] : null

app/pages/[...package].vue

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -762,7 +762,7 @@ defineOgImageComponent('Package', {
762762
</h2>
763763
<!-- Package manager tabs -->
764764
<div
765-
class="flex items-center gap-1 p-0.5 bg-bg-subtle border border-border rounded-md"
765+
class="flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md"
766766
role="tablist"
767767
:aria-label="$t('package.install.pm_label')"
768768
>
@@ -772,11 +772,11 @@ defineOgImageComponent('Package', {
772772
:key="pm.id"
773773
role="tab"
774774
:aria-selected="selectedPM === pm.id"
775-
class="px-2 py-1 font-mono text-xs rounded transition-colors duration-150 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
775+
class="px-2 py-1 font-mono text-xs rounded transition-colors duration-150 border border-solid focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50"
776776
:class="
777777
selectedPM === pm.id
778-
? 'bg-bg-elevated text-fg'
779-
: 'text-fg-subtle hover:text-fg-muted'
778+
? 'bg-bg shadow text-fg border-border'
779+
: 'text-fg-subtle hover:text-fg border-transparent'
780780
"
781781
@click="selectedPM = pm.id"
782782
>
@@ -797,11 +797,11 @@ defineOgImageComponent('Package', {
797797
</div>
798798
<div class="relative group">
799799
<!-- Terminal-style install command -->
800-
<div class="bg-[#0d0d0d] border border-border rounded-lg overflow-hidden">
800+
<div class="bg-bg-subtle border border-border rounded-lg overflow-hidden">
801801
<div class="flex gap-1.5 px-3 pt-2 sm:px-4 sm:pt-3">
802-
<span class="w-2.5 h-2.5 rounded-full bg-[#333]" />
803-
<span class="w-2.5 h-2.5 rounded-full bg-[#333]" />
804-
<span class="w-2.5 h-2.5 rounded-full bg-[#333]" />
802+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
803+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
804+
<span class="w-2.5 h-2.5 rounded-full bg-fg-subtle" />
805805
</div>
806806
<div class="space-y-1 px-3 pt-2 pb-3 sm:px-4 sm:pt-3 sm:pb-4">
807807
<!-- Main package install -->

i18n/locales/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@
4343
"settings": {
4444
"relative_dates": "Relative dates",
4545
"include_types": "Include {'@'}types in install",
46+
"theme": "Theme",
47+
"theme_light": "Light",
48+
"theme_dark": "Dark",
49+
"theme_system": "System",
4650
"language": "Language",
4751
"help_translate": "Help translate npmx"
4852
},

nuxt.config.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,17 @@ export default defineNuxtConfig({
3131
'@vite-pwa/nuxt',
3232
'@vueuse/nuxt',
3333
'@nuxtjs/i18n',
34+
'@nuxtjs/color-mode',
3435
],
3536

36-
css: ['vue-data-ui/style.css'],
37+
colorMode: {
38+
preference: 'system',
39+
fallback: 'dark',
40+
dataValue: 'theme',
41+
storageKey: 'npmx-color-mode',
42+
},
43+
44+
css: ['~/assets/main.css', 'vue-data-ui/style.css'],
3745

3846
devtools: { enabled: true },
3947

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"@nuxt/a11y": "1.0.0-alpha.1",
3333
"@nuxt/fonts": "^0.13.0",
3434
"@nuxt/scripts": "^0.13.2",
35+
"@nuxtjs/color-mode": "^4.0.0",
3536
"@nuxtjs/html-validator": "^2.1.0",
3637
"@nuxtjs/i18n": "10.2.1",
3738
"@shikijs/langs": "^3.21.0",

pnpm-lock.yaml

Lines changed: 18 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)