Skip to content

Commit 84efccc

Browse files
authored
Merge branch 'main' into feat/file-tree-scoll-to-active-node
2 parents ab14372 + b6da02d commit 84efccc

File tree

6 files changed

+43
-159
lines changed

6 files changed

+43
-159
lines changed

app/components/OgImage/BlogPost.vue

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ const formattedAuthorNames = computed(() => {
110110
v-if="author.avatar"
111111
:src="author.avatar"
112112
:alt="author.name"
113+
width="48"
114+
height="48"
113115
class="w-full h-full object-cover"
114116
/>
115117
<span v-else style="font-size: 20px; color: #666; font-weight: 500">

app/components/Settings/Toggle.client.vue

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const id = useId()
2727
<template>
2828
<label
2929
:for="id"
30-
class="grid items-center gap-1.5 py-1 -my-1 grid-cols-[auto_1fr_auto]"
30+
class="grid items-center gap-1.5 py-1 -my-1 grid-cols-[auto_1fr_auto] cursor-pointer"
3131
:class="[justify === 'start' ? 'justify-start' : '']"
3232
:style="
3333
props.reverseOrder
@@ -39,9 +39,9 @@ const id = useId()
3939
<input
4040
role="switch"
4141
type="checkbox"
42-
:id
42+
:id="id"
4343
v-model="checked"
44-
class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg-subtle checked:bg-fg checked:border-fg focus-visible:(outline-2 outline-fg outline-offset-2) before:content-[''] before:absolute before:h-5 before:w-5 before:top-1px before:rounded-full before:bg-bg"
44+
class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg/50 transition-colors duration-200 ease-in-out checked:bg-fg hover:bg-fg/60 checked:hover:(bg-fg/80 after:opacity-50) focus-visible:(outline-2 outline-accent outline-offset-2) before:(content-[''] absolute h-5 w-5 top-px start-px rounded-full bg-bg transition-transform duration-200 ease-in-out) checked:before:translate-x-[20px] rtl:checked:before:-translate-x-[20px] after:(content-[''] absolute h-3.5 w-3.5 top-[4px] start-[4px] i-lucide:check bg-fg opacity-0 transition-all duration-200 ease-in-out) checked:after:opacity-100 checked:after:translate-x-[20px] rtl:checked:after:-translate-x-[20px]"
4545
style="grid-area: toggle"
4646
/>
4747
<TooltipApp
@@ -85,9 +85,9 @@ const id = useId()
8585
<input
8686
role="switch"
8787
type="checkbox"
88-
:id
88+
:id="id"
8989
v-model="checked"
90-
class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg-subtle checked:bg-fg checked:border-fg focus-visible:(outline-2 outline-fg outline-offset-2) before:content-[''] before:absolute before:h-5 before:w-5 before:top-1px before:rounded-full before:bg-bg"
90+
class="toggle appearance-none h-6 w-11 rounded-full border border-fg relative shrink-0 bg-fg/50 transition-colors duration-200 ease-in-out checked:bg-fg hover:bg-fg/60 checked:hover:(bg-fg/80 after:opacity-50) focus-visible:(outline-2 outline-accent outline-offset-2) before:(content-[''] absolute h-5 w-5 top-px start-px rounded-full bg-bg transition-transform duration-200 ease-in-out) checked:before:translate-x-[20px] rtl:checked:before:-translate-x-[20px] after:(content-[''] absolute h-3.5 w-3.5 top-[4px] start-[4px] i-lucide:check bg-fg opacity-0 transition-all duration-200 ease-in-out) checked:after:opacity-100 checked:after:translate-x-[20px] rtl:checked:after:-translate-x-[20px]"
9191
style="grid-area: toggle; justify-self: end"
9292
/>
9393
</template>
@@ -98,82 +98,37 @@ const id = useId()
9898
</template>
9999

100100
<style scoped>
101-
/* Thumb position: logical property for RTL support */
102-
.toggle::before {
103-
inset-inline-start: 1px;
104-
}
105-
106-
/* Track transition */
107-
.toggle {
108-
transition:
109-
background-color 200ms ease-in-out,
110-
border-color 100ms ease-in-out;
111-
}
112-
113-
.toggle::before {
114-
transition:
115-
background-color 200ms ease-in-out,
116-
translate 200ms ease-in-out;
117-
}
118-
119-
/* Hover states */
120-
.toggle:hover:not(:checked) {
121-
background: var(--fg-muted);
122-
}
123-
124-
.toggle:checked:hover {
125-
background: var(--fg-muted);
126-
border-color: var(--fg-muted);
127-
}
128-
129-
/* RTL-aware checked thumb position */
130-
:dir(ltr) .toggle:checked::before {
131-
translate: 20px;
132-
}
133-
134-
:dir(rtl) .toggle:checked::before {
135-
translate: -20px;
136-
}
137-
138-
@media (prefers-reduced-motion: reduce) {
139-
.toggle,
140-
.toggle::before {
141-
transition: none;
142-
}
143-
}
144-
145101
/* Support forced colors */
146102
@media (forced-colors: active) {
147-
label > span {
103+
.toggle {
148104
background: Canvas;
149-
color: Highlight;
150-
forced-color-adjust: none;
105+
border-color: CanvasText;
151106
}
152107
153-
label:has(.toggle:checked) > span {
108+
.toggle:checked {
154109
background: Highlight;
155-
color: Canvas;
110+
border-color: CanvasText;
156111
}
157112
158113
.toggle::before {
159-
forced-color-adjust: none;
160-
background-color: Highlight;
114+
background-color: CanvasText;
161115
}
162116
163-
.toggle,
164-
.toggle:hover {
165-
background: Canvas;
166-
border-color: CanvasText;
117+
.toggle:checked::before {
118+
background-color: Canvas;
167119
}
168120
169-
.toggle:checked,
170-
.toggle:checked:hover {
171-
background: Highlight;
172-
border-color: CanvasText;
121+
.toggle::after {
122+
background-color: Highlight;
173123
}
124+
}
174125
175-
.toggle:checked::before {
176-
background: Canvas;
126+
@media (prefers-reduced-motion: reduce) {
127+
.toggle,
128+
.toggle::before,
129+
.toggle::after {
130+
transition: none !important;
131+
animation: none !important;
177132
}
178133
}
179134
</style>

app/components/Settings/Toggle.server.vue

Lines changed: 5 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ const props = withDefaults(
44
label: string
55
description?: string
66
justify?: 'between' | 'start'
7+
tooltip?: string
8+
tooltipPosition?: 'top' | 'bottom' | 'left' | 'right'
9+
tooltipTo?: string
10+
tooltipOffset?: number
711
reverseOrder?: boolean
812
}>(),
913
{
@@ -15,7 +19,7 @@ const props = withDefaults(
1519

1620
<template>
1721
<div
18-
class="grid items-center gap-4 py-1 -my-1 grid-cols-[auto_1fr_auto]"
22+
class="grid items-center gap-1.5 py-1 -my-1 grid-cols-[auto_1fr_auto]"
1923
:class="[justify === 'start' ? 'justify-start' : '']"
2024
:style="
2125
props.reverseOrder
@@ -51,84 +55,3 @@ const props = withDefaults(
5155
{{ description }}
5256
</p>
5357
</template>
54-
55-
<style scoped>
56-
/* Thumb position: logical property for RTL support */
57-
.toggle::before {
58-
inset-inline-start: 1px;
59-
}
60-
61-
/* Track transition */
62-
.toggle {
63-
transition:
64-
background-color 200ms ease-in-out,
65-
border-color 100ms ease-in-out;
66-
}
67-
68-
.toggle::before {
69-
transition:
70-
background-color 200ms ease-in-out,
71-
translate 200ms ease-in-out;
72-
}
73-
74-
/* Hover states */
75-
.toggle:hover:not(:checked) {
76-
background: var(--fg-muted);
77-
}
78-
79-
.toggle:checked:hover {
80-
background: var(--fg-muted);
81-
border-color: var(--fg-muted);
82-
}
83-
84-
/* RTL-aware checked thumb position */
85-
:dir(ltr) .toggle:checked::before {
86-
translate: 20px;
87-
}
88-
89-
:dir(rtl) .toggle:checked::before {
90-
translate: -20px;
91-
}
92-
93-
@media (prefers-reduced-motion: reduce) {
94-
.toggle,
95-
.toggle::before {
96-
transition: none;
97-
}
98-
}
99-
100-
/* Support forced colors */
101-
@media (forced-colors: active) {
102-
label > span {
103-
background: Canvas;
104-
color: Highlight;
105-
forced-color-adjust: none;
106-
}
107-
108-
label:has(.toggle:checked) > span {
109-
background: Highlight;
110-
color: Canvas;
111-
}
112-
113-
.toggle::before {
114-
forced-color-adjust: none;
115-
background-color: Highlight;
116-
}
117-
118-
.toggle,
119-
.toggle:hover {
120-
background: Canvas;
121-
border-color: CanvasText;
122-
}
123-
124-
.toggle:checked,
125-
.toggle:checked:hover {
126-
background: Highlight;
127-
border-color: CanvasText;
128-
}
129-
130-
.toggle:checked::before {
131-
background: Canvas;
132-
}
133-
}
134-
</style>

modules/blog.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,18 @@ async function fetchBlueskyAvatars(
5151
for (const profile of data.profiles) {
5252
if (profile.avatar) {
5353
const hash = crypto.createHash('sha256').update(profile.avatar).digest('hex')
54-
const dest = join(imagesDir, `${hash}.jpg`)
54+
const dest = join(imagesDir, `${hash}.png`)
5555

5656
if (!existsSync(dest)) {
57-
const res = await fetch(profile.avatar)
58-
await writeFile(join(imagesDir, `${hash}.jpg`), res.body!)
57+
const res = await fetch(`${profile.avatar}@png`)
58+
if (!res.ok || !res.body) {
59+
console.warn(`[blog] Failed to fetch Bluesky avatar: ${profile.avatar}@png`)
60+
continue
61+
}
62+
await writeFile(join(imagesDir, `${hash}.png`), res.body)
5963
}
6064

61-
avatarMap.set(profile.handle, `/blog/avatar/${hash}.jpg`)
65+
avatarMap.set(profile.handle, `/blog/avatar/${hash}.png`)
6266
}
6367
}
6468
} catch (error) {
@@ -85,7 +89,7 @@ function resolveAuthors(authors: Author[], avatarMap: Map<string, string>): Reso
8589
* Resolves Bluesky avatars at build time.
8690
*/
8791
async function loadBlogPosts(blogDir: string, imagesDir: string): Promise<BlogPostFrontmatter[]> {
88-
const files: string[] = globSync(join(blogDir, '*.md'))
92+
const files: string[] = globSync(join(blogDir, '*.md').replace(/\\/g, '/'))
8993

9094
// First pass: extract raw frontmatter and collect all Bluesky handles
9195
const rawPosts: Array<{ frontmatter: Record<string, unknown> }> = []

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
"vite-plugin-pwa": "1.2.0",
120120
"vite-plus": "0.0.0-g52709db6.20260226-1136",
121121
"vue": "3.5.29",
122-
"vue-data-ui": "3.15.9"
122+
"vue-data-ui": "3.15.10"
123123
},
124124
"devDependencies": {
125125
"@e18e/eslint-plugin": "0.2.0",

pnpm-lock.yaml

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

0 commit comments

Comments
 (0)