@naeil/ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/CHANGELOG.md +22 -2
  2. package/DESIGN.md +27 -0
  3. package/README.md +16 -9
  4. package/THIRD_PARTY_NOTICES.md +6 -0
  5. package/dist/chunk-CE73AEJZ.js +667 -0
  6. package/dist/{chunk-QKVN6Q6C.js → chunk-QSTGUEEI.js} +60 -175
  7. package/dist/chunk-S64H3OYQ.js +1512 -0
  8. package/dist/components/index.d.ts +33 -10
  9. package/dist/components/index.js +101 -557
  10. package/dist/components/naeil-header.d.ts +54 -0
  11. package/dist/components/naeil-header.js +14 -0
  12. package/dist/components/ui/index.d.ts +3 -1
  13. package/dist/components/ui/index.js +40 -179
  14. package/dist/navigation-CL10a6Eb.d.ts +48 -0
  15. package/dist/site-footer-B67meCDv.d.ts +21 -0
  16. package/dist/source/components/brand-artwork.generated.d.ts +162 -0
  17. package/dist/source/components/brand-artwork.generated.js +1103 -0
  18. package/dist/source/components/footer.d.ts +13 -4
  19. package/dist/source/components/footer.js +74 -114
  20. package/dist/source/components/index.d.ts +6 -4
  21. package/dist/source/components/locale-switcher.js +1 -1
  22. package/dist/source/components/logo.d.ts +13 -4
  23. package/dist/source/components/logo.js +83 -44
  24. package/dist/source/components/naeil-header-content.d.ts +171 -0
  25. package/dist/source/components/naeil-header-content.js +176 -0
  26. package/dist/source/components/naeil-header.d.ts +52 -0
  27. package/dist/source/components/naeil-header.js +196 -0
  28. package/dist/source/components/nav.d.ts +12 -4
  29. package/dist/source/components/nav.js +51 -384
  30. package/dist/source/components/ui/index.d.ts +2 -0
  31. package/dist/source/components/ui/index.js +4 -0
  32. package/dist/source/components/ui/navigation.d.ts +48 -0
  33. package/dist/source/components/ui/navigation.js +347 -0
  34. package/dist/source/components/ui/site-footer.d.ts +21 -0
  35. package/dist/source/components/ui/site-footer.js +93 -0
  36. package/docs/components/README.md +6 -1
  37. package/docs/components/common.md +1 -1
  38. package/docs/components/naeil-header.md +50 -0
  39. package/docs/components/navigation.md +59 -0
  40. package/docs/design/public-ui-support.md +17 -2
  41. package/docs/design/v2-migration.md +75 -11
  42. package/docs/package-release.md +54 -13
  43. package/licenses/Lato-OFL.txt +93 -0
  44. package/package.json +18 -4
  45. package/src/styles/components.css +292 -0
  46. package/src/styles/theme.css +4 -0
@@ -1,12 +1,19 @@
1
1
  "use client";
