forked from
npmx.dev/npmx.dev
[READ-ONLY]
a fast, modern browser for the npm registry
1<script setup lang="ts">
2const props = withDefaults(
3 defineProps<{
4 disabled?: boolean
5 type?: 'button' | 'submit'
6 variant?: 'primary' | 'secondary'
7 size?: 'small' | 'medium'
8 ariaKeyshortcuts?: string
9 block?: boolean
10
11 classicon?: string
12 }>(),
13 {
14 type: 'button',
15 variant: 'secondary',
16 size: 'medium',
17 },
18)
19
20const el = useTemplateRef('el')
21
22defineExpose({
23 focus: () => el.value?.focus(),
24 getBoundingClientRect: () => el.value?.getBoundingClientRect(),
25})
26</script>
27
28<template>
29 <button
30 ref="el"
31 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)"
32 :class="{
33 'inline-flex': !block,
34 'flex': block,
35 'text-sm px-4 py-2': size === 'medium',
36 'text-xs px-2 py-0.5': size === 'small',
37 '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))':
38 variant === 'secondary',
39 '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))':
40 variant === 'primary',
41 }"
42 :type="props.type"
43 :disabled="
44 /**
45 * Unfortunately Vue _sometimes_ doesn't handle `disabled` correct,
46 * resulting in an invalid `disabled=false` attribute in the final HTML.
47 *
48 * This fixes this.
49 */
50 disabled ? true : undefined
51 "
52 :aria-keyshortcuts="ariaKeyshortcuts"
53 >
54 <span v-if="classicon" class="size-[1em]" :class="classicon" aria-hidden="true" />
55 <slot />
56 <kbd
57 v-if="ariaKeyshortcuts"
58 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"
59 aria-hidden="true"
60 >
61 {{ ariaKeyshortcuts }}
62 </kbd>
63 </button>
64</template>