Skip to content

Commit 6e7c336

Browse files
committed
feat: add variants to gradientbutton
1 parent b4d34a5 commit 6e7c336

File tree

18 files changed

+294
-291
lines changed

18 files changed

+294
-291
lines changed

.changeset/funny-cats-eat.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte-5-ui-lib': patch
3+
---
4+
5+
feat: variants to gradientbutton

src/lib/buttons/GradientButton.svelte

Lines changed: 9 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,68 +1,25 @@
11
<script lang="ts">
2-
import { twMerge } from 'tailwind-merge';
32
import Button from './Button.svelte';
4-
import { getContext } from 'svelte';
5-
import { type GradientButtonProps as Props } from '.';
3+
// import { getContext } from 'svelte';
4+
import { type GradientButtonProps as Props, gradientButton } from '.';
65
7-
const group = getContext('group');
6+
// const group = getContext('group');
87
9-
let { children, outline, pill, color = 'blue', shadow, class: className, onclick, href, target, rel, type, disabled, name, ...restProps }: Props = $props();
8+
let { children, outline, pill, color = 'blue', shadow, class: className, href, target, rel, type, disabled, name, ...restProps }: Props = $props();
109
11-
const gradientClasses = {
12-
blue: 'text-white bg-gradient-to-r from-blue-500 via-blue-600 to-blue-700 hover:bg-gradient-to-br focus:ring-blue-300 dark:focus:ring-blue-800 ',
13-
green: 'text-white bg-gradient-to-r from-green-400 via-green-500 to-green-600 hover:bg-gradient-to-br focus:ring-green-300 dark:focus:ring-green-800',
14-
cyan: 'text-white bg-gradient-to-r from-cyan-400 via-cyan-500 to-cyan-600 hover:bg-gradient-to-br focus:ring-cyan-300 dark:focus:ring-cyan-800',
15-
teal: 'text-white bg-gradient-to-r from-teal-400 via-teal-500 to-teal-600 hover:bg-gradient-to-br focus:ring-teal-300 dark:focus:ring-teal-800',
16-
lime: 'text-gray-900 bg-gradient-to-r from-lime-200 via-lime-400 to-lime-500 hover:bg-gradient-to-br focus:ring-lime-300 dark:focus:ring-lime-800',
17-
red: 'text-white bg-gradient-to-r from-red-400 via-red-500 to-red-600 hover:bg-gradient-to-br focus:ring-red-300 dark:focus:ring-red-800',
18-
pink: 'text-white bg-gradient-to-r from-pink-400 via-pink-500 to-pink-600 hover:bg-gradient-to-br focus:ring-pink-300 dark:focus:ring-pink-800',
19-
purple: 'text-white bg-gradient-to-r from-purple-500 via-purple-600 to-purple-700 hover:bg-gradient-to-br focus:ring-purple-300 dark:focus:ring-purple-800',
20-
purpleToBlue: 'text-white bg-gradient-to-br from-purple-600 to-blue-500 hover:bg-gradient-to-bl focus:ring-blue-300 dark:focus:ring-blue-800',
21-
cyanToBlue: 'text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-cyan-300 dark:focus:ring-cyan-800',
22-
greenToBlue: 'text-white bg-gradient-to-br from-green-400 to-blue-600 hover:bg-gradient-to-bl focus:ring-green-200 dark:focus:ring-green-800',
23-
purpleToPink: 'text-white bg-gradient-to-r from-purple-500 to-pink-500 hover:bg-gradient-to-l focus:ring-purple-200 dark:focus:ring-purple-800',
24-
pinkToOrange: 'text-white bg-gradient-to-br from-pink-500 to-orange-400 hover:bg-gradient-to-bl focus:ring-pink-200 dark:focus:ring-pink-800',
25-
tealToLime: 'text-gray-900 bg-gradient-to-r from-teal-200 to-lime-200 hover:bg-gradient-to-l focus:ring-lime-200 dark:focus:ring-teal-700',
26-
redToYellow: 'text-gray-900 bg-gradient-to-r from-red-200 via-red-300 to-yellow-200 hover:bg-gradient-to-bl focus:ring-red-100 dark:focus:ring-red-400'
27-
};
10+
const disabledValue = disabled !== null ? disabled : undefined;
2811
29-
const coloredShadowClasses = {
30-
blue: 'shadow-blue-500/50 dark:shadow-blue-800/80',
31-
green: 'shadow-green-500/50 dark:shadow-green-800/80',
32-
cyan: 'shadow-cyan-500/50 dark:shadow-cyan-800/80',
33-
teal: 'shadow-teal-500/50 dark:shadow-teal-800/80 ',
34-
lime: 'shadow-lime-500/50 dark:shadow-lime-800/80',
35-
red: 'shadow-red-500/50 dark:shadow-red-800/80 ',
36-
pink: 'shadow-pink-500/50 dark:shadow-pink-800/80',
37-
purple: 'shadow-purple-500/50 dark:shadow-purple-800/80',
38-
purpleToBlue: 'shadow-blue-500/50 dark:shadow-blue-800/80',
39-
cyanToBlue: 'shadow-cyan-500/50 dark:shadow-cyan-800/80',
40-
greenToBlue: 'shadow-green-500/50 dark:shadow-green-800/80',
41-
purpleToPink: 'shadow-purple-500/50 dark:shadow-purple-800/80',
42-
pinkToOrange: 'shadow-pink-500/50 dark:shadow-pink-800/80',
43-
tealToLime: 'shadow-lime-500/50 dark:shadow-teal-800/80',
44-
redToYellow: 'shadow-red-500/50 dark:shadow-red-800/80'
45-
};
46-
47-
let gradientOutlineClass: string = twMerge(
48-
'inline-flex items-center justify-center w-full !border-0',
49-
pill ? 'rounded-full' : '!rounded-md',
50-
'bg-white !text-gray-900 dark:bg-gray-900 dark:!text-white', // this is limitation - no transparency
51-
'hover:bg-transparent hover:!text-inherit',
52-
'transition-all duration-75 ease-in group-hover:!bg-opacity-0 group-hover:!text-inherit'
53-
);
54-
55-
let divClass: string = twMerge(outline && 'p-0.5', gradientClasses[color], shadow && 'shadow-lg', shadow && coloredShadowClasses[color], group ? (pill && 'first:rounded-s-full last:rounded-e-full') || 'first:rounded-s-lg last:rounded-e-lg' : (pill && 'rounded-full') || 'rounded-lg', className);
12+
const { base, outlineWrapper } = $derived(gradientButton({ color, outline, pill, shadow, disabled: disabledValue }));
5613
</script>
5714

