diff --git a/docs/guide/button/button.md b/docs/guide/button/button.md index 21e1ca0..468457a 100644 --- a/docs/guide/button/button.md +++ b/docs/guide/button/button.md @@ -303,12 +303,28 @@ import { Button } from 'flowbite-vue' const loading = ref(false) ``` diff --git a/docs/guide/button/examples/ButtonLoadingExample.vue b/docs/guide/button/examples/ButtonLoadingExample.vue index 62c1f4e..35e44ae 100644 --- a/docs/guide/button/examples/ButtonLoadingExample.vue +++ b/docs/guide/button/examples/ButtonLoadingExample.vue @@ -1,15 +1,32 @@ diff --git a/src/components/Button/Button.vue b/src/components/Button/Button.vue index cc63f8f..fd743f2 100644 --- a/src/components/Button/Button.vue +++ b/src/components/Button/Button.vue @@ -1,16 +1,30 @@ diff --git a/src/components/Button/useButtonClasses.ts b/src/components/Button/useButtonClasses.ts index dcf1b11..34a5aa4 100644 --- a/src/components/Button/useButtonClasses.ts +++ b/src/components/Button/useButtonClasses.ts @@ -157,6 +157,7 @@ export type UseButtonClassesProps = { } const simpleGradients = ['blue', 'green', 'cyan', 'teal', 'lime', 'red', 'pink', 'purple'] +const alternativeColors = ['alternative', 'light'] export function useButtonClasses(props: UseButtonClassesProps): { wrapperClasses: Ref, spanClasses: Ref } { const slots = useSlots() @@ -180,7 +181,9 @@ export function useButtonClasses(props: UseButtonClassesProps): { wrapperClasses if(!props.disabled) hoverClass = buttonOutlineGradientClasses.hover[props.gradient as unknown as keyof typeof buttonOutlineGradientClasses.hover] - } // TODO: log for invalid props or fallback + } else { + console.warn(`cannot use outline prop with "${props.gradient}" gradient`) // TODO: prettify + } } else if (isGradient) { // JUST GRADIENT @@ -191,12 +194,14 @@ export function useButtonClasses(props: UseButtonClassesProps): { wrapperClasses } else if (isColor && isOutline) { // COLOR AND OUTLINE - if (!['alternative', 'light'].includes(props.color)) { + if (!alternativeColors.includes(props.color)) { backgroundClass = buttonOutlineColorClasses.default[props.color as unknown as keyof typeof buttonOutlineColorClasses.default] if(!props.disabled) hoverClass = buttonOutlineColorClasses.hover[props.color as unknown as keyof typeof buttonOutlineColorClasses.hover] - } // TODO: log for invalid props or fallback + } else { + console.warn(`cannot use outline prop with "${props.color}" color`) // TODO: prettify + } } else { // JUST COLOR @@ -225,7 +230,7 @@ export function useButtonClasses(props: UseButtonClassesProps): { wrapperClasses shadowClass, props.pill ? '!rounded-full' : '', props.disabled ? 'cursor-not-allowed opacity-50' : '', - isGradient && isOutline ? 'p-0.5' : sizeClasses.value, + (isGradient && isOutline) ? 'p-0.5' : sizeClasses.value, (slots.prefix || slots.suffix || props.loading) ? 'inline-flex items-center' : '', ) }) @@ -233,7 +238,7 @@ export function useButtonClasses(props: UseButtonClassesProps): { wrapperClasses const spanClasses = computed(() => { if (!!props.gradient && props.outline) { // ONLY FOR GRADIENT OUTLINE BUTTON return classNames( - 'relative bg-white dark:bg-gray-900 rounded-md', + 'relative bg-white dark:bg-gray-900 rounded-md inline-flex items-center', sizeClasses.value, !props.disabled ? 'group-hover:bg-opacity-0 transition-all ease-in duration-75' : '', ) diff --git a/src/components/Button/useButtonSpinner.ts b/src/components/Button/useButtonSpinner.ts new file mode 100644 index 0000000..15503b6 --- /dev/null +++ b/src/components/Button/useButtonSpinner.ts @@ -0,0 +1,44 @@ +import type {ButtonGradient, ButtonSize, ButtonVariant} from './Button.vue' +import type {SpinnerColor, SpinnerSize} from '../Spinner/Spinner.vue' +import type {Ref} from 'vue' +import {computed} from 'vue' + +export type UseButtonSpinnerProps = { + outline: boolean + size: ButtonSize + color: ButtonVariant + gradient: ButtonGradient | null +} + +export function useButtonSpinner(props: UseButtonSpinnerProps): { size: Ref, color: Ref } { + const btnSizeSpinnerSizeMap: Record = { + lg: '5', md: '4', sm: '3', xl: '6', xs: '2.5', + } + const size = computed(() => { + return btnSizeSpinnerSizeMap[props.size] + }) + const color = computed(() => { + + if(!props.outline) return 'white' + + if(props.gradient) { + if(props.gradient.includes('purple')) return 'purple' + else if(props.gradient.includes('blue')) return 'blue' + else if(props.gradient.includes('pink')) return 'pink' + else if(props.gradient.includes('red')) return 'red' + return 'white' + } + + if(['alternative', 'dark', 'light'].includes(props.color)) { + return 'white' + } else if(props.color === 'default') { + return 'blue' + } + return props.color as SpinnerColor + }) + + return { + size, + color, + } +} \ No newline at end of file diff --git a/src/components/Spinner/Spinner.vue b/src/components/Spinner/Spinner.vue index 3024312..ef734a6 100644 --- a/src/components/Spinner/Spinner.vue +++ b/src/components/Spinner/Spinner.vue @@ -5,47 +5,22 @@ \ No newline at end of file diff --git a/src/components/Spinner/useSpinnerClasses.ts b/src/components/Spinner/useSpinnerClasses.ts new file mode 100644 index 0000000..77d55dd --- /dev/null +++ b/src/components/Spinner/useSpinnerClasses.ts @@ -0,0 +1,61 @@ +import type { SpinnerColor, SpinnerSize } from './Spinner.vue' +import { computed } from 'vue' +import type { Ref } from 'vue' +import classNames from 'classnames' + +const sizes: Record = { + '0': 'w-0 h-0', + '0.5': 'w-0.5 h-0.5', + '1': 'w-1 h-1', + '1.5': 'w-1.5 h-1.5', + '10': 'w-10 h-10', + '11': 'w-11 h-11', + '12': 'w-12 h-12', + '2': 'w-2 h-2', + '2.5': 'w-2.5 h-2.5', + '3': 'w-3 h-3', + '4': 'w-4 h-4', + '5': 'w-5 h-5', + '6': 'w-6 h-6', + '7': 'w-7 h-7', + '8': 'w-8 h-8', + '9': 'w-9 h-9', + px: 'w-px h-px', +} + +const colors: Record = { + blue: 'fill-blue-600', + gray: 'fill-gray-600 dark:fill-gray-300', + green: 'fill-green-500', + pink: 'fill-pink-600', + purple: 'fill-purple-600', + red: 'fill-red-600', + yellow: 'fill-yellow-400', + white: 'fill-white', +} + +export type UseSpinnerClassesProps = { + size: SpinnerSize + color: SpinnerColor +} + +export function useSpinnerClasses(props: UseSpinnerClassesProps): { spinnerClasses: Ref } { + + const sizeClasses = computed(() => sizes[props.size]) + const colorClasses = computed(() => colors[props.color]) + const bgColorClasses = computed(() => 'text-gray-200 dark:text-gray-600') + const animateClasses = computed(() => 'animate-spin') + + const spinnerClasses = computed(() => { + return classNames( + sizeClasses.value, + bgColorClasses.value, + colorClasses.value, + animateClasses.value, + ) + }) + + return { + spinnerClasses, + } +} \ No newline at end of file