openpencil/src/components/ui/IconButton.vue
Danila Poyarkov f525c0f4fb feat(ui): add themed panel foundations
- Introduce Nuxt UI-style Tailwind Variants themes and 26px panel primitives\n- Align section and field action rails across labeled property rows\n- Add Storybook with dark/light states, accessibility tooling, and CI build coverage\n- Standardize UI acronym casing across app and Vue SDK types
2026-07-10 18:16:21 +03:00

54 lines
1.1 KiB
Vue

<script setup lang="ts">
import { computed, normalizeClass, useAttrs } from 'vue'
import { tv } from 'tailwind-variants'
import theme from '@/theme/icon-button'
import Tip from '@/components/ui/Tip.vue'
const {
active = false,
disabled = false,
label,
side = 'top',
size = 'sm',
type = 'button'
} = defineProps<{
active?: boolean
disabled?: boolean
label?: string
side?: 'top' | 'bottom' | 'left' | 'right'
size?: 'sm' | 'md'
type?: 'button' | 'submit' | 'reset'
}>()
const attrs = useAttrs()
defineOptions({ inheritAttrs: false })
const buttonAttrs = computed(() => {
const { class: _class, ...rest } = attrs
return rest
})
const cls = computed(() =>
tv(theme)({ size, active, disabled, class: normalizeClass(attrs.class) })
)
</script>
<template>
<Tip :label="label" :side="side" :disabled="disabled || !label">
<button
v-bind="buttonAttrs"
data-slot="icon-button"
:type="type"
:disabled="disabled"
:aria-label="label"
:aria-pressed="active ? 'true' : undefined"
:data-state="active ? 'on' : 'off'"
:class="cls"
>
<slot />
</button>
</Tip>
</template>