Skip to content

Commit 2cf758d

Browse files
committed
feat: enhance Button component with new variants, sizes, and styles
1 parent 1365433 commit 2cf758d

File tree

8 files changed

+248
-23
lines changed

8 files changed

+248
-23
lines changed
Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,56 @@
11
<template>
2-
<div class="flex flex-col gap-2">
3-
<a-button class="btn btn-primary">Primary Button</a-button>
4-
<a-button class="btn btn-secondary">Default Button</a-button>
5-
<a-button class="btn btn-error">Dashed Button</a-button>
6-
<a-button class="btn btn-link">Text Button</a-button>
7-
<a-button class="btn btn-link">Link Button</a-button>
2+
<div class="flex flex-wrap gap-2">
3+
<a-button variant="solid" size="lg">Solid Button</a-button>
4+
<a-button variant="solid" size="lg" disabled>Solid Button</a-button>
5+
<a-button variant="solid" size="lg" loading>Solid Button</a-button>
6+
<a-button variant="solid" size="lg" danger>Danger Solid Button</a-button>
7+
<a-button variant="solid" size="lg" danger disabled>Disabled Danger Solid Button</a-button>
8+
<br />
9+
<a-button variant="outlined" size="sm">Outlined Button</a-button>
10+
<a-button variant="outlined" size="md">Outlined Button</a-button>
11+
<a-button variant="outlined" size="lg">Outlined Button</a-button>
12+
<a-button variant="outlined" size="lg" disabled>Disabled Outlined Button</a-button>
13+
<a-button variant="outlined" size="lg" loading>Loading Outlined Button</a-button>
14+
<a-button variant="outlined" size="lg" danger>Danger Outlined Button</a-button>
15+
<a-button variant="outlined" size="lg" danger disabled>
16+
Disabled Danger Outlined Button
17+
</a-button>
18+
<br />
19+
<a-button variant="text" size="sm">Text Button</a-button>
20+
<a-button variant="text" size="md">Text Button</a-button>
21+
<a-button variant="text" size="lg">Text Button</a-button>
22+
<a-button variant="text" size="lg" disabled>Disabled Text Button</a-button>
23+
<a-button variant="text" size="lg" loading>Loading Text Button</a-button>
24+
<a-button variant="text" size="lg" danger>Danger Text Button</a-button>
25+
<a-button variant="text" size="lg" danger disabled>Disabled Danger Text Button</a-button>
26+
<br />
27+
<a-button variant="link" size="sm">Link Button</a-button>
28+
<a-button variant="link" size="md">Link Button</a-button>
29+
<a-button variant="link" size="lg">Link Button</a-button>
30+
<a-button variant="link" size="lg" disabled>Disabled Link Button</a-button>
31+
<a-button variant="link" size="lg" loading>Loading Link Button</a-button>
32+
<a-button variant="link" size="lg" danger>Danger Link Button</a-button>
33+
<a-button variant="link" size="lg" danger disabled>Disabled Danger Link Button</a-button>
34+
<br />
35+
<a-button variant="dashed" size="sm">Dashed Button</a-button>
36+
<a-button variant="dashed" size="md">Dashed Button</a-button>
37+
<a-button variant="dashed" size="lg">Dashed Button</a-button>
38+
<a-button variant="dashed" size="lg" disabled>Disabled Dashed Button</a-button>
39+
<a-button variant="dashed" size="lg" loading>Loading Dashed Button</a-button>
40+
<a-button variant="dashed" size="lg" danger>Danger Dashed Button</a-button>
41+
<a-button variant="dashed" size="lg" danger disabled>Disabled Danger Dashed Button</a-button>
42+
<br />
43+
<a-button variant="filled" size="sm">Filled Button</a-button>
44+
<a-button variant="filled" size="md">Filled Button</a-button>
45+
<a-button variant="filled" size="lg">Filled Button</a-button>
46+
<a-button variant="filled" size="lg" disabled>Disabled Filled Button</a-button>
47+
<a-button variant="filled" size="lg" loading>Loading Filled Button</a-button>
48+
<a-button variant="filled" size="lg" danger>Danger Filled Button</a-button>
49+
<a-button variant="filled" size="lg" danger disabled>Disabled Danger Filled Button</a-button>
50+
51+
<a-button color="purple">Purple Button</a-button>
52+
<a-button color="blue">Blue Button</a-button>
53+
<a-button color="green">Green Button</a-button>
54+
<a-button color="red">Red Button</a-button>
855
</div>
956
</template>

packages-config/tailwind-config/tailwind.css

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@import 'tailwindcss' source(none);
2-
@plugin '@tailwindcss/typography';
32

