Breadcrumb && Link added new Components
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
---
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
interface BreadcrumbItem {
|
||||
name: string;
|
||||
icon?: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
const { items, separator = "/" } = Astro.props as {
|
||||
items: BreadcrumbItem[];
|
||||
separator?: string;
|
||||
};
|
||||
---
|
||||
|
||||
<nav
|
||||
aria-label="Breadcrumb"
|
||||
class="wr:flex wr:items-center wr:gap-2 wr:text-sm wr:text-gray-600"
|
||||
>
|
||||
{
|
||||
items.map((item, index) => (
|
||||
<span class="wr:flex wr:items-center wr:gap-3">
|
||||
{index !== 0 && (
|
||||
<span class="wr:text-gray-400">{separator}</span>
|
||||
)}
|
||||
|
||||
{index === items.length - 1 || !item.url ? (
|
||||
<span class="wr:flex wr:items-center wr:gap-2 wr:font-medium wr:text-gray-900 wr:dark:text-white">
|
||||
{item.icon && (
|
||||
<Icon name={item.icon} class={`wr:size-4`} />
|
||||
)}
|
||||
{item.name}
|
||||
</span>
|
||||
) : (
|
||||
<a
|
||||
href={item.url}
|
||||
class="wr:flex wr:items-center wr:gap-2 wr:text-gray-800 wr:dark:text-gray-200 wr:hover:underline wr:hover:text-blue-600 wr:hover:dark:text-blue-400"
|
||||
>
|
||||
{item.icon && (
|
||||
<Icon name={item.icon} class={`wr:size-4`} />
|
||||
)}
|
||||
{item.name}
|
||||
</a>
|
||||
)}
|
||||
</span>
|
||||
))
|
||||
}
|
||||
</nav>
|
||||
@@ -0,0 +1,140 @@
|
||||
---
|
||||
import type { HTMLAttributes } from "astro/types";
|
||||
import { cn } from "../utils/cn";
|
||||
import { Icon } from "astro-icon/components";
|
||||
|
||||
type Variant = "solid" | "outline" | "ghost" | "soft" | "link";
|
||||
type Color =
|
||||
| "primary"
|
||||
| "secondary"
|
||||
| "tertiary"
|
||||
| "accent"
|
||||
| "info"
|
||||
| "success"
|
||||
| "warning"
|
||||
| "danger"
|
||||
| "neutral";
|
||||
type Size = "sm" | "md" | "lg" | "icon";
|
||||
|
||||
interface Props extends HTMLAttributes<"a"> {
|
||||
variant?: Variant;
|
||||
color?: Color;
|
||||
size?: Size;
|
||||
pill?: boolean;
|
||||
icon?: string;
|
||||
}
|
||||
|
||||
const {
|
||||
variant = "solid",
|
||||
color = "primary",
|
||||
size = "md",
|
||||
pill = false,
|
||||
icon = "",
|
||||
class: className,
|
||||
href = "#",
|
||||
...rest
|
||||
}: Props = Astro.props;
|
||||
|
||||
const base =
|
||||
"wr:inline-flex wr:items-center wr:justify-center wr:gap-2 wr:font-medium wr:transition-colors " +
|
||||
"wr:focus-visible:outline-none wr:focus-visible:ring-2 wr:focus-visible:ring-offset-2 " +
|
||||
"wr:disabled:opacity-50 wr:disabled:pointer-events-none";
|
||||
|
||||
const sizeClass: Record<Size, string> = {
|
||||
sm: "wr:h-8 wr:px-3 wr:text-sm",
|
||||
md: "wr:h-10 wr:px-4 wr:text-sm",
|
||||
lg: "wr:h-11 wr:px-5 wr:text-base",
|
||||
icon: "wr:h-10 wr:w-10 wr:p-0",
|
||||
};
|
||||
|
||||
const radius = pill ? "wr:rounded-full" : "wr:rounded-md";
|
||||
|
||||
const styles: Record<Color, Record<Variant, string>> = {
|
||||
primary: {
|
||||
solid: "wr:bg-primary wr:text-primary-foreground wr:hover:bg-primary/90 wr:border wr:border-transparent wr:focus-visible:ring-primary/40",
|
||||
outline:
|
||||
"wr:border wr:border-primary wr:text-primary wr:hover:bg-primary/10 wr:focus-visible:ring-primary/40",
|
||||
ghost: "wr:text-primary wr:hover:bg-primary/10 wr:border wr:border-transparent wr:focus-visible:ring-primary/30",
|
||||
soft: "wr:bg-primary/15 wr:text-primary wr:hover:bg-primary/20 wr:border wr:border-transparent wr:focus-visible:ring-primary/30",
|
||||
link: "wr:text-primary wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-primary/40",
|
||||
},
|
||||
secondary: {
|
||||
solid: "wr:bg-secondary wr:text-secondary-foreground wr:hover:bg-secondary/90 wr:border wr:border-transparent wr:focus-visible:ring-secondary/40",
|
||||
outline:
|
||||
"wr:border wr:border-secondary wr:text-secondary wr:hover:bg-secondary/10 wr:focus-visible:ring-secondary/40",
|
||||
ghost: "wr:text-secondary wr:hover:bg-secondary/10 wr:border wr:border-transparent wr:focus-visible:ring-secondary/30",
|
||||
soft: "wr:bg-secondary/15 wr:text-secondary wr:hover:bg-secondary/20 wr:border wr:border-transparent wr:focus-visible:ring-secondary/30",
|
||||
link: "wr:text-secondary wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-secondary/40",
|
||||
},
|
||||
tertiary: {
|
||||
solid: "wr:bg-tertiary wr:text-tertiary-foreground wr:hover:bg-tertiary/90 wr:border wr:border-transparent wr:focus-visible:ring-tertiary/40",
|
||||
outline:
|
||||
"wr:border wr:border-tertiary wr:text-tertiary wr:hover:bg-tertiary/10 wr:focus-visible:ring-tertiary/40",
|
||||
ghost: "wr:text-tertiary wr:hover:bg-tertiary/10 wr:border wr:border-transparent wr:focus-visible:ring-tertiary/30",
|
||||
soft: "wr:bg-tertiary/15 wr:text-tertiary wr:hover:bg-tertiary/20 wr:border wr:border-transparent wr:focus-visible:ring-tertiary/30",
|
||||
link: "wr:text-tertiary wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-tertiary/40",
|
||||
},
|
||||
accent: {
|
||||
solid: "wr:bg-accent wr:text-accent-foreground wr:hover:bg-accent/90 wr:border wr:border-transparent wr:focus-visible:ring-accent/40",
|
||||
outline:
|
||||
"wr:border wr:border-accent wr:text-accent wr:hover:bg-accent/10 wr:focus-visible:ring-accent/40",
|
||||
ghost: "wr:text-accent wr:hover:bg-accent/10 wr:border wr:border-transparent wr:focus-visible:ring-accent/30",
|
||||
soft: "wr:bg-accent/15 wr:text-accent wr:hover:bg-accent/20 wr:border wr:border-transparent wr:focus-visible:ring-accent/30",
|
||||
link: "wr:text-accent wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-accent/40",
|
||||
},
|
||||
info: {
|
||||
solid: "wr:bg-info wr:text-info-foreground wr:hover:bg-info/90 wr:border wr:border-transparent wr:focus-visible:ring-info/40",
|
||||
outline:
|
||||
"wr:border wr:border-info wr:text-info wr:hover:bg-info/10 wr:focus-visible:ring-info/40",
|
||||
ghost: "wr:text-info wr:hover:bg-info/10 wr:border wr:border-transparent wr:focus-visible:ring-info/30",
|
||||
soft: "wr:bg-info/15 wr:text-info wr:hover:bg-info/20 wr:border wr:border-transparent wr:focus-visible:ring-info/30",
|
||||
link: "wr:text-info wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-info/40",
|
||||
},
|
||||
success: {
|
||||
solid: "wr:bg-success wr:text-success-foreground wr:hover:bg-success/90 wr:border wr:border-transparent wr:focus-visible:ring-success/40",
|
||||
outline:
|
||||
"wr:border wr:border-success wr:text-success wr:hover:bg-success/10 wr:focus-visible:ring-success/40",
|
||||
ghost: "wr:text-success wr:hover:bg-success/10 wr:border wr:border-transparent wr:focus-visible:ring-success/30",
|
||||
soft: "wr:bg-success/15 wr:text-success wr:hover:bg-success/20 wr:border wr:border-transparent wr:focus-visible:ring-success/30",
|
||||
link: "wr:text-success wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-success/40",
|
||||
},
|
||||
warning: {
|
||||
solid: "wr:bg-warning wr:text-warning-foreground wr:hover:bg-warning/90 wr:border wr:border-transparent wr:focus-visible:ring-warning/40",
|
||||
outline:
|
||||
"wr:border wr:border-warning wr:text-warning wr:hover:bg-warning/10 wr:focus-visible:ring-warning/40",
|
||||
ghost: "wr:text-warning wr:hover:bg-warning/10 wr:border wr:border-transparent wr:focus-visible:ring-warning/30",
|
||||
soft: "wr:bg-warning/14 wr:text-warning wr:hover:bg-warning/20 wr:border wr:border-transparent wr:focus-visible:ring-warning/30",
|
||||
link: "wr:text-warning wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-warning/40",
|
||||
},
|
||||
danger: {
|
||||
solid: "wr:bg-danger wr:text-danger-foreground wr:hover:bg-danger/90 wr:border wr:border-transparent wr:focus-visible:ring-danger/40",
|
||||
outline:
|
||||
"wr:border wr:border-danger wr:text-danger wr:hover:bg-danger/10 wr:focus-visible:ring-danger/40",
|
||||
ghost: "wr:text-danger wr:hover:bg-danger/10 wr:border wr:border-transparent wr:focus-visible:ring-danger/30",
|
||||
soft: "wr:bg-danger/15 wr:text-danger wr:hover:bg-danger/20 wr:border wr:border-transparent wr:focus-visible:ring-danger/30",
|
||||
link: "wr:text-danger wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-danger/40",
|
||||
},
|
||||
neutral: {
|
||||
solid: "wr:bg-neutral wr:text-neutral-foreground wr:hover:bg-neutral/90 wr:border wr:border-transparent wr:focus-visible:ring-neutral/40",
|
||||
outline:
|
||||
"wr:border wr:border-neutral wr:text-neutral wr:hover:bg-neutral/10 wr:focus-visible:ring-neutral/40",
|
||||
ghost: "wr:text-neutral wr:hover:bg-neutral/10 wr:border wr:border-transparent wr:focus-visible:ring-neutral/30",
|
||||
soft: "wr:bg-neutral/15 wr:text-neutral wr:hover:bg-neutral/20 wr:border wr:border-transparent wr:focus-visible:ring-neutral/30",
|
||||
link: "wr:text-neutral wr:underline wr:underline-offset-4 wr:p-0 wr:h-auto wr:border-0 wr:focus-visible:ring-neutral/40",
|
||||
},
|
||||
};
|
||||
|
||||
const variantColor = styles[color][variant];
|
||||
const sizeKls = variant === "link" ? "" : sizeClass[size];
|
||||
const iconSize =
|
||||
size === "sm" ? "wr:size-4" : size === "lg" ? "wr:size-5" : "wr:size-5";
|
||||
---
|
||||
|
||||
<a
|
||||
href={href}
|
||||
class={cn(base, radius, sizeKls, variantColor, className)}
|
||||
{...rest}
|
||||
>
|
||||
{icon && <Icon name={icon} class={cn(iconSize, "wr:shrink-0")} />}
|
||||
<slot />
|
||||
</a>
|
||||
Reference in New Issue
Block a user