2
2
  import {
3
- Badge,
4
- Button,
3
+ Logo,
4
+ NaeilHeader,
5
+ headerLocales
6
+ } from "../chunk-S64H3OYQ.js";
7
+ import {
5
8
  DropdownMenu,
6
9
  DropdownMenuContent,
7
10
  DropdownMenuItem,
8
- DropdownMenuTrigger
9
- } from "../chunk-QKVN6Q6C.js";
11
+ DropdownMenuTrigger,
12
+ SiteFooter
13
+ } from "../chunk-QSTGUEEI.js";
14
+ import {
15
+ Button
16
+ } from "../chunk-CE73AEJZ.js";
10
17
  import {
11
18
  __objRest,
12
19
  __spreadProps,
@@ -15,47 +22,9 @@ import {
15
22
  } from "../chunk-JBTDRVZ7.js";
16
23
 
17
24
  // src/components/nav.tsx
18
- import { useEffect, useState } from "react";
19
- import { useTranslations } from "next-intl";
20
- import Image from "next/image";
25
+ import { useLocale, useTranslations } from "next-intl";
21
26
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
22
- var PROJECTS = [
23
- {
24
- key: "cc",
25
- href: "/cc",
26
- accent: "oklch(0.704 0.140 181)",
27
- icon: "/images/coral.png",
28
- status: "active"
29
- },
30
- {
31
- key: "pkm",
32
- href: "/pkm",
33
- accent: "oklch(0.702 0.183 293)",
34
- icon: "/images/jellyfish.png",
35
- status: "coming"
36
- },
37
- {
38
- key: "naeilUi",
39
- href: "/design",
40
- accent: "oklch(0.623 0.214 259)",
41
- icon: "/images/whale.png",
42
- status: "active"
43
- },
44
- {
45
- key: "sa",
46
- href: "/sa",
47
- accent: "oklch(0.723 0.219 149)",
48
- icon: "/images/fish.png",
49
- status: "active"
50
- },
51
- {
52
- key: "babyAgent",
53
- href: "/baby-agent",
54
- accent: "oklch(0.769 0.188 70.08)",
55
- icon: "/images/turtle.png",
56
- status: "coming"
57
- }
58
- ];
27
+ var NativeBrandLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
59
28
  function Nav({
60
29
  Link,
61
30
  usePathname,
@@ -70,355 +39,43 @@ function Nav({
70
39
  authSlot,
71
40
  showProjects = true,
72
41
  showBlog = true,
73
- toolbarSlot
42
+ toolbarSlot,
43
+ projects,
44
+ className,
45
+ containerClassName,
46
+ labels
74
47
  }) {
48
+ var _a;
49
+ const consumerLocale = useLocale();
50
+ const locale = (_a = headerLocales.find((value) => value === consumerLocale)) != null ? _a : "en";
75
51
  const t = useTranslations("nav");
76
52
  const pt = useTranslations("projects");
77
53
  const pathname = usePathname();
78
- const [scrolled, setScrolled] = useState(false);
79
- const [mobileOpen, setMobileOpen] = useState(false);
80
- const [projectsOpen, setProjectsOpen] = useState(false);
81
- useEffect(() => {
82
- const onScroll = () => setScrolled(window.scrollY > 16);
83
- window.addEventListener("scroll", onScroll, { passive: true });
84
- return () => window.removeEventListener("scroll", onScroll);
85
- }, []);
86
- useEffect(() => {
87
- setMobileOpen(false);
88
- setProjectsOpen(false);
89
- }, [pathname]);
90
- useEffect(() => {
91
- document.body.style.overflow = mobileOpen ? "hidden" : "";
92
- return () => {
93
- document.body.style.overflow = "";
94
- };
95
- }, [mobileOpen]);
96
- const linkClass = (href) => {
97
- const isActive = pathname === href;
98
- return [
99
- "text-sm font-medium transition-colors",
100
- isActive ? "text-foreground" : "text-muted-foreground hover:text-foreground"
101
- ].join(" ");
102
- };
103
- const isProjectActive = pathname.startsWith("/projects") || pathname.startsWith("/cc") || pathname.startsWith("/pkm") || pathname.startsWith("/sa") || pathname.startsWith("/design");
104
- function getProjectLink(project) {
105
- if (currentProjectKey && project.key === currentProjectKey) {
106
- return { href: currentProjectHref || "/", external: false };
107
- }
108
- if (projectsExternal) {
109
- return { href: `${externalBaseUrl}${project.href}`, external: true };
110
- }
111
- return { href: project.href, external: false };
112
- }
113
- const brandContent = brandSlot != null ? brandSlot : /* @__PURE__ */ jsxs("span", { className: "text-foreground flex items-center gap-3 text-xl font-semibold tracking-tight", children: [
114
- /* @__PURE__ */ jsx(Logo, { size: 28 }),
115
- ".naeil"
116
- ] });
117
- const brandElement = brandExternal ? /* @__PURE__ */ jsx("a", { href: brandHref, children: brandContent }) : /* @__PURE__ */ jsx(Link, { href: brandHref, children: brandContent });
118
- return /* @__PURE__ */ jsxs(Fragment, { children: [
119
- /* @__PURE__ */ jsx(
120
- "nav",
121
- {
122
- className: [
123
- "fixed top-0 z-50 w-full transition-[background-color,border-color] duration-300",
124
- scrolled || mobileOpen ? "border-b border-border/40 bg-background/80 backdrop-blur-md" : "border-b border-transparent bg-transparent"
125
- ].join(" "),
126
- children: /* @__PURE__ */ jsxs("div", { className: "mx-auto flex h-[58px] max-w-7xl items-center px-6", children: [
127
- /* @__PURE__ */ jsx("div", { className: "flex shrink-0 items-center md:w-[200px]", children: brandElement }),
128
- /* @__PURE__ */ jsxs("div", { className: "hidden flex-1 items-center gap-6 md:flex", children: [
129
- showProjects && /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
130
- /* @__PURE__ */ jsxs(
131
- "button",
132
- {
133
- className: [
134
- "text-sm font-medium transition-colors",
135
- isProjectActive ? "text-foreground" : "text-muted-foreground hover:text-foreground"
136
- ].join(" "),
137
- children: [
138
- t("projects"),
139
- /* @__PURE__ */ jsx(
140
- "svg",
141
- {
142
- width: "10",
143
- height: "10",
144
- viewBox: "0 0 24 24",
145
- fill: "none",
146
- stroke: "currentColor",
147
- strokeWidth: "2",
148
- strokeLinecap: "round",
149
- strokeLinejoin: "round",
150
- className: "ml-1 inline-block transition-transform group-hover:rotate-180",
151
- children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" })
152
- }
153
- )
154
- ]
155
- }
156
- ),
157
- /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute left-0 top-full pt-3 opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100", children: /* @__PURE__ */ jsx("div", { className: "border-border/40 bg-background/95 w-[520px] rounded-xl border p-4 shadow-xl backdrop-blur-md", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1", children: PROJECTS.map((project) => {
158
- const { href, external } = getProjectLink(project);
159
- const inner = /* @__PURE__ */ jsxs("div", { className: "hover:bg-muted/50 flex items-start gap-3.5 rounded-lg px-3 py-3 transition-colors", children: [
160
- /* @__PURE__ */ jsx(
161
- "div",
162
- {
163
- className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg border",
164
- style: {
165
- borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
166
- backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
167
- },
168
- children: /* @__PURE__ */ jsx(
169
- Image,
170
- {
171
- src: project.icon,
172
- alt: "",
173
- width: 24,
174
- height: 24,
175
- className: "object-contain"
176
- }
177
- )
178
- }
179
- ),
180
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
181
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
182
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-medium", children: pt(`${project.key}.name`) }),
183
- project.status === "coming" && /* @__PURE__ */ jsx(
184
- Badge,
185
- {
186
- variant: "outline",
187
- className: "text-muted-foreground px-1 py-0 text-[9px]",
188
- children: pt("status.coming")
189
- }
190
- )
191
- ] }),
192
- /* @__PURE__ */ jsx("p", { className: "text-muted-foreground mt-0.5 text-xs leading-snug", children: pt(`${project.key}.description`) })
193
- ] })
194
- ] });
195
- if (external) {
196
- return /* @__PURE__ */ jsx("a", { href, children: inner }, project.key);
197
- }
198
- return /* @__PURE__ */ jsx(Link, { href, children: inner }, project.key);
199
- }) }) }) })
200
- ] }),
201
- showBlog && /* @__PURE__ */ jsx(Fragment, { children: projectsExternal ? /* @__PURE__ */ jsx(
202
- "a",
203
- {
204
- href: `${externalBaseUrl}/blog`,
205
- className: "text-sm font-medium text-muted-foreground transition-colors hover:text-foreground",
206
- children: t("blog")
207
- }
208
- ) : /* @__PURE__ */ jsx(Link, { href: "/blog", className: linkClass("/blog"), children: t("blog") }) }),
209
- subNav && subNav.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
210
- /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-border/40" }),
211
- subNav.map((item) => /* @__PURE__ */ jsx(
212
- Link,
213
- {
214
- href: item.href,
215
- className: linkClass(item.href),
216
- children: item.label
217
- },
218
- item.href
219
- ))
220
- ] })
221
- ] }),
222
- /* @__PURE__ */ jsxs("div", { className: "hidden items-center gap-3 md:flex", children: [
223
- authSlot,
224
- authSlot && toolbarSlot && /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-border/40" }),
225
- toolbarSlot && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: toolbarSlot })
226
- ] }),
227
- /* @__PURE__ */ jsx(
228
- "button",
229
- {
230
- className: "text-muted-foreground hover:text-foreground ml-auto transition-colors md:hidden",
231
- onClick: () => setMobileOpen(!mobileOpen),
232
- "aria-label": "Menu",
233
- children: mobileOpen ? /* @__PURE__ */ jsx(CloseIcon, {}) : /* @__PURE__ */ jsx(MenuIcon, {})
234
- }
235
- )
236
- ] })
237
- }
238
- ),
239
- mobileOpen && /* @__PURE__ */ jsx("div", { className: "bg-background/95 fixed inset-0 z-40 overflow-y-auto pt-[58px] backdrop-blur-md md:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-6 py-6", children: [
240
- showProjects && /* @__PURE__ */ jsxs(Fragment, { children: [
241
- /* @__PURE__ */ jsxs(
242
- "button",
243
- {
244
- className: "text-foreground flex items-center justify-between py-3 text-base font-medium",
245
- onClick: () => setProjectsOpen(!projectsOpen),
246
- children: [
247
- t("projects"),
248
- /* @__PURE__ */ jsx(
249
- "svg",
250
- {
251
- width: "14",
252
- height: "14",
253
- viewBox: "0 0 24 24",
254
- fill: "none",
255
- stroke: "currentColor",
256
- strokeWidth: "2",
257
- strokeLinecap: "round",
258
- strokeLinejoin: "round",
259
- className: [
260
- "transition-transform duration-200",
261
- projectsOpen ? "rotate-180" : ""
262
- ].join(" "),
263
- children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6" })
264
- }
265
- )
266
- ]
267
- }
268
- ),
269
- projectsOpen && /* @__PURE__ */ jsx("div", { className: "mb-2 flex flex-col gap-1 pl-1", children: PROJECTS.map((project) => {
270
- const { href, external } = getProjectLink(project);
271
- const inner = /* @__PURE__ */ jsxs("div", { className: "hover:bg-muted/50 flex items-center gap-3 rounded-lg px-3 py-3 transition-colors", children: [
272
- /* @__PURE__ */ jsx(
273
- "div",
274
- {
275
- className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-lg border",
276
- style: {
277
- borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
278
- backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
279
- },
280
- children: /* @__PURE__ */ jsx(
281
- Image,
282
- {
283
- src: project.icon,
284
- alt: "",
285
- width: 20,
286
- height: 20,
287
- className: "object-contain"
288
- }
289
- )
290
- }
291
- ),
292
- /* @__PURE__ */ jsxs("div", { children: [
293
- /* @__PURE__ */ jsx("span", { className: "text-foreground text-sm font-medium", children: pt(`${project.key}.name`) }),
294
- project.status === "coming" && /* @__PURE__ */ jsx(
295
- Badge,
296
- {
297
- variant: "outline",
298
- className: "text-muted-foreground ml-2 px-1 py-0 text-[9px]",
299
- children: pt("status.coming")
300
- }
301
- )
302
- ] })
303
- ] });
304
- if (external) {
305
- return /* @__PURE__ */ jsx(
306
- "a",
307
- {
308
- href,
309
- onClick: () => setMobileOpen(false),
310
- children: inner
311
- },
312
- project.key
313
- );
314
- }
315
- return /* @__PURE__ */ jsx(
316
- Link,
317
- {
318
- href,
319
- onClick: () => setMobileOpen(false),
320
- children: inner
321
- },
322
- project.key
323
- );
324
- }) })
325
- ] }),
326
- showBlog && /* @__PURE__ */ jsx(Fragment, { children: projectsExternal ? /* @__PURE__ */ jsx(
327
- "a",
328
- {
329
- href: `${externalBaseUrl}/blog`,
330
- className: "text-foreground border-border/40 border-t py-3 text-base font-medium",
331
- onClick: () => setMobileOpen(false),
332
- children: t("blog")
333
- }
334
- ) : /* @__PURE__ */ jsx(
335
- Link,
336
- {
337
- href: "/blog",
338
- className: "text-foreground border-border/40 border-t py-3 text-base font-medium",
339
- onClick: () => setMobileOpen(false),
340
- children: t("blog")
341
- }
342
- ) }),
343
- subNav && subNav.length > 0 && /* @__PURE__ */ jsx("div", { className: "border-border/40 border-t", children: subNav.map((item) => /* @__PURE__ */ jsx(
344
- Link,
345
- {
346
- href: item.href,
347
- className: "text-foreground block py-3 text-base font-medium",
348
- onClick: () => setMobileOpen(false),
349
- children: item.label
350
- },
351
- item.href
352
- )) }),
353
- authSlot && /* @__PURE__ */ jsx("div", { className: "border-border/40 border-t pt-4", children: authSlot }),
354
- toolbarSlot && /* @__PURE__ */ jsx("div", { className: "border-border/40 flex items-center gap-4 border-t pt-4 mt-2", children: toolbarSlot })
355
- ] }) })
356
- ] });
357
- }
358
- function Logo({
359
- size = 20
360
- }) {
361
- const id = `naeil-nav-logo-${size}`;
362
- return /* @__PURE__ */ jsxs(
363
- "svg",
364
- {
365
- width: size,
366
- height: size,
367
- viewBox: "0 0 24 24",
368
- fill: "none",
369
- "aria-label": "naeil",
370
- children: [
371
- /* @__PURE__ */ jsx(
372
- "path",
373
- {
374
- d: "M6 4 L6 16 L20 16",
375
- stroke: "currentColor",
376
- strokeWidth: "2",
377
- strokeLinecap: "square",
378
- strokeLinejoin: "miter"
379
- }
380
- ),
381
- /* @__PURE__ */ jsx("circle", { cx: "15", cy: "16", r: "3.5", fill: `url(#${id}-grad)`, mask: `url(#${id})` }),
382
- /* @__PURE__ */ jsxs("defs", { children: [
383
- /* @__PURE__ */ jsxs("linearGradient", { id: `${id}-grad`, x1: "15", y1: "12.5", x2: "15", y2: "16", children: [
384
- /* @__PURE__ */ jsx("stop", { stopColor: "#eab308" }),
385
- /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#dc2626" })
386
- ] }),
387
- /* @__PURE__ */ jsx("mask", { id, children: /* @__PURE__ */ jsx("rect", { x: "0", y: "0", width: "24", height: "16", fill: "white" }) })
388
- ] })
389
- ]
390
- }
391
- );
392
- }
393
- function MenuIcon() {
394
- return /* @__PURE__ */ jsx(
395
- "svg",
396
- {
397
- width: "22",
398
- height: "22",
399
- viewBox: "0 0 24 24",
400
- fill: "none",
401
- stroke: "currentColor",
402
- strokeWidth: "1.5",
403
- strokeLinecap: "round",
404
- strokeLinejoin: "round",
405
- children: /* @__PURE__ */ jsx("path", { d: "M4 6h16M4 12h16M4 18h16" })
406
- }
407
- );
408
- }
409
- function CloseIcon() {
410
54
  return /* @__PURE__ */ jsx(
411
- "svg",
55
+ NaeilHeader,
412
56
  {
413
- width: "22",
414
- height: "22",
415
- viewBox: "0 0 24 24",
416
- fill: "none",
417
- stroke: "currentColor",
418
- strokeWidth: "1.5",
419
- strokeLinecap: "round",
420
- strokeLinejoin: "round",
421
- children: /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" })
57
+ locale,
58
+ Link,
59
+ currentHref: pathname,
60
+ resolveHref: (path) => projectsExternal ? `${externalBaseUrl}${path}` : path,
61
+ projectsExternal,
62
+ translations: { projects: showProjects ? t("projects") : "", blog: showBlog ? t("blog") : "", project: pt },
63
+ brandHref,
64
+ brandSlot,
65
+ brandLinkComponent: brandExternal ? NativeBrandLink : Link,
66
+ currentProjectKey,
67
+ currentProjectHref,
68
+ subNav,
69
+ projects,
70
+ showProjects,
71
+ showBlog,
72
+ toolbarSlot: /* @__PURE__ */ jsxs(Fragment, { children: [
73
+ authSlot,
74
+ toolbarSlot
75
+ ] }),
76
+ className,
77
+ containerClassName,
78
+ labels
422
79
  }
423
80
  );
424
81
  }