43
@utility text-tint-* {
54
color: color-mix(in srgb, --value(--color-*, [*]), white calc(--modifier(integer) * 1%));

packages/ui/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"license": "MIT",
5454
"main": "./dist/lib.cjs",
5555
"module": "./dist/lib.mjs",
56-
"types": "./dist/types/index.d.ts",
56+
"types": "./dist/index.d.ts",
5757
"files": [
5858
"dist",
5959
"src/style",
@@ -72,6 +72,7 @@
7272
"@floating-ui/dom": "^1.6.13",
7373
"@floating-ui/vue": "^1.1.6",
7474
"lodash-es": "^4.17.21",
75+
"@ctrl/tinycolor": "^4.0.0",
7576
"resize-observer-polyfill": "^1.5.1"
7677
},
7778
"devDependencies": {
Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,50 @@
11
<template>
2-
<button class="ant-btn" :class="classes" @click="$emit('click', $event)">
2+
<button :class="rootClass" @click="$emit('click', $event)" :disabled="disabled" :style="cssVars">
3+
<slot name="loading"></slot>
4+
<slot name="icon"></slot>
35
<slot></slot>
46
</button>
57
</template>
68

79
<script setup lang="ts">
810
import { computed } from 'vue'
911
import { buttonProps, buttonEmits, ButtonSlots } from './meta'
12+
import { getCssVarColor } from '@/utils/colorAlgorithm'
1013
1114
const props = defineProps(buttonProps)
1215
1316
defineEmits(buttonEmits)
1417
defineSlots<ButtonSlots>()
1518
16-
const classes = computed(() => {
17-
return [
18-
'rounded-md px-4 py-2 cursor-pointer',
19-
props.type,
20-
{
21-
'bg-primary text-primary-content': props.type === 'primary',
22-
'bg-secondary text-secondary-content': props.type === 'secondary',
23-
},
24-
]
19+
// todo: color value should from theme provider
20+
const color = computed(() => {
21+
if (props.disabled) {
22+
return 'rgba(0,0,0,0.25)'
23+
}
24+
if (props.color) {
25+
return props.color
26+
}
27+
if (props.danger) {
28+
return '#ff4d4f'
29+
}
30+
if (props.variant === 'text') {
31+
return '#000000'
32+
}
33+
34+
return '#1677ff'
35+
})
36+
37+
const rootClass = computed(() => {
38+
return {
39+
'ant-btn': true,
40+
[`ant-btn-${props.variant}`]: true,
41+
[`ant-btn-${props.size}`]: true,
42+
'ant-btn-danger': props.danger,
43+
'ant-btn-loading': props.loading,
44+
'ant-btn-disabled': props.disabled,
45+
}
46+
})
47+
const cssVars = computed(() => {
48+
return getCssVarColor(color.value)
2549
})
2650
</script>

packages/ui/src/components/button/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { App, Plugin } from 'vue'
22
import Button from './Button.vue'
33
import './style/index.css'
44

5-
// 导出组件
65
export { default as Button } from './Button.vue'
76
export * from './meta'
87

packages/ui/src/components/button/meta.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,61 @@ export const buttonProps = {
66
* Specifies the visual style variant of the button
77
* @default 'primary'
88
*/
9-
type: {
10-
type: String as PropType<'primary' | 'secondary'>,
11-
default: 'primary',
9+
variant: {
10+
type: String as PropType<'solid' | 'outlined' | 'text' | 'link' | 'dashed' | 'filled'>,
11+
default: 'solid',
12+
},
13+
14+
/**
15+
* Specifies the size of the button
16+
* @default 'md'
17+
*/
18+
size: {
19+
type: String as PropType<'sm' | 'md' | 'lg'>,
20+
default: 'md',
21+
},
22+
23+
/**
24+
* Specifies the shape of the button
25+
* @default 'default'
26+
*/
27+
shape: {
28+
type: String as PropType<'default' | 'circle' | 'round'>,
29+
default: 'default',
30+
},
31+
32+
/**
33+
* Specifies the loading state of the button
34+
* @default false
35+
*/
36+
loading: {
37+
type: Boolean,
38+
default: false,
39+
},
40+
41+
/**
42+
* Specifies the disabled state of the button
43+
* @default false
44+
*/
45+
disabled: {
46+
type: Boolean,
47+
default: false,
48+
},
49+
50+
/**
51+
* Specifies the danger state of the button
52+
* @default false
53+
*/
54+
danger: {
55+
type: Boolean,
56+
default: false,
57+
},
58+
59+
/**
60+
* Specifies the color of the button
61+
*/
62+
color: {
63+
type: String,
1264
},
1365
} as const
1466

@@ -31,6 +83,14 @@ export const buttonSlots = {
3183
* Main content slot for the button text or custom content
3284
*/
3385
default: (_: any) => null as any,
86+
/**
87+
* Slot for the button icon
88+
*/
89+
icon: (_: any) => null as any,
90+
/**
91+
* Slot for the button loading indicator
92+
*/
93+
loading: (_: any) => null as any,
3494
} as const
3595

3696
export type ButtonSlots = typeof buttonSlots
Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,50 @@
11
@reference '../../../style/tailwind.css';
22

33
.ant-btn {
4-
@apply text-primary-content;
4+
@apply relative;
5+
@apply inline-flex shrink-0 cursor-pointer items-center justify-center gap-1 whitespace-nowrap;
6+
@apply border-1 text-sm;
7+
@apply box-border rounded-md px-4 transition-all duration-200 select-none;
8+
&:where(.ant-btn-disabled) {
9+
@apply cursor-not-allowed;
10+
}
11+
&:where(.ant-btn-loading) {
12+
@apply cursor-default opacity-50;
13+
}
14+
15+
&:where(.ant-btn-solid) {
16+
@apply border-none bg-[var(--bg-color)] text-[var(--bg-color-content)];
17+
@apply not-disabled:hover:bg-[var(--bg-color-hover)] not-disabled:active:bg-[var(--bg-color-active)];
18+
}
19+
&:where(.ant-btn-outlined),
20+
&:where(.ant-btn-dashed) {
21+
@apply border-[var(--border-color-tint-30)] bg-transparent text-[var(--text-color)];
22+
@apply not-disabled:hover:border-[var(--border-color-hover)] not-disabled:hover:text-[var(--text-color-hover)] not-disabled:active:border-[var(--border-color-active)] not-disabled:active:text-[var(--text-color-active)];
23+
@apply disabled:border-[var(--border-color-tint-80)];
24+
}
25+
&:where(.ant-btn-text) {
26+
@apply border-none bg-transparent text-[var(--text-color)];
27+
@apply not-disabled:hover:bg-[var(--bg-color-tint-90)] not-disabled:hover:text-[var(--text-color-hover)];
28+
}
29+
30+
&:where(.ant-btn-link) {
31+
@apply border-none bg-transparent text-[var(--text-color)] not-disabled:hover:text-[var(--text-color-hover)];
32+
}
33+
&:where(.ant-btn-dashed) {
34+
@apply border-dashed;
35+
}
36+
&:where(.ant-btn-filled) {
37+
@apply border-none bg-[var(--bg-color-tint-90)] text-[var(--text-color)] not-disabled:hover:text-[var(--text-color-hover)];
38+
@apply not-disabled:hover:bg-[var(--bg-color-tint-80)] not-disabled:active:bg-[var(--bg-color-tint-80)];
39+
}
40+
41+
&:where(.ant-btn-sm) {
42+
@apply h-6 text-xs;
43+
}
44+
&:where(.ant-btn-md) {
45+
@apply h-8 text-sm;
46+
}
47+
&:where(.ant-btn-lg) {
48+
@apply h-10 text-base;
49+
}
550
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { TinyColor } from '@ctrl/tinycolor'
2+
3+
export const getAlphaColor = (baseColor: string, alpha: number) =>
4+
new TinyColor(baseColor).setAlpha(alpha).toRgbString()
5+
6+
export const getSolidColor = (baseColor: string, brightness: number) => {
7+
const instance = new TinyColor(baseColor)
8+
return instance.darken(brightness).toHexString()
9+
}
10+
11+
export const getTintColor = (baseColor: string, tintNumber: number) => {
12+
return new TinyColor(baseColor).tint(tintNumber).toString()
13+
}
14+
15+
export const getShadeColor = (baseColor: string, shadeNumber: number) => {
16+
return new TinyColor(baseColor).shade(shadeNumber).toString()
17+
}
18+
19+
export const getCssVarColor = (baseColor: string) => {
20+
return {
21+
'--bg-color': baseColor,
22+
'--bg-color-hover': getTintColor(baseColor, 10),
23+
'--bg-color-active': getTintColor(baseColor, 20),
24+
'--bg-color-content': '#ffffff',
25+
'--border-color': baseColor,
26+
'--border-color-hover': getTintColor(baseColor, 10),
27+
'--border-color-active': getTintColor(baseColor, 20),
28+
'--border-color-tint-10': getTintColor(baseColor, 10),
29+
'--border-color-tint-20': getTintColor(baseColor, 20),
30+
'--border-color-tint-30': getTintColor(baseColor, 30),
31+
'--border-color-tint-40': getTintColor(baseColor, 40),
32+
'--border-color-tint-50': getTintColor(baseColor, 50),
33+
'--border-color-tint-60': getTintColor(baseColor, 60),
34+
'--border-color-tint-70': getTintColor(baseColor, 70),
35+
'--border-color-tint-80': getTintColor(baseColor, 80),
36+
'--border-color-tint-90': getTintColor(baseColor, 90),
37+
'--bg-color-tint-10': getTintColor(baseColor, 10),
38+
'--bg-color-tint-20': getTintColor(baseColor, 20),
39+
'--bg-color-tint-30': getTintColor(baseColor, 30),
40+
'--bg-color-tint-40': getTintColor(baseColor, 40),
41+
'--bg-color-tint-50': getTintColor(baseColor, 50),
42+
'--bg-color-tint-60': getTintColor(baseColor, 60),
43+
'--bg-color-tint-70': getTintColor(baseColor, 70),
44+
'--bg-color-tint-80': getTintColor(baseColor, 80),
45+
'--bg-color-tint-90': getTintColor(baseColor, 90),
46+
'--text-color': baseColor,
47+
'--text-color-hover': getTintColor(baseColor, 10),
48+
'--text-color-active': getTintColor(baseColor, 20),
49+
}
50+
}

0 commit comments

Comments
 (0)