a10418ab93
- CV split button: make the chevron <details> flex and the summary full-height so the toggle matches the primary button height (verified 39.1px == 39.1px) - nginx: /Linkedin now 301s to the real profile (linkedin.com/in/connor-babbington) - prettier-ignore .pnpm-store; gitignore .claude/settings.local.json; e2e port 4321->4399; dev preview autoPort Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
72 lines
2.7 KiB
Plaintext
72 lines
2.7 KiB
Plaintext
---
|
|
/*
|
|
CV split button (MICRO_INTERACTIONS): primary zone downloads the current-locale CV;
|
|
the chevron is a native <details> disclosure listing both languages with file sizes
|
|
— works with no JavaScript. nav.ts enhances it with outside-click / Esc close.
|
|
*/
|
|
import { useDict, interpolate } from '@i18n/t';
|
|
import type { Locale } from '@i18n/locales';
|
|
import { getProfile } from '@lib/content';
|
|
|
|
interface Props {
|
|
locale: Locale;
|
|
compact?: boolean;
|
|
}
|
|
const { locale, compact = false } = Astro.props;
|
|
const d = useDict(locale);
|
|
const p = getProfile(locale);
|
|
const current = p.cv[locale];
|
|
const other = locale === 'en' ? p.cv.no : p.cv.en;
|
|
const otherLabel = locale === 'en' ? d.cv.norsk : d.cv.english;
|
|
const currentLabel = locale === 'en' ? d.cv.english : d.cv.norsk;
|
|
---
|
|
|
|
<div class="cv-split relative inline-flex items-stretch">
|
|
<a
|
|
href={current.path}
|
|
download
|
|
class="bg-accent text-small text-accent-ink inline-flex items-center rounded-l-sm px-4 py-2 font-semibold transition-[filter] duration-[--dur-quick] hover:brightness-105"
|
|
>
|
|
{d.cv.download}
|
|
{!compact && <span class="text-mono-label ml-2 font-mono opacity-70">EN/NO</span>}
|
|
</a>
|
|
<details class="cv-menu flex">
|
|
<summary
|
|
class="border-accent-ink/20 bg-accent text-accent-ink flex h-full cursor-pointer list-none items-center rounded-r-sm border-l px-2 transition-[filter] duration-[--dur-quick] hover:brightness-105"
|
|
aria-label={d.cv.download}
|
|
>
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" aria-hidden="true">
|
|
<path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2" stroke-linecap="round"></path>
|
|
</svg>
|
|
</summary>
|
|
<div
|
|
class="border-line-strong bg-surface-2 absolute top-[calc(100%+8px)] right-0 z-30 w-64 overflow-hidden rounded-md border shadow-[var(--shadow-overlay)]"
|
|
>
|
|
<a
|
|
href={current.path}
|
|
download
|
|
class="text-small text-ink hover:bg-surface-1 flex items-center justify-between gap-2 px-4 py-3"
|
|
>
|
|
<span
|
|
><span class="text-mono-label text-accent mr-2 font-mono">{d.lang[locale]}</span>{
|
|
currentLabel
|
|
}</span
|
|
>
|
|
<span class="mono-meta">{interpolate(d.cv.fileMeta, { size: current.sizeKb })}</span>
|
|
</a>
|
|
<a
|
|
href={other.path}
|
|
download
|
|
class="border-line text-small text-ink-muted hover:bg-surface-1 hover:text-ink flex items-center justify-between gap-2 border-t px-4 py-3"
|
|
>
|
|
<span
|
|
><span class="text-mono-label mr-2 font-mono">{locale === 'en' ? 'NO' : 'EN'}</span>{
|
|
otherLabel
|
|
}</span
|
|
>
|
|
<span class="mono-meta">{interpolate(d.cv.fileMeta, { size: other.sizeKb })}</span>
|
|
</a>
|
|
</div>
|
|
</details>
|
|
</div>
|