Skip to content

Commit 2d28548

Browse files
committed
feat(ui): button variants style
1 parent 245f445 commit 2d28548

File tree

11 files changed

+244
-16
lines changed

11 files changed

+244
-16
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ A Turbo monorepo repository with Sveltekit.
3838
| `svelte` | ![v5.28.2](https://img.shields.io/badge/npm-v5.28.2-blue) |
3939
| `svelte-email-tailwind` | ![v2.1.1](https://img.shields.io/badge/npm-v2.1.1-blue) |
4040
| `tailwindcss` | ![v4.1.4](https://img.shields.io/badge/npm-v4.1.4-blue) |
41+
| `tailwind-variants` | ![v1.0.0](https://img.shields.io/badge/npm-v1.0.0-blue) |
4142
| `turbo` | ![v2.5.2](https://img.shields.io/badge/npm-v2.5.2-blue) |
4243
| `typesafe-i18n` | ![v5.26.2](https://img.shields.io/badge/npm-v5.26.2-blue) |
4344
| `typescript` | ![v5.8.3](https://img.shields.io/badge/npm-v5.8.3-blue) |

apps/docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"assets": "*",
2222
"bits-ui": "^1.3.19",
2323
"locale": "*",
24+
"tailwind-variants": "^1.0.0",
2425
"typesafe-i18n": "^5.26.2",
2526
"ui": "*",
2627
"utils": "*",

apps/web/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"locale": "*",
2727
"nodemailer": "^6.10.1",
2828
"svelte-email-tailwind": "^2.1.1",
29+
"tailwind-variants": "^1.0.0",
2930
"typesafe-i18n": "^5.26.2",
3031
"ui": "*",
3132
"utils": "*",

apps/web/src/routes/+page.svelte

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222

2323
<div class="flex flex-col items-center gap-2">
2424
<p>{$LL.counter({ count: counter.count })}</p>
25-
<Button onclick={() => counter.increment()}>{$LL.button()}</Button>
25+
<Button
26+
color="primary"
27+
onclick={() => counter.increment()}>{$LL.button()}</Button
28+
>
2629
</div>
2730
</div>

package-lock.json

Lines changed: 29 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"@internationalized/date": "^3.8.0",
4242
"bits-ui": "^1.3.19",
4343
"js-cookie": "^3.0.5",
44+
"tailwind-variants": "^1.0.0",
4445
"utils": "*"
4546
},
4647
"devDependencies": {

packages/ui/src/button/__snapshots__/button.spec.ts.snap

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3-
exports[`Button > should render component 1`] = `
3+
exports[`Button > should render default button 1`] = `
44
HTMLCollection [
55
<button
6-
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg bg-orange-600 px-4 py-2 text-sm font-semibold text-orange-50 shadow-md shadow-orange-500/75 transition hover:bg-orange-500 active:scale-98 "
6+
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98 bg-gray-200 text-gray-800 hover:bg-gray-100 shadow-gray-300/75 px-4 py-2 text-sm"
77
data-button-root="true"
88
tabindex="0"
99
>
@@ -15,6 +15,86 @@ HTMLCollection [
1515
1616
1717
18+
</button>,
19+
]
20+
`;
21+
22+
exports[`Button > should render large button 1`] = `
23+
HTMLCollection [
24+
<button
25+
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98 bg-gray-200 text-gray-800 hover:bg-gray-100 shadow-gray-300/75 px-5 py-3 text-base"
26+
data-button-root="true"
27+
size="large"
28+
tabindex="0"
29+
>
30+
<!---->
31+
<!---->
32+
<span>
33+
Button
34+
</span>
35+
36+
37+
38+
</button>,
39+
]
40+
`;
41+
42+
exports[`Button > should render medium button 1`] = `
43+
HTMLCollection [
44+
<button
45+
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98 bg-gray-200 text-gray-800 hover:bg-gray-100 shadow-gray-300/75 px-4 py-2 text-sm"
46+
data-button-root="true"
47+
size="medium"
48+
tabindex="0"
49+
>
50+
<!---->
51+
<!---->
52+
<span>
53+
Button
54+
</span>
55+
56+
57+
58+
</button>,
59+
]
60+
`;
61+
62+
exports[`Button > should render primary button 1`] = `
63+
HTMLCollection [
64+
<button
65+
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98 bg-orange-600 text-orange-50 hover:bg-orange-500 shadow-orange-500/75 px-4 py-2 text-sm"
66+
color="primary"
67+
data-button-root="true"
68+
tabindex="0"
69+
>
70+
<!---->
71+
<!---->
72+
<span>
73+
Button
74+
</span>
75+
76+
77+
78+
</button>,
79+
]
80+
`;
81+
82+
exports[`Button > should render small button 1`] = `
83+
HTMLCollection [
84+
<button
85+
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98 bg-gray-200 text-gray-800 hover:bg-gray-100 shadow-gray-300/75 px-3 py-1.5 text-xs"
86+
data-button-root="true"
87+
size="small"
88+
tabindex="0"
89+
>
90+
<!---->
91+
<!---->
92+
<span>
93+
Button
94+
</span>
95+
96+
97+
1898
</button>,
1999
]
20100
`;

packages/ui/src/button/button.spec.ts

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,49 @@ import { createRawSnippet } from "svelte";
55
import { describe, expect, test, vi } from "vitest";
66

77
describe("Button", () => {
8-
test("should render component", async () => {
8+
const children = createRawSnippet(() => ({
9+
render: () => `<span>Button</span>`,
10+
}));
11+
12+
test("should render default button", async () => {
13+
const { container } = render(Button, {
14+
children,
15+
});
16+
17+
expect(container.children).toMatchSnapshot();
18+
});
19+
20+
test("should render primary button", async () => {
21+
const { container } = render(Button, {
22+
children,
23+
color: "primary",
24+
});
25+
26+
expect(container.children).toMatchSnapshot();
27+
});
28+
29+
test("should render small button", async () => {
30+
const { container } = render(Button, {
31+
children,
32+
size: "small",
33+
});
34+
35+
expect(container.children).toMatchSnapshot();
36+
});
37+
38+
test("should render medium button", async () => {
39+
const { container } = render(Button, {
40+
children,
41+
size: "medium",
42+
});
43+
44+
expect(container.children).toMatchSnapshot();
45+
});
46+
47+
test("should render large button", async () => {
948
const { container } = render(Button, {
10-
children: createRawSnippet(() => ({
11-
render: () => `<span>Button</span>`,
12-
})),
49+
children,
50+
size: "large",
1351
});
1452

1553
expect(container.children).toMatchSnapshot();
@@ -19,9 +57,7 @@ describe("Button", () => {
1957
const onclick = vi.fn();
2058

2159
render(Button, {
22-
children: createRawSnippet(() => ({
23-
render: () => `<span>Button</span>`,
24-
})),
60+
children,
2561
onclick,
2662
});
2763

packages/ui/src/button/button.stories.svelte

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,27 @@
1010
const { Story } = defineMeta({
1111
title: "UI/Button",
1212
component: Button,
13+
parameters: {
14+
docs: {
15+
description: {
16+
component: "Extending Bits UI Button Component",
17+
},
18+
},
19+
},
1320
tags: ["autodocs"],
14-
argTypes: {},
21+
argTypes: {
22+
color: {
23+
control: { type: "select" },
24+
options: ["default", "primary"],
25+
},
26+
size: {
27+
control: { type: "select" },
28+
options: ["small", "medium", "large"],
29+
},
30+
},
1531
args: {
32+
color: "default",
33+
size: "medium",
1634
children: createRawSnippet(() => ({
1735
render: () => "Click me",
1836
})),
@@ -21,5 +39,32 @@
2139
});
2240
</script>
2341

24-
<!-- Extending Bits UI Button Component -->
2542
<Story name="Default" />
43+
44+
<Story
45+
name="Primary"
46+
args={{
47+
color: "primary",
48+
}}
49+
/>
50+
51+
<Story
52+
name="Small"
53+
args={{
54+
size: "small",
55+
}}
56+
/>
57+
58+
<Story
59+
name="Medium"
60+
args={{
61+
size: "medium",
62+
}}
63+
/>
64+
65+
<Story
66+
name="Large"
67+
args={{
68+
size: "large",
69+
}}
70+
/>

packages/ui/src/button/button.svelte

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,45 @@
1+
<script
2+
module
3+
lang="ts"
4+
>
5+
import { type VariantProps, tv } from "tailwind-variants";
6+
7+
export const button = tv({
8+
base: "inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg font-semibold shadow-md transition active:scale-98",
9+
variants: {
10+
color: {
11+
default: "bg-gray-200 text-gray-800 hover:bg-gray-100 shadow-gray-300/75",
12+
primary: "bg-orange-600 text-orange-50 hover:bg-orange-500 shadow-orange-500/75",
13+
},
14+
size: {
15+
small: "px-3 py-1.5 text-xs",
16+
medium: "px-4 py-2 text-sm",
17+
large: "px-5 py-3 text-base",
18+
},
19+
},
20+
defaultVariants: {
21+
color: "default",
22+
size: "medium",
23+
},
24+
});
25+
26+
export type ButtonVariant = VariantProps<typeof button>;
27+
</script>
28+
129
<script lang="ts">
230
import { Button, type ButtonRootProps } from "bits-ui";
331
import type { Snippet } from "svelte";
32+
import type { ClassValue } from "tailwind-variants";
433
5-
const { children, ...props }: ButtonRootProps & { children: Snippet } = $props();
34+
const {
35+
children,
36+
...props
37+
}: ButtonRootProps & ButtonVariant & { class?: ClassValue; children: Snippet } = $props();
638
</script>
739

840
<Button.Root
941
{...props}
10-
class="inline-flex min-h-10 cursor-pointer items-center justify-center rounded-lg bg-orange-600 px-4 py-2 text-sm font-semibold text-orange-50 shadow-md shadow-orange-500/75 transition hover:bg-orange-500 active:scale-98 {props.class}"
42+
class={button(props)}
1143
>
1244
{@render children()}
1345
</Button.Root>

0 commit comments

Comments
 (0)