<script module lang="ts">
import { tv, type VariantProps } from "tailwind-variants";
const link = tv({
base: "inline-flex cursor-pointer items-center gap-2xs no-underline select-none hover:underline focus-visible:outline-2 focus-visible:outline-offset-2",
variants: {
variant: {
default:
"text-foreground-link-default hover:text-foreground-link-hover focus-visible:outline-border-focus",
success:
"text-foreground-link-success hover:text-foreground-link-success-hover focus-visible:outline-foreground-link-success",
warning:
"text-foreground-link-warning hover:text-foreground-link-warning-hover focus-visible:outline-foreground-link-warning",
danger: "text-foreground-link-danger hover:text-foreground-link-danger-hover focus-visible:outline-foreground-link-danger",
inherit: "text-inherit focus-visible:outline-border-focus"
},
size: {
regular: "",
small: "typography-paragraph-small"
},
disabled: {
true: "pointer-events-none opacity-50",
false: ""
}
},
defaultVariants: {
variant: "default",
size: "regular",
disabled: false
}
});
export type LinkVariants = VariantProps<typeof link>;
</script>
<script lang="ts">
import type { ResolvedPathname } from "$app/types";
import type { Component, Snippet } from "svelte";
import type {
HTMLAnchorAttributes,
HTMLButtonAttributes,
SvelteHTMLElements
} from "svelte/elements";
interface Props extends Omit<
HTMLAnchorAttributes & HTMLButtonAttributes,
"class" | "children"
> {
variant?: LinkVariants["variant"];
size?: LinkVariants["size"];
href?: ResolvedPathname;
fragment?: string;
type?: "button" | "submit" | "reset";
disabled?: boolean;
iconLeft?: Component<SvelteHTMLElements["svg"]>;
iconRight?: Component<SvelteHTMLElements["svg"]>;
class?: string;
children?: Snippet;
}
let {
variant = "default",
size = "regular",
href,
fragment,
type = "button",
disabled = false,
iconLeft,
iconRight,
class: className,
children,
...rest
}: Props = $props();
const classes = $derived(link({ variant, size, disabled, class: className }));
const iconSize = "size-3.5";
</script>
{#if href || fragment !== undefined}
<a
href={fragment === undefined ? href : `#${fragment}`}
class={classes}
aria-disabled={disabled ? "true" : undefined}
tabindex={disabled ? -1 : undefined}
{...rest}
>
{#if iconLeft}
{@const IconLeft = iconLeft}
<IconLeft class={iconSize} aria-hidden="true" />
{/if}
{#if children}
{@render children()}
{/if}
{#if iconRight}
{@const IconRight = iconRight}
<IconRight class={iconSize} aria-hidden="true" />
{/if}
</a>
{:else}
<button {type} {disabled} class={classes} {...rest}>
{#if iconLeft}
{@const IconLeft = iconLeft}
<IconLeft class={iconSize} aria-hidden="true" />
{/if}
{#if children}
{@render children()}
{/if}
{#if iconRight}
{@const IconRight = iconRight}
<IconRight class={iconSize} aria-hidden="true" />
{/if}
</button>
{/if}