Skip to content

Commit

Permalink
component: Button
Browse files Browse the repository at this point in the history
  • Loading branch information
jeannemas committed Jun 4, 2024
1 parent c42d593 commit a926de0
Show file tree
Hide file tree
Showing 23 changed files with 136 additions and 83 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
<script context="module" lang="ts">
import { Button as ButtonPrimitive } from 'bits-ui';
import { writable } from 'svelte/store';
import { tv, type VariantProps } from 'tailwind-variants';
import type { ComponentInfo } from '$lib/utils/types.js';
import { rootContext } from './context.js';
type Primitive = ComponentInfo<ButtonPrimitive.Root>;
/**
Expand All @@ -30,20 +33,20 @@
/**
* The size of the button.
*/
export type Size = NonNullable<VariantProps<typeof buttonStyles>['size']>;
export type Size = NonNullable<VariantProps<typeof rootStyles>['size']>;
/**
* The slots of the button.
*/
export type Slots = Primitive['slots'];
/**
* The variant of the button.
*/
export type Variant = NonNullable<VariantProps<typeof buttonStyles>['variant']>;
export type Variant = NonNullable<VariantProps<typeof rootStyles>['variant']>;
/**
* The styles of the button.
*/
export const buttonStyles = tv({
export const rootStyles = tv({
base: [
'inline-flex flex-row items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
Expand Down Expand Up @@ -81,18 +84,58 @@
type $$Props = Attributes & Props;
type $$Slots = Slots;
export let size: Props['size'] = buttonStyles.defaultVariants.size;
export let variant: Props['variant'] = buttonStyles.defaultVariants.variant;
export let size: Props['size'] = rootStyles.defaultVariants.size;
export let variant: Props['variant'] = rootStyles.defaultVariants.variant;
$: attributes = $$restProps as Attributes;
const rootCtx = rootContext.set(writable());
$: rootCtx.update(($ctx) => ({
...$ctx,
size,
variant,
}));
</script>

<!-- <style lang="postcss">
</style> -->

<!--
@component
The root of a button component.
### Attributes
Accepts the attributes of a `button` element.
### Events
- `click`
- `keydown`
### Props
- `size` - The size of the button.
- `variant` - The variant of the button.
### Slots
- `default` - The default slot.
### Components hierarchy
```html
<Button.Root>
...
</Button.Root>
```
-->

<ButtonPrimitive.Root
{...attributes}
class="{buttonStyles({
class="{rootStyles({
class: attributes.class,
size,
variant,
Expand Down
7 changes: 7 additions & 0 deletions src/lib/components/button/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Writable } from 'svelte/store';

import { Context } from '$lib/utils/context.js';

import type { RootProps } from './index.js';

export const rootContext = new Context<Writable<Pick<RootProps, 'size' | 'variant'>>>();
12 changes: 6 additions & 6 deletions src/lib/components/button/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
export {
default,
buttonStyles,
type Attributes,
type Props,
default as Root,
rootStyles,
type Attributes as RootAttributes,
type Props as RootProps,
type Slots as RootSlots,
type Size,
type Slots,
type Variant,
} from './Button.svelte';
} from './ButtonRoot.svelte';
4 changes: 2 additions & 2 deletions src/lib/components/calendar/CalendarDay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { SvelteHTMLElements } from 'svelte/elements';
import { tv } from 'tailwind-variants';
import { buttonStyles } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import type { ComponentInfo } from '$lib/utils/types.js';
type Primitive = ComponentInfo<CalendarPrimitive.Day>;
Expand All @@ -26,7 +26,7 @@
*/
export const dayStyles = tv({
base: [
buttonStyles({ variant: 'ghost' }),
Button.rootStyles({ variant: 'ghost' }),
'size-8 p-0 font-normal ',
'[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground',
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/calendar/CalendarNextButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { SvelteHTMLElements } from 'svelte/elements';
import { tv } from 'tailwind-variants';
import { buttonStyles } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import type { ComponentInfo } from '$lib/utils/types.js';
type Primitive = ComponentInfo<CalendarPrimitive.NextButton>;
Expand All @@ -27,7 +27,7 @@
*/
export const nextButtonStyles = tv({
base: [
buttonStyles({ variant: 'outline' }),
Button.rootStyles({ variant: 'outline' }),
'size-8 bg-transparent p-0 opacity-50',
'hover:opacity-100',
Expand Down
4 changes: 2 additions & 2 deletions src/lib/components/calendar/CalendarPreviousButton.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { SvelteHTMLElements } from 'svelte/elements';
import { tv } from 'tailwind-variants';
import { buttonStyles } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import type { ComponentInfo } from '$lib/utils/types.js';
type Primitive = ComponentInfo<CalendarPrimitive.PrevButton>;
Expand All @@ -27,7 +27,7 @@
*/
export const previousButtonStyles = tv({
base: [
buttonStyles({ variant: 'outline' }),
Button.rootStyles({ variant: 'outline' }),
'size-8 bg-transparent p-0 opacity-50',
'hover:opacity-100',
Expand Down
10 changes: 5 additions & 5 deletions src/lib/components/pagination/PaginationLink.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import type { SvelteHTMLElements } from 'svelte/elements';
import { tv } from 'tailwind-variants';
import { buttonStyles, type Props as ButtonProps } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import type { ComponentInfo } from '$lib/utils/types.js';
type Primitive = ComponentInfo<PaginationPrimitive.Page>;
Expand All @@ -16,7 +16,7 @@
* The props of the link.
*/
export type Props = Omit<Primitive['props'], keyof Attributes> &
Omit<ButtonProps, 'variant'> & {
Omit<Button.RootProps, 'variant'> & {
isActive?: boolean;
};
/**
Expand All @@ -28,12 +28,12 @@
* The styles of the link.
*/
export const linkStyles = tv({
base: [...buttonStyles.base],
base: [...Button.rootStyles.base],
defaultVariants: {
...buttonStyles.defaultVariants,
...Button.rootStyles.defaultVariants,
},
variants: {
...buttonStyles.variants,
...Button.rootStyles.variants,
},
});
</script>
Expand Down
6 changes: 3 additions & 3 deletions src/lib/components/top-navigation/TopNavigationRoot.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import { writable } from 'svelte/store';
import { tv, type VariantProps } from 'tailwind-variants';
import Button from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import * as Collapsible from '$lib/components/collapsible/index.js';
import Container from '$lib/components/container/index.js';
import type { EmptyObject } from '$lib/utils/types.js';
Expand Down Expand Up @@ -143,13 +143,13 @@
bind:open="{open}"
>
<Collapsible.Trigger asChild let:builder>
<Button builders="{[builder]}" class="m-2" size="icon" type="button" variant="outline">
<Button.Root builders="{[builder]}" class="m-2" size="icon" type="button" variant="outline">
{#if open}
<XIcon />
{:else}
<AlignJustifyIcon />
{/if}
</Button>
</Button.Root>
</Collapsible.Trigger>

<Collapsible.Content class="flex flex-col justify-between pb-2">
Expand Down
10 changes: 5 additions & 5 deletions src/routes/alert-dialog/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import { zodClient } from 'sveltekit-superforms/adapters';
import * as AlertDialog from '$lib/components/alert-dialog/index.js';
import Button from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import * as Form from '$lib/components/form/index.js';
import * as Select from '$lib/components/select/index.js';
import * as Switch from '$lib/components/switch/index.js';
Expand Down Expand Up @@ -145,7 +145,7 @@
<svelte:fragment slot="demo">
<AlertDialog.Root {...$props} portal="{null}">
<AlertDialog.Trigger asChild let:builder>
<Button builders="{[builder]}" variant="outline">Show Dialog</Button>
<Button.Root builders="{[builder]}" variant="outline">Show Dialog</Button.Root>
</AlertDialog.Trigger>

<AlertDialog.Portal>
Expand All @@ -160,16 +160,16 @@
</AlertDialog.Description>

<AlertDialog.Action asChild let:builder>
<Button
<Button.Root
builders="{[builder]}"
variant="{$props.variant === 'danger' ? 'danger' : 'default'}"
>
Continue
</Button>
</Button.Root>
</AlertDialog.Action>

<AlertDialog.Cancel asChild let:builder>
<Button builders="{[builder]}" variant="ghost">Cancel</Button>
<Button.Root builders="{[builder]}" variant="ghost">Cancel</Button.Root>
</AlertDialog.Cancel>
</AlertDialog.Content>
</AlertDialog.Portal>
Expand Down
12 changes: 6 additions & 6 deletions src/routes/button/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { superForm } from 'sveltekit-superforms';
import { zodClient } from 'sveltekit-superforms/adapters';
import Button, { type Size, type Variant } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import * as Form from '$lib/components/form/index.js';
import * as Select from '$lib/components/select/index.js';
import * as Switch from '$lib/components/switch/index.js';
Expand All @@ -25,16 +25,16 @@
$: selectedSize = {
label: $props.size,
value: $props.size,
} satisfies Selected<Size>;
} satisfies Selected<Button.Size>;
$: selectedVariant = {
label: $props.variant,
value: $props.variant,
} satisfies Selected<Variant>;
} satisfies Selected<Button.Variant>;
function handleSizeChange(selected?: Selected<Size>) {
function handleSizeChange(selected?: Selected<Button.Size>) {
$props.size = selected!.value;
}
function handleVariantChange(selected?: Selected<Variant>) {
function handleVariantChange(selected?: Selected<Button.Variant>) {
$props.variant = selected!.value;
}
</script>
Expand Down Expand Up @@ -114,6 +114,6 @@
</svelte:fragment>

<svelte:fragment slot="demo">
<Button {...$props}>Lorem ipsum</Button>
<Button.Root {...$props}>Lorem ipsum</Button.Root>
</svelte:fragment>
</ComponentDemoLayout>
14 changes: 7 additions & 7 deletions src/routes/button/+page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Selected } from 'bits-ui';
import { superValidate } from 'sveltekit-superforms';
import { zod } from 'sveltekit-superforms/adapters';

import { buttonStyles, type Size, type Variant } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';

import type { PageLoad } from './$types.js';
import { schema } from './props.schema.js';
Expand All @@ -11,18 +11,18 @@ export const load = (async () => {
const form = await superValidate(zod(schema), {
defaults: {
disabled: false,
size: buttonStyles.defaultVariants.size!,
variant: buttonStyles.defaultVariants.variant!,
size: Button.rootStyles.defaultVariants.size!,
variant: Button.rootStyles.defaultVariants.variant!,
},
});
const sizes = Object.keys(buttonStyles.variants.size).map((size) => ({
const sizes = Object.keys(Button.rootStyles.variants.size).map((size) => ({
label: size,
value: size,
})) as Selected<Size>[];
const variants = Object.keys(buttonStyles.variants.variant).map((variant) => ({
})) as Selected<Button.Size>[];
const variants = Object.keys(Button.rootStyles.variants.variant).map((variant) => ({
label: variant,
value: variant,
})) as Selected<Variant>[];
})) as Selected<Button.Variant>[];

return {
form,
Expand Down
9 changes: 6 additions & 3 deletions src/routes/button/props.schema.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import z from 'zod';

import { buttonStyles, type Size, type Variant } from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';

const sizes = Object.keys(buttonStyles.variants.size) as [Size, ...Size[]];
const variants = Object.keys(buttonStyles.variants.variant) as [Variant, ...Variant[]];
const sizes = Object.keys(Button.rootStyles.variants.size) as [Button.Size, ...Button.Size[]];
const variants = Object.keys(Button.rootStyles.variants.variant) as [
Button.Variant,
...Button.Variant[],
];

export const schema = z.object({
disabled: z.boolean({
Expand Down
6 changes: 3 additions & 3 deletions src/routes/card/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { superForm } from 'sveltekit-superforms';
import { zodClient } from 'sveltekit-superforms/adapters';
import Button from '$lib/components/button/index.js';
import * as Button from '$lib/components/button/index.js';
import * as Card from '$lib/components/card/index.js';
import * as Form from '$lib/components/form/index.js';
import Input from '$lib/components/input/index.js';
Expand Down Expand Up @@ -82,9 +82,9 @@
</Card.Content>

<Card.Footer class="flex flex-row justify-between">
<Button variant="outline">Cancel</Button>
<Button.Root variant="outline">Cancel</Button.Root>

<Button>Deploy</Button>
<Button.Root>Deploy</Button.Root>
</Card.Footer>
</Card.Root>
</svelte:fragment>
Expand Down
Loading

0 comments on commit a926de0

Please sign in to comment.