first publish

This commit is contained in:
knso committed 2026-09-06 17:21:52 +02:00
commit b8e41b4d55
147 files changed
+19367

No files matched your search

+64
View File
@@ -0,0 +1,64 @@
import { cn } from "@/lib/utils";
import { TransitionLink } from "@/components/motion/TransitionLink";
export interface TextLinkProps {
href: string;
label: string;
/** `target="_blank" rel="noopener noreferrer"` + ↗ instead of →. */
external?: boolean;
/** Anchor/arrow glyph override (default → / ↗ / ↓ for `#…`). */
arrow?: string;
className?: string;
}
/** Caps text link style (Jost 500, 13 px, ls .2em) – shared with ledger links.
* `-my-4/py-4` grows the tap target to 45 px without moving the baseline. */
export const TEXT_LINK =
"group/tl -my-4 inline-flex items-baseline gap-2 py-4 font-sans text-[0.8125rem] font-medium uppercase leading-none tracking-[0.2em] text-accent";
/** Underline grows from the left (`background-size 0 → 100%`, 0.4 s). */
export const GROW_UNDERLINE =
"bg-[linear-gradient(currentColor,currentColor)] bg-[length:0%_1px] bg-left-bottom bg-no-repeat pb-1 transition-[background-size] duration-[400ms] ease-[var(--ease-out-quart)] group-hover/tl:bg-[length:100%_1px] group-focus-visible/tl:bg-[length:100%_1px]";
const ARROW = "transition-transform duration-300 ease-[var(--ease-out-quart)] group-hover/tl:translate-x-2";
function isInternal(href: string) {
return href.startsWith("/");
}
/**
* Caps link with an arrow glyph. Internal routes go through the curtain
* (`TransitionLink`); mailto/tel/http are plain anchors.
*/
export function TextLink({ href, label, external = false, arrow, className }: TextLinkProps) {
const glyph = arrow ?? (external ? "↗" : href.startsWith("#") ? "↓" : "→");
const inner = (
<>
<span className={GROW_UNDERLINE}>{label}</span>
<span aria-hidden="true" className={ARROW}>
{glyph}
</span>
</>
);
const cls = cn(TEXT_LINK, className);
if (isInternal(href) && !external) {
return (
<TransitionLink href={href} label={label} className={cls}>
{inner}
</TransitionLink>
);
}
return (
<a
href={href}
target={external ? "_blank" : undefined}
rel={external ? "noopener noreferrer" : undefined}
className={cls}
>
{inner}
</a>
);
}
export default TextLink;