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
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>
|
|
|