Create project?
Start with the default component set.
<script lang="ts">
import { PillButton } from "$lib/components/ui/button/index.js";
import ArrowRightIcon from "phosphor-svelte/lib/ArrowRightIcon";
</script>
<div
class="hairline-frame w-full max-w-xl border border-border bg-card p-5 text-card-foreground"
>
<div class="grid gap-5 sm:grid-cols-[1fr_auto] sm:items-end">
<div class="grid gap-2">
<h3 class="text-lg font-semibold">Create project?</h3>
<p class="max-w-md text-sm/6 text-muted-foreground">
Start with the default component set.
</p>
</div>
<div class="flex flex-wrap gap-2 sm:justify-end">
<PillButton href="/docs/installation">
Create project
<ArrowRightIcon data-icon="inline-end" />
</PillButton>
<PillButton href="/docs/components" variant="outline"
>View components</PillButton
>
</div>
</div>
</div> Installation
Install the button component.
pnpm dlx jsrepo@latest add buttonnpx jsrepo@latest add buttonyarn dlx jsrepo@latest add buttonbunx jsrepo@latest add buttonCopy and paste the following code into your project.
<script lang="ts" module>
import { cn, type WithElementRef } from '$lib/utils.js';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
import { type VariantProps, tv } from 'tailwind-variants';
export const buttonVariants = tv({
base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-control border border-transparent bg-clip-padding text-xs font-medium focus-visible:ring-1 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-1 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/90',
outline:
'border-border bg-background hover:bg-muted hover:text-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 aria-expanded:bg-muted aria-expanded:text-foreground',
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground',
ghost:
'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground',
destructive:
'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30',
link: 'rounded-control px-0 text-link underline underline-offset-4 hover:text-foreground'
},
size: {
default:
'h-8 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
xs: "h-6 gap-1 rounded-control px-2 text-xs has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
sm: "h-7 gap-1 rounded-control px-2.5 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3.5",
lg: 'h-9 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2',
icon: 'size-8',
'icon-xs': "size-6 rounded-control [&_svg:not([class*='size-'])]:size-3",
'icon-sm': 'size-7 rounded-control',
'icon-lg': 'size-9'
}
},
defaultVariants: {
variant: 'default',
size: 'default'
}
});
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
WithElementRef<HTMLAnchorAttributes> & {
variant?: ButtonVariant;
size?: ButtonSize;
};
</script>
<script lang="ts">
let {
class: className,
variant = 'default',
size = 'default',
ref = $bindable(null),
href = undefined,
type = 'button',
disabled,
children,
...restProps
}: ButtonProps = $props();
</script>
{#if href}
<a
bind:this={ref}
data-slot="button"
class={cn(buttonVariants({ variant, size }), className)}
href={disabled ? undefined : href}
aria-disabled={disabled}
role={disabled ? 'link' : undefined}
tabindex={disabled ? -1 : undefined}
{...restProps}
>
{@render children?.()}
</a>
{:else}
<button
bind:this={ref}
data-slot="button"
class={cn(buttonVariants({ variant, size }), className)}
{type}
{disabled}
{...restProps}
>
{@render children?.()}
</button>
{/if}
Usage
<script lang="ts">
import { PillButton } from '$lib/components/ui/button/index.js';
</script> <PillButton>Button</PillButton> Examples
Default
<script lang="ts">
import { PillButton } from "$lib/components/ui/button/index.js";
</script>
<PillButton>Button</PillButton> <PillButton>Button</PillButton> Outline
<script lang="ts">
import { PillButton } from "$lib/components/ui/button/index.js";
</script>
<PillButton href="/docs/components" variant="outline"
>View components</PillButton
> <PillButton href="/docs/components" variant="outline">View components</PillButton> With Icon
<script lang="ts">
import { PillButton } from "$lib/components/ui/button/index.js";
import ArrowRightIcon from "phosphor-svelte/lib/ArrowRightIcon";
</script>
<PillButton href="/docs/installation">
Continue
<ArrowRightIcon data-icon="inline-end" />
</PillButton> <PillButton href="/docs/installation">
Continue
<ArrowRightIcon data-icon="inline-end" />
</PillButton> Pair
Create project?
Start with the default component set.
<script lang="ts">
import { PillButton } from "$lib/components/ui/button/index.js";
import ArrowRightIcon from "phosphor-svelte/lib/ArrowRightIcon";
</script>
<div
class="hairline-frame grid max-w-sm gap-4 border border-border bg-card p-4 text-card-foreground"
>
<div class="grid gap-1">
<h3 class="text-base font-semibold">Create project?</h3>
<p class="text-sm/6 text-muted-foreground">
Start with the default component set.
</p>
</div>
<div class="flex flex-wrap justify-end gap-2">
<PillButton variant="outline">Review settings</PillButton>
<PillButton>
Create project
<ArrowRightIcon data-icon="inline-end" />
</PillButton>
</div>
</div> <div class="hairline-frame grid max-w-sm gap-4 border border-border bg-card p-4">
<div class="grid gap-1">
<h3 class="text-base font-semibold">Create project?</h3>
<p class="text-sm/6 text-muted-foreground">Start with the default component set.</p>
</div>
<div class="flex flex-wrap justify-end gap-2">
<PillButton variant="outline">Review settings</PillButton>
<PillButton>
Create project
<ArrowRightIcon data-icon="inline-end" />
</PillButton>
</div>
</div>