You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

132 lines
2.7 KiB

<script setup lang="ts">
/**
* ExperimentaButton Component
*
* Experimenta-branded button with animated gradient background.
* Based on the experimenta Design System.
*
* @example
* <ExperimentaButton>Click me</ExperimentaButton>
* <ExperimentaButton variant="secondary">Cancel</ExperimentaButton>
* <ExperimentaButton size="small">Small</ExperimentaButton>
*/
interface Props {
/** Button variant */
variant?: 'primary' | 'secondary'
/** Button size */
size?: 'small' | 'medium' | 'large'
/** Disabled state */
disabled?: boolean
/** Button type */
type?: 'button' | 'submit' | 'reset'
/** Link behavior (renders as <a> tag) */
href?: string
/** Target for links */
target?: '_blank' | '_self' | '_parent' | '_top'
}
withDefaults(defineProps<Props>(), {
variant: 'primary',
size: 'large',
disabled: false,
type: 'button',
})
const emit = defineEmits<{
click: [event: MouseEvent]
}>()
function handleClick(event: MouseEvent) {
emit('click', event)
}
</script>
<template>
<component
:is="href ? 'a' : 'button'"
:href="href"
:target="href ? target : undefined"
:type="!href ? type : undefined"
:disabled="!href ? disabled : undefined"
:class="[
'btn-experimenta',
`btn-${variant}`,
`btn-${size}`,
{
'btn-disabled': disabled,
},
]"
@click="handleClick"
>
<slot />
</component>
</template>
<style scoped>
/* Base Button Styles */
.btn-experimenta {
@apply inline-block cursor-pointer;
@apply font-medium text-white;
@apply transition-all;
@apply outline-0 border-0;
@apply rounded-2xl;
text-decoration: none;
line-height: 1.7em;
}
/* Primary Variant */
.btn-primary {
background: #e6007e;
background-image: linear-gradient(to left, #e6007e, #e6007e, #e40521, #e6007e);
background-size: 300%;
background-position: left;
transition:
background-position 1s ease,
all 0.3s ease;
}
.btn-primary:hover:not(.btn-disabled) {
background-position: right;
}
/* Secondary Variant */
.btn-secondary {
@apply bg-transparent border-2 border-accent text-accent;
}
.btn-secondary:hover:not(.btn-disabled) {
@apply bg-accent text-white;
}
/* Sizes */
.btn-large {
@apply text-lg px-8 py-2.5;
}
.btn-medium {
@apply text-base px-6 py-2;
}
.btn-small {
@apply text-base px-6 py-2;
}
/* Responsive */
@media (max-width: 480px) {
.btn-large {
@apply text-base px-6 py-2;
}
}
/* Disabled State */
.btn-disabled {
@apply opacity-50 cursor-not-allowed;
}
/* Focus State (Accessibility) */
.btn-experimenta:focus-visible {
@apply outline-none ring-2 ring-accent ring-offset-2;
ring-offset-color: var(--color-purple-darkest, #0f051d);
}
</style>