-
-
Notifications
You must be signed in to change notification settings - Fork 424
Expand file tree
/
Copy pathBase.vue
More file actions
84 lines (78 loc) · 2.8 KB
/
Base.vue
File metadata and controls
84 lines (78 loc) · 2.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
<script setup lang="ts">
import type { IconClass } from '~/types'
const props = withDefaults(
defineProps<{
disabled?: boolean
/** @default "button" */
type?: 'button' | 'submit'
/** @default "secondary" */
variant?: 'primary' | 'secondary'
/** @default "medium" */
size?: 'small' | 'medium'
/** Keyboard shortcut hint */
ariaKeyshortcuts?: string
/** Forces the button to occupy the entire width of its container. */
block?: boolean
classicon?: IconClass
}>(),
{
type: 'button',
variant: 'secondary',
size: 'medium',
},
)
const el = useTemplateRef('el')
const slots = defineSlots<{
default?: () => unknown
}>()
const iconOnly = computed(() => !!props.classicon && !slots.default)
const keyboardShortcutsEnabled = useKeyboardShortcuts()
defineExpose({
focus: () => el.value?.focus(),
getBoundingClientRect: () => el.value?.getBoundingClientRect(),
})
</script>
<template>
<button
ref="el"
class="group gap-x-1 items-center justify-center font-mono border border-border rounded-md transition-all duration-200 disabled:(opacity-40 cursor-not-allowed border-transparent)"
:class="{
'inline-flex': !block,
'flex': block,
'text-sm py-2': size === 'medium' && !iconOnly,
'text-sm p-2': size === 'medium' && !!iconOnly,
'px-4': size === 'medium' && !classicon && !iconOnly,
'ps-3 pe-4': size === 'medium' && !!classicon && !iconOnly,
'text-xs py-0.5': size === 'small' && !iconOnly,
'text-xs p-0.5': size === 'small' && !!iconOnly,
'px-2': size === 'small' && !classicon && !iconOnly,
'ps-1.5 pe-2': size === 'small' && !!classicon && !iconOnly,
'bg-transparent text-fg hover:enabled:(bg-fg/10) focus-visible:enabled:(bg-fg/10) aria-pressed:(bg-fg/10 border-fg/20 hover:enabled:(bg-fg/20 text-fg/50))':
variant === 'secondary',
'text-bg bg-fg hover:enabled:(bg-fg/50) focus-visible:enabled:(bg-fg/50) aria-pressed:(bg-fg text-bg border-fg hover:enabled:(text-bg/50))':
variant === 'primary',
}"
:type="props.type"
:disabled="
/**
* Unfortunately Vue _sometimes_ doesn't handle `disabled` correct,
* resulting in an invalid `disabled=false` attribute in the final HTML.
*
* This fixes this.
*/
disabled ? true : undefined
"
:aria-keyshortcuts="keyboardShortcutsEnabled ? ariaKeyshortcuts : undefined"
>
<span v-if="classicon" class="size-[1em]" :class="classicon" aria-hidden="true" />
<slot />
<kbd
v-if="keyboardShortcutsEnabled && ariaKeyshortcuts"
data-kbd-hint
class="ms-2 inline-flex items-center justify-center w-4 h-4 text-xs text-fg bg-bg-muted border border-border rounded no-underline"
aria-hidden="true"
>
{{ ariaKeyshortcuts }}
</kbd>
</button>
</template>