5815
{#if outline}
59-
<div class={divClass}>
60-
<Button {...restProps} color="none" class={gradientOutlineClass} {onclick} {disabled} {name} {type} {href} {target} {rel}>
16+
<div class={base({ className })}>
17+
<Button {...restProps} color="none" class={outlineWrapper()} {disabled} {name} {type} {href} {target} {rel}>
6118
{@render children()}
6219
</Button>
6320
</div>
6421
{:else}
65-
<Button {...restProps} color="none" class={divClass} {onclick} {disabled} {name} {type} {href} {target} {rel}>
22+
<Button {...restProps} color="none" class={base({ className })} {disabled} {name} {type} {href} {target} {rel}>
6623
{@render children()}
6724
</Button>
6825
{/if}

src/lib/buttons/index.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import Button from './Button.svelte';
22
import GradientButton from './GradientButton.svelte';
3+
import { type VariantProps } from 'tailwind-variants';
34
import type { Snippet } from 'svelte';
45
import type { HTMLButtonAttributes, HTMLAnchorAttributes } from 'svelte/elements';
6+
import { gradientButton } from './theme';
7+
8+
type ColorType = VariantProps<typeof gradientButton>['color'];
59

610
interface GradientButtonProps {
711
children: Snippet;
8-
color?: keyof typeof gradientClasses;
12+
color?: ColorType;
913
shadow?: boolean;
1014
outline?: boolean;
1115
pill?: boolean;
1216
class?: string | undefined | null;
13-
onclick?: () => void;
1417
href?: HTMLAnchorAttributes['href'];
1518
target?: HTMLAnchorAttributes['target'];
1619
rel?: HTMLAnchorAttributes['rel'];
@@ -19,4 +22,4 @@ interface GradientButtonProps {
1922
name?: HTMLButtonAttributes['name'];
2023
}
2124

22-
export { Button, GradientButton, type GradientButtonProps };
25+
export { Button, GradientButton, gradientButton, type GradientButtonProps };

src/lib/buttons/theme.ts

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { tv } from 'tailwind-variants';
2+
3+
const coloredShadowClasses = {
4+
blue: 'shadow-blue-500/50 dark:shadow-blue-800/80',
5+
green: 'shadow-green-500/50 dark:shadow-green-800/80',
6+
cyan: 'shadow-cyan-500/50 dark:shadow-cyan-800/80',
7+
teal: 'shadow-teal-500/50 dark:shadow-teal-800/80',
8+
lime: 'shadow-lime-500/50 dark:shadow-lime-800/80',
9+
red: 'shadow-red-500/50 dark:shadow-red-800/80',
10+
pink: 'shadow-pink-500/50 dark:shadow-pink-800/80',
11+
purple: 'shadow-purple-500/50 dark:shadow-purple-800/80',
12+
purpleToBlue: 'shadow-blue-500/50 dark:shadow-blue-800/80',
13+
cyanToBlue: 'shadow-cyan-500/50 dark:shadow-cyan-800/80',
14+
greenToBlue: 'shadow-green-500/50 dark:shadow-green-800/80',
15+
purpleToPink: 'shadow-purple-500/50 dark:shadow-purple-800/80',
16+
pinkToOrange: 'shadow-pink-500/50 dark:shadow-pink-800/80',
17+
tealToLime: 'shadow-lime-500/50 dark:shadow-teal-800/80',
18+
redToYellow: 'shadow-red-500/50 dark:shadow-red-800/80'
19+
};
20+
21+
export const gradientButton = tv({
22+
slots: {
23+
base: 'inline-flex items-center justify-center transition-all duration-75 ease-in text-white bg-gradient-to-r ',
24+
outlineWrapper: 'inline-flex items-center justify-center w-full !border-0',
25+
},
26+
variants: {
27+
color: {
28+
blue: {
29+
base: 'from-blue-500 via-blue-600 to-blue-700 hover:bg-gradient-to-br focus:ring-blue-300 dark:focus:ring-blue-800',
30+
},
31+
green: {
32+
base: 'from-green-400 via-green-500 to-green-600 hover:bg-gradient-to-br focus:ring-green-300 dark:focus:ring-green-800',
33+
},
34+
cyan: { base: 'text-white bg-gradient-to-r from-cyan-400 via-cyan-500 to-cyan-600 hover:bg-gradient-to-br focus:ring-cyan-300 dark:focus:ring-cyan-800' },
35+
teal: { base: 'text-white bg-gradient-to-r from-teal-400 via-teal-500 to-teal-600 hover:bg-gradient-to-br focus:ring-teal-300 dark:focus:ring-teal-800'},
36+
lime: { base: 'text-gray-900 bg-gradient-to-r from-lime-200 via-lime-400 to-lime-500 hover:bg-gradient-to-br focus:ring-lime-300 dark:focus:ring-lime-800'},
37+
red:{ base: 'text-white bg-gradient-to-r from-red-400 via-red-500 to-red-600 hover:bg-gradient-to-br focus:ring-red-300 dark:focus:ring-red-800'},
38+
pink: { base: 'text-white bg-gradient-to-r from-pink-400 via-pink-500 to-pink-600 hover:bg-gradient-to-br focus:ring-pink-300 dark:focus:ring-pink-800'},
39+
purple:{ base: 'text-white bg-gradient-to-r from-purple-500 via-purple-600 to-purple-700 hover:bg-gradient-to-br focus:ring-purple-300 dark:focus:ring-purple-800'},
40+
purpleToBlue: { base: 'text-white bg-gradient-to-br from-purple-600 to-blue-500 hover:bg-gradient-to-bl focus:ring-blue-300 dark:focus:ring-blue-800'},
41+
cyanToBlue: { base: 'text-white bg-gradient-to-r from-cyan-500 to-blue-500 hover:bg-gradient-to-bl focus:ring-cyan-300 dark:focus:ring-cyan-800'},
42+
greenToBlue: { base: 'text-white bg-gradient-to-br from-green-400 to-blue-600 hover:bg-gradient-to-bl focus:ring-green-200 dark:focus:ring-green-800'},
43+
purpleToPink: { base: 'text-white bg-gradient-to-r from-purple-500 to-pink-500 hover:bg-gradient-to-l focus:ring-purple-200 dark:focus:ring-purple-800'},
44+
pinkToOrange: { base: 'text-white bg-gradient-to-br from-pink-500 to-orange-400 hover:bg-gradient-to-bl focus:ring-pink-200 dark:focus:ring-pink-800'},
45+
tealToLime: { base: 'text-gray-900 bg-gradient-to-r from-teal-200 to-lime-200 hover:bg-gradient-to-l focus:ring-lime-200 dark:focus:ring-teal-700'},
46+
redToYellow: { base: 'text-gray-900 bg-gradient-to-r from-red-200 via-red-300 to-yellow-200 hover:bg-gradient-to-bl focus:ring-red-100 dark:focus:ring-red-400' }
47+
48+
},
49+
outline: {
50+
true: {
51+
base: 'p-0.5',
52+
outlineWrapper: 'bg-white !text-gray-900 dark:bg-gray-900 dark:!text-white hover:bg-transparent hover:!text-inherit group-hover:!bg-opacity-0 group-hover:!text-inherit',
53+
},
54+
},
55+
pill: {
56+
true: {
57+
base: 'rounded-full',
58+
outlineWrapper: 'rounded-full'
59+
},
60+
false: {
61+
base: 'rounded-lg',
62+
outlineWrapper: 'rounded-lg'
63+
},
64+
},
65+
shadow : {
66+
true: {
67+
base: 'shadow-lg'
68+
}
69+
},
70+
// group: {
71+
// true: {},
72+
// },
73+
disabled: {
74+
true: { base: 'opacity-50 cursor-not-allowed' },
75+
},
76+
},
77+
compoundVariants: [
78+
// {
79+
// group: true,
80+
// pill: true,
81+
// class: { base: 'first:rounded-s-full last:rounded-e-full' },
82+
// },
83+
// {
84+
// group: true,
85+
// pill: false,
86+
// class: { base: 'first:rounded-s-lg last:rounded-e-lg' },
87+
// },
88+
{
89+
shadow: true,
90+
color: 'blue',
91+
class: { base: 'shadow-blue-500/50 dark:shadow-blue-800/80'}
92+
},
93+
{
94+
shadow: true,
95+
color: 'green',
96+
class: { base: 'shadow-green-500/50 dark:shadow-green-800/80'}
97+
},
98+
{
99+
shadow: true,
100+
color: 'cyan',
101+
class: { base: 'shadow-cyan-500/50 dark:shadow-cyan-800/80'}
102+
},
103+
{
104+
shadow: true,
105+
color: 'teal',
106+
class: { base: 'shadow-teal-500/50 dark:shadow-teal-800/80'}
107+
},
108+
{
109+
shadow: true,
110+
color: 'lime',
111+
class: { base: 'shadow-lime-500/50 dark:shadow-lime-800/80'}
112+
},
113+
{
114+
shadow: true,
115+
color: 'red',
116+
class: { base: 'shadow-red-500/50 dark:shadow-red-800/80'}
117+
},
118+
{
119+
shadow: true,
120+
color: 'pink',
121+
class: { base: 'shadow-pink-500/50 dark:shadow-pink-800/80'}
122+
},
123+
{
124+
shadow: true,
125+
color: 'purple',
126+
class: { base: 'shadow-purple-500/50 dark:shadow-purple-800/80'}
127+
},
128+
{
129+
shadow: true,
130+
color: 'purpleToBlue',
131+
class: { base: 'shadow-blue-500/50 dark:shadow-blue-800/80'}
132+
},
133+
{
134+
shadow: true,
135+
color: 'cyanToBlue',
136+
class: { base: 'shadow-cyan-500/50 dark:shadow-cyan-800/80'}
137+
},
138+
{
139+
shadow: true,
140+
color: 'greenToBlue',
141+
class: { base: 'shadow-green-500/50 dark:shadow-green-800/80'}
142+
},
143+
{
144+
shadow: true,
145+
color: 'purpleToPink',
146+
class: { base: 'shadow-purple-500/50 dark:shadow-purple-800/80'}
147+
},
148+
{
149+
shadow: true,
150+
color: 'pinkToOrange',
151+
class: { base: 'shadow-pink-500/50 dark:shadow-pink-800/80'}
152+
},
153+
{
154+
shadow: true,
155+
color: 'tealToLime',
156+
class: { base: 'shadow-lime-500/50 dark:shadow-teal-800/80'}
157+
},
158+
{
159+
shadow: true,
160+
color: 'redToYellow',
161+
class: { base: 'shadow-red-500/50 dark:shadow-red-800/80'}
162+
}
163+
],
164+
});

src/lib/list-group/ListgroupItem.svelte

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import { tv } from 'tailwind-variants';
55
import { type ListgroupItemProps as Props, listGroupItem } from '.';
66
7-
let { children, onclick, active, current, disabled, name, icon, href, currentClass = 'text-white bg-primary-700 dark:text-white dark:bg-gray-800', normalClass, disabledClass = 'text-gray-900 bg-gray-100 dark:bg-gray-600 dark:text-gray-400', liClass = 'py-2 px-4 w-full text-sm font-medium list-none first:rounded-t-lg last:rounded-b-lg', class: className, ...restProps }: Props = $props();
7+
let { children, onclick, active, current, disabled, name, Icon, href, currentClass = 'text-white bg-primary-700 dark:text-white dark:bg-gray-800', normalClass, disabledClass = 'text-gray-900 bg-gray-100 dark:bg-gray-600 dark:text-gray-400', liClass = 'py-2 px-4 w-full text-sm font-medium list-none first:rounded-t-lg last:rounded-b-lg', class: className, ...restProps }: Props = $props();
88
99
active = getContext('active');
1010
@@ -43,8 +43,8 @@
4343
</a>
4444
{:else}
4545
<button {onclick} class={buttonClass} {disabled} aria-current={current}>
46-
{#if icon}
47-
<icon class="me-2.5 h-5 w-5"></icon>
46+
{#if Icon}
47+
<Icon class="me-2.5 h-5 w-5" />
4848
{/if}
4949
{name}
5050
</button>
@@ -60,7 +60,7 @@
6060
@prop current
6161
@prop disabled
6262
@prop name
63-
@prop icon
63+
@prop Icon
6464
@prop href
6565
@prop currentClass = 'text-white bg-primary-700 dark:text-white dark:bg-gray-800'
6666
@prop normalClass

src/lib/list-group/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface ListgroupItemProps extends HTMLAnchorAttributes {
2323
current?: boolean;
2424
disabled?: boolean;
2525
name?: string | undefined | null;
26-
icon?: Component;
26+
Icon?: Component;
2727
href?: string | undefined | null;
2828
currentClass?: string | undefined | null;
2929
normalClass?: string | undefined | null;

0 commit comments

Comments
 (0)