diff --git a/docs/content/3.components/button.md b/docs/content/3.components/button.md index 81051629..ad8f064d 100644 --- a/docs/content/3.components/button.md +++ b/docs/content/3.components/button.md @@ -29,23 +29,6 @@ props: --- :: -### Link - -You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc. - -::component-code ---- -ignore: - - label - - target -props: - to: https://github.com/nuxt/ui - target: _blank -slots: - default: Button ---- -:: - ### Color Use the `color` prop to change the color of the Button. @@ -160,6 +143,96 @@ props: --- :: +### Link + +You can pass any property from the [Link](/components/link#props) component such as `to`, `target`, etc. + +::component-code +--- +ignore: + - target +props: + to: https://github.com/nuxt/ui + target: _blank +slots: + default: Button +--- +:: + +When the Button is a link or when using the `active` prop, you can use the `active-color` and `active-variant` props to customize the active state. + +::component-code +--- +prettier: true +ignore: + - color + - variant +items: + activeColor: + - primary + - secondary + - success + - info + - warning + - error + - neutral + activeVariant: + - solid + - outline + - soft + - subtle + - ghost + - link +props: + active: true + color: neutral + variant: outline + activeColor: primary + activeVariant: solid +slots: + default: | + + Button +--- + +Button +:: + +You can also use the `active-class` and `inactive-class` props to customize the active state. + +::component-code +--- +props: + active: true + activeClass: 'font-bold' + inactiveClass: 'font-light' +slots: + default: Button +--- + +Button +:: + +::tip +You can configure these styles globally in your `app.config.ts` file under the `ui.button.variants.active` key. + +```ts +export default defineAppConfig({ + ui: { + button: { + variants: { + active: { + true: { + base: 'font-bold' + } + } + } + } + } +}) +``` +:: + ### Loading Use the `loading` prop to show a loading icon and disable the Button. diff --git a/src/runtime/components/Button.vue b/src/runtime/components/Button.vue index 5486ac24..14628e60 100644 --- a/src/runtime/components/Button.vue +++ b/src/runtime/components/Button.vue @@ -21,10 +21,12 @@ export interface ButtonProps extends UseComponentIconsProps, Omit() +const props = withDefaults(defineProps(), { + active: undefined, + activeClass: '', + inactiveClass: '' +}) const slots = defineSlots() const linkProps = useForwardProps(pickLinkProps(props)) @@ -87,7 +93,19 @@ const { isLeading, isTrailing, leadingIconName, trailingIconName } = useComponen computed(() => ({ ...props, loading: isLoading.value })) ) -const ui = computed(() => button({ +const ui = computed(() => tv({ + extend: button, + variants: { + active: { + true: { + base: props.activeClass + }, + false: { + base: props.inactiveClass + } + } + } +})({ color: props.color, variant: props.variant, size: buttonSize.value, @@ -102,26 +120,37 @@ const ui = computed(() => button({ diff --git a/src/theme/button.ts b/src/theme/button.ts index cc04a814..36501f24 100644 --- a/src/theme/button.ts +++ b/src/theme/button.ts @@ -73,6 +73,14 @@ export default (options: Required) => ({ }, loading: { true: '' + }, + active: { + true: { + base: '' + }, + false: { + base: '' + } } }, compoundVariants: [...(options.theme.colors || []).map((color: string) => ({ diff --git a/test/components/Button.spec.ts b/test/components/Button.spec.ts index 5ce06761..51153dee 100644 --- a/test/components/Button.spec.ts +++ b/test/components/Button.spec.ts @@ -20,6 +20,7 @@ describe('Button', () => { ...sizes.map((size: string) => [`with size ${size}`, { props: { label: 'Button', size } }]), ...variants.map((variant: string) => [`with primary variant ${variant}`, { props: { label: 'Button', variant } }]), ...variants.map((variant: string) => [`with neutral variant ${variant}`, { props: { label: 'Button', variant, color: 'neutral' } }]), + ...variants.map((activeVariant: string) => [`with active variant ${activeVariant}`, { props: { label: 'Button', active: true, activeVariant } }]), ['with icon', { props: { icon: 'i-lucide-rocket' } }], ['with leading and icon', { props: { leading: true, icon: 'i-lucide-arrow-left' } }], ['with leadingIcon', { props: { leadingIcon: 'i-lucide-arrow-left' } }], @@ -39,6 +40,8 @@ describe('Button', () => { ['with square', { props: { label: 'Button', square: true } }], ['with as', { props: { label: 'Button', as: 'div' } }], ['with class', { props: { label: 'Button', class: 'rounded-full font-bold' } }], + ['with activeClass', { props: { label: 'Button', active: true, activeClass: 'font-bold' } }], + ['with inactiveClass', { props: { label: 'Button', active: false, inactiveClass: 'font-light' } }], ['with ui', { props: { label: 'Button', ui: { label: 'font-bold' } } }], // Slots ['with default slot', { slots: { default: () => 'Default slot' } }], diff --git a/test/components/__snapshots__/Button-vue.spec.ts.snap b/test/components/__snapshots__/Button-vue.spec.ts.snap index 3ed7a866..16196477 100644 --- a/test/components/__snapshots__/Button-vue.spec.ts.snap +++ b/test/components/__snapshots__/Button-vue.spec.ts.snap @@ -1,5 +1,54 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html +exports[`Button > renders with active variant ghost correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant link correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant outline correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant soft correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant solid correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant subtle correctly 1`] = ` +"" +`; + +exports[`Button > renders with activeClass correctly 1`] = ` +"" +`; + exports[`Button > renders with as correctly 1`] = ` "
Button @@ -69,6 +118,13 @@ exports[`Button > renders with icon correctly 1`] = ` " `; +exports[`Button > renders with inactiveClass correctly 1`] = ` +"" +`; + exports[`Button > renders with label correctly 1`] = ` "" +`; + +exports[`Button > renders with active variant link correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant outline correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant soft correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant solid correctly 1`] = ` +"" +`; + +exports[`Button > renders with active variant subtle correctly 1`] = ` +"" +`; + +exports[`Button > renders with activeClass correctly 1`] = ` +"" +`; + exports[`Button > renders with as correctly 1`] = ` "
Button @@ -69,6 +118,13 @@ exports[`Button > renders with icon correctly 1`] = ` " `; +exports[`Button > renders with inactiveClass correctly 1`] = ` +"" +`; + exports[`Button > renders with label correctly 1`] = ` "