@@ -426,47 +83,65 @@ function CloseIcon() {
426
83
  // src/components/footer.tsx
427
84
  import { useTranslations as useTranslations2 } from "next-intl";
428
85
  import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
429
- function NavLink({
430
- href,
431
- children,
86
+ function Footer({
87
+ Link,
88
+ linksExternal = false,
89
+ brandSlot,
90
+ description,
91
+ groups,
92
+ socialSlot,
93
+ meta,
94
+ variant,
432
95
  className,
433
- linksExternal,
434
- Link
96
+ containerClassName
435
97
  }) {
436
- if (linksExternal) {
437
- return /* @__PURE__ */ jsx2(
438
- "a",
439
- {
440
- href: `https://naeil.dev${href}`,
441
- target: "_blank",
442
- rel: "noopener noreferrer",
443
- className,
444
- children
445
- }
446
- );
447
- }
448
- if (Link) {
449
- return /* @__PURE__ */ jsx2(Link, { href, className, children });
450
- }
451
- return /* @__PURE__ */ jsx2("a", { href, className, children });
452
- }
453
- function Footer({ Link, linksExternal = false }) {
454
98
  const t = useTranslations2("footer");
455
- return /* @__PURE__ */ jsx2("footer", { className: "border-border/40 border-t", children: /* @__PURE__ */ jsxs2("div", { className: "mx-auto flex max-w-7xl flex-col gap-10 px-6 py-16 sm:flex-row sm:justify-between", children: [
456
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-4", children: [
457
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
458
- /* @__PURE__ */ jsx2(Logo2, { size: 20 }),
459
- /* @__PURE__ */ jsx2("span", { className: "text-foreground text-sm font-semibold tracking-tight", children: ".naeil" })
460
- ] }),
461
- /* @__PURE__ */ jsx2("p", { className: "text-muted-foreground max-w-[240px] text-sm leading-relaxed", children: t("tagline") }),
462
- /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
99
+ const destinations = [
100
+ { id: "projects", label: t("projects"), href: "/projects" },
101
+ { id: "blog", label: t("blog"), href: "/blog" }
102
+ ];
103
+ return /* @__PURE__ */ jsx2(
104
+ SiteFooter,
105
+ {
106
+ Link,
107
+ className,
108
+ containerClassName: cn("max-w-7xl", containerClassName),
109
+ variant,
110
+ brand: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx2(Logo, { variant: "footer", size: 20, className: "block" }),
111
+ description: description === void 0 ? t("tagline") : description,
112
+ groups: groups != null ? groups : [
113
+ {
114
+ id: "navigation",
115
+ label: t("navigation"),
116
+ links: destinations.map((item) => __spreadProps(__spreadValues({}, item), {
117
+ href: linksExternal ? `https://naeil.dev${item.href}` : item.href,
118
+ external: linksExternal,
119
+ target: linksExternal ? "_blank" : void 0
120
+ }))
121
+ },
122
+ {
123
+ id: "social",
124
+ label: t("social"),
125
+ links: [
126
+ {
127
+ id: "github",
128
+ label: "GitHub",
129
+ href: "https://github.com/naeil-dev",
130
+ external: true,
131
+ target: "_blank"
132
+ }
133
+ ]
134
+ }
135
+ ],
136
+ meta,
137
+ children: socialSlot === void 0 ? /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-3", children: [
463
138
  /* @__PURE__ */ jsx2(
464
139
  "a",
465
140
  {
466
141
  href: "https://github.com/naeil-dev",
467
142
  target: "_blank",
468
143
  rel: "noopener noreferrer",
469
- className: "text-muted-foreground hover:text-foreground transition-colors",
144
+ className: "ui-navigation-link ui-focus",
470
145
  "aria-label": "GitHub",
471
146
  children: /* @__PURE__ */ jsx2(GitHubIcon, {})
472
147
  }
@@ -477,92 +152,12 @@ function Footer({ Link, linksExternal = false }) {
477
152
  href: "https://x.com",
478
153
  target: "_blank",
479
154
  rel: "noopener noreferrer",
480
- className: "text-muted-foreground hover:text-foreground transition-colors",
155
+ className: "ui-navigation-link ui-focus",
481
156
  "aria-label": "X",
482
157
  children: /* @__PURE__ */ jsx2(XIcon, {})
483
158
  }
484
159
  )
485
- ] })
486
- ] }),
487
- /* @__PURE__ */ jsxs2("div", { className: "flex gap-10 sm:gap-16", children: [
488
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
489
- /* @__PURE__ */ jsx2("span", { className: "text-foreground text-xs font-medium uppercase tracking-wider", children: t("navigation") }),
490
- /* @__PURE__ */ jsx2(
491
- NavLink,
492
- {
493
- href: "/projects",
494
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
495
- linksExternal,
496
- Link,
497
- children: t("projects")
498
- }
499
- ),
500
- /* @__PURE__ */ jsx2(
501
- NavLink,
502
- {
503
- href: "/blog",
504
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
505
- linksExternal,
506
- Link,
507
- children: t("blog")
508
- }
509
- )
510
- ] }),
511
- /* @__PURE__ */ jsxs2("div", { className: "flex flex-col gap-3", children: [
512
- /* @__PURE__ */ jsx2("span", { className: "text-foreground text-xs font-medium uppercase tracking-wider", children: t("social") }),
513
- /* @__PURE__ */ jsx2(
514
- "a",
515
- {
516
- href: "https://github.com/naeil-dev",
517
- target: "_blank",
518
- rel: "noopener noreferrer",
519
- className: "text-muted-foreground hover:text-foreground text-sm transition-colors",
520
- children: "GitHub \u2197"
521
- }
522
- )
523
- ] })
524
- ] })
525
- ] }) });
526
- }
527
- function Logo2({ size = 20 }) {
528
- const id = `naeil-footer-logo-${size}`;
529
- return /* @__PURE__ */ jsxs2(
530
- "svg",
531
- {
532
- width: size,
533
- height: size,
534
- viewBox: "0 0 24 24",
535
- fill: "none",
536
- "aria-label": "naeil",
537
- children: [
538
- /* @__PURE__ */ jsx2(
539
- "path",
540
- {
541
- d: "M6 4 L6 16 L20 16",
542
- stroke: "currentColor",
543
- strokeWidth: "2",
544
- strokeLinecap: "square",
545
- strokeLinejoin: "miter"
546
- }
547
- ),
548
- /* @__PURE__ */ jsx2(
549
- "circle",
550
- {
551
- cx: "15",
552
- cy: "16",
553
- r: "3.5",
554
- fill: `url(#${id}-grad)`,
555
- mask: `url(#${id})`
556
- }
557
- ),
558
- /* @__PURE__ */ jsxs2("defs", { children: [
559
- /* @__PURE__ */ jsxs2("linearGradient", { id: `${id}-grad`, x1: "15", y1: "12.5", x2: "15", y2: "16", children: [
560
- /* @__PURE__ */ jsx2("stop", { stopColor: "#eab308" }),
561
- /* @__PURE__ */ jsx2("stop", { offset: "1", stopColor: "#dc2626" })
562
- ] }),
563
- /* @__PURE__ */ jsx2("mask", { id, children: /* @__PURE__ */ jsx2("rect", { x: "0", y: "0", width: "24", height: "16", fill: "white" }) })
564
- ] })
565
- ]
160
+ ] }) : socialSlot
566
161
  }
567
162
  );
568
163
  }
@@ -606,7 +201,7 @@ function LocaleSwitcher({
606
201
  /* @__PURE__ */ jsx3(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
607
202
  "button",
608
203
  {
609
- className: "text-muted-foreground hover:text-foreground flex items-center gap-1.5 text-sm transition-colors focus:outline-none",
204
+ className: "ui-focus text-muted-foreground hover:text-foreground inline-flex min-h-11 min-w-11 items-center justify-center gap-1.5 rounded-md px-2 text-sm transition-colors",
610
205
  "aria-label": `Change language \u2014 current: ${(_a = current == null ? void 0 : current.short) != null ? _a : currentLocale}`,
611
206
  children: [
612
207
  /* @__PURE__ */ jsx3(GlobeIcon, {}),
@@ -754,73 +349,22 @@ function ThemeToggleIcon() {
754
349
  );
755
350
  }
756
351
 
757
- // src/components/logo.tsx
758
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
759
- function Logo3({
760
- size = 20,
761
- mono = false,
762
- className
763
- }) {
764
- const id = `naeil-logo-${size}`;
765
- return /* @__PURE__ */ jsxs5(
766
- "svg",
767
- {
768
- width: size,
769
- height: size,
770
- viewBox: "0 0 24 24",
771
- fill: "none",
772
- "aria-label": "naeil",
773
- className,
774
- children: [
775
- /* @__PURE__ */ jsx7(
776
- "path",
777
- {
778
- d: "M6 4 L6 16 L20 16",
779
- stroke: "currentColor",
780
- strokeWidth: "2",
781
- strokeLinecap: "square",
782
- strokeLinejoin: "miter"
783
- }
784
- ),
785
- mono ? /* @__PURE__ */ jsx7("circle", { cx: "15", cy: "16", r: "3.5", fill: "currentColor", mask: `url(#${id})` }) : /* @__PURE__ */ jsx7("circle", { cx: "15", cy: "16", r: "3.5", fill: `url(#${id}-grad)`, mask: `url(#${id})` }),
786
- /* @__PURE__ */ jsxs5("defs", { children: [
787
- !mono && /* @__PURE__ */ jsxs5(
788
- "linearGradient",
789
- {
790
- id: `${id}-grad`,
791
- x1: "15",
792
- y1: "12.5",
793
- x2: "15",
794
- y2: "16",
795
- children: [
796
- /* @__PURE__ */ jsx7("stop", { stopColor: "#eab308" }),
797
- /* @__PURE__ */ jsx7("stop", { offset: "1", stopColor: "#dc2626" })
798
- ]
799
- }
800
- ),
801
- /* @__PURE__ */ jsx7("mask", { id, children: /* @__PURE__ */ jsx7("rect", { x: "0", y: "0", width: "24", height: "16", fill: "white" }) })
802
- ] })
803
- ]
804
- }
805
- );
806
- }
807
-
808
352
  // src/components/typography.tsx
809
- import { jsx as jsx8 } from "react/jsx-runtime";
353
+ import { jsx as jsx7 } from "react/jsx-runtime";
810
354
  var pageTitleClass = "text-foreground text-3xl font-semibold leading-tight";
811
355
  var sectionTitleClass = "text-foreground text-xl font-semibold";
812
356
  function PageTitle(_a) {
813
357
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
814
- return /* @__PURE__ */ jsx8("h1", __spreadProps(__spreadValues({ className: cn(pageTitleClass, className) }, props), { children }));
358
+ return /* @__PURE__ */ jsx7("h1", __spreadProps(__spreadValues({ className: cn(pageTitleClass, className) }, props), { children }));
815
359
  }
816
360
  function SectionTitle(_a) {
817
361
  var _b = _a, { className, children } = _b, props = __objRest(_b, ["className", "children"]);
818
- return /* @__PURE__ */ jsx8("h2", __spreadProps(__spreadValues({ className: cn(sectionTitleClass, className) }, props), { children }));
362
+ return /* @__PURE__ */ jsx7("h2", __spreadProps(__spreadValues({ className: cn(sectionTitleClass, className) }, props), { children }));
819
363
  }
820
364
  export {
821
365
  Footer,
822
366
  LocaleSwitcher,
823
- Logo3 as Logo,
367
+ Logo,
824
368
  Nav,
825
369
  PageTitle,
826
370
  SectionTitle,