feat(quick-261022-k9k): admin save shortcuts and Create and new on record forms
- app/hotkeys.ts: dependency-free data-hotkey core (Ctrl/Cmd+S, Ctrl/Cmd+Enter, Ctrl/Cmd+Shift+S, Esc, / and ?), innermost-modal root, capture-phase modifier listener, platform labels and the help-dialog state - Button hotkey prop (data-hotkey, aria-keyshortcuts); shortcuts installed by AppShell - FormView: save keys and tooltips, Create and new on create forms via remountView - phrasebook: form.create_and_new and the shortcuts group (en, pl)
This commit is contained in:
@@ -1,9 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, type Component } from 'vue'
|
||||
import { RouterLink, type RouteLocationRaw } from 'vue-router'
|
||||
import { ariaKeyshortcuts } from '../../app/hotkeys'
|
||||
|
||||
// One button for the whole admin (design tokens): primary, outline, ghost and
|
||||
// danger (outline). With `to` it renders a router link styled the same way.
|
||||
// A hotkey prop marks the button for the admin's keyboard shortcuts
|
||||
// (data-hotkey tokens, see app/hotkeys.ts).
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
variant?: 'primary' | 'outline' | 'ghost' | 'danger'
|
||||
@@ -12,8 +15,9 @@ const props = withDefaults(
|
||||
disabled?: boolean
|
||||
icon?: Component
|
||||
to?: RouteLocationRaw
|
||||
hotkey?: string
|
||||
}>(),
|
||||
{ variant: 'outline', size: 'md', type: 'button', disabled: false, icon: undefined, to: undefined },
|
||||
{ variant: 'outline', size: 'md', type: 'button', disabled: false, icon: undefined, to: undefined, hotkey: undefined },
|
||||
)
|
||||
|
||||
const variants: Record<NonNullable<typeof props.variant>, string> = {
|
||||
@@ -23,6 +27,8 @@ const variants: Record<NonNullable<typeof props.variant>, string> = {
|
||||
danger: 'border border-danger bg-surface text-danger hover:bg-danger-soft',
|
||||
}
|
||||
|
||||
const keyshortcuts = computed(() => (props.hotkey ? ariaKeyshortcuts(props.hotkey) : undefined))
|
||||
|
||||
const classes = computed(() => [
|
||||
'inline-flex shrink-0 items-center justify-center gap-2 rounded-control px-4 font-semibold whitespace-nowrap no-underline transition-colors duration-150 ease-out disabled:cursor-not-allowed disabled:opacity-60',
|
||||
props.size === 'sm' ? 'h-[38px]' : 'h-button',
|
||||
@@ -31,11 +37,24 @@ const classes = computed(() => [
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<RouterLink v-if="to !== undefined" :to="to" :class="classes">
|
||||
<RouterLink
|
||||
v-if="to !== undefined"
|
||||
:to="to"
|
||||
:class="classes"
|
||||
:data-hotkey="hotkey"
|
||||
:aria-keyshortcuts="keyshortcuts"
|
||||
>
|
||||
<component :is="icon" v-if="icon" :size="16" aria-hidden="true" />
|
||||
<slot />
|
||||
</RouterLink>
|
||||
<button v-else :type="type" :disabled="disabled" :class="classes">
|
||||
<button
|
||||
v-else
|
||||
:type="type"
|
||||
:disabled="disabled"
|
||||
:class="classes"
|
||||
:data-hotkey="hotkey"
|
||||
:aria-keyshortcuts="keyshortcuts"
|
||||
>
|
||||
<component :is="icon" v-if="icon" :size="16" aria-hidden="true" />
|
||||
<slot />
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user