feat(ui): implement autofocus prop on input and link

This commit is contained in:
upsiflu 2025-01-02 11:27:49 +01:00
parent dcddaaa561
commit e9a79dfaf8
6 changed files with 26 additions and 18 deletions

View File

@ -48,12 +48,6 @@ const labels = computed(() => ({
usernamePlaceholder: t('components.auth.LoginForm.placeholder.username')
}))
const username = ref()
onMounted(async () => {
await nextTick()
username.value?.focus()
})
const isLoading = ref(false)
const errors = ref([] as string[])
const submit = async () => {

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed, ref } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { useI18n } from 'vue-i18n';
import onKeyboardShortcut from '~/composables/onKeyboardShortcut';
@ -13,6 +13,8 @@ const { icon, placeholder, ...restProps } = defineProps<{
search?: true,
numeric?: true,
label?: string,
autofocus? : boolean
}>()
// TODO(A11y): Add `inputmode="numeric" pattern="[0-9]*"` to input if model type is number:
@ -34,6 +36,12 @@ const attributes = computed(() => ({
const { t } = useI18n()
const input = ref()
onMounted(() => {
if (restProps.autofocus) input.value.focus();
})
const model = defineModel<string|number>()
</script>

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import { computed } from 'vue'
import { computed, onMounted, ref } from 'vue'
import { type RouterLinkProps } from 'vue-router'
import { type ColorProps, type DefaultProps, type VariantProps, color, isNoColors } from '~/composables/color';
@ -13,6 +13,8 @@ const props = defineProps<{
icon?: string;
round?: true;
autofocus? : boolean
} & RouterLinkProps
& (ColorProps | DefaultProps)
& VariantProps
@ -26,6 +28,12 @@ const isExternalLink = computed(() =>
const [fontWeight, activeFontWeight] = props.thickWhenActive ? [600, 900] : [400, 400]
const isIconOnly = computed(() => !!props.icon)
const button = ref()
onMounted(() => {
if (props.autofocus) button.value.focus();
})
</script>
<template>
@ -34,6 +42,7 @@ const isIconOnly = computed(() => !!props.icon)
width(props)(
align(props)(
)))"
ref="button"
:class="[
$style.link,
round && $style['is-round'],

View File

@ -31,13 +31,13 @@ const styles = {
} as const;
const getStyle = (props : Partial<AlignmentProps>) => ([key, value]: Entry<AlignmentProps>) =>
(trace(`getStyle: key=${key}, value=${value}`),
(
typeof styles[key] === 'function' ?
(trace(`getStyle: key=${key}, value=${value}`), styles[key](
(styles[key](
// We know that props[key] is a value accepted by styles[key]. The ts compiler is not so smart.
// @ts-ignore
(key in props && props[key]) ?
props[(trace(props[key]), trace(key))]
props[((props[key]), (key))]
: value
))
: styles[key]
@ -73,14 +73,14 @@ export const align = <TProps extends Partial<AlignmentProps>>(
props: TProps,
defaults: Partial<AlignmentProps> = {}
) => merge (
trace((Object.entries(props) as Entries<TProps>).reduce(
((Object.entries(props) as Entries<TProps>).reduce(
((acc, [key, value]) =>
value && key in styles ?
acc.filter(([accKey, _]) => !conflicts.find(set => set.has(accKey) && set.has(key)))
.concat([[key, value]])
: acc
),
trace(Object.entries(defaults)) as Entries<Partial<AlignmentProps>>
(Object.entries(defaults)) as Entries<Partial<AlignmentProps>>
)).map(getStyle(props))
)

View File

@ -91,7 +91,7 @@ const logoUrl = computed(() => store.state.auth.authenticated ? 'library.index'
<!-- Sign up, Log in -->
<div style="display:contents;" v-if="!store.state.auth.authenticated">
<Layout flex grow no-gap>
<Layout flex grow style="--gap:16px;">
<Link :to="{ name: 'login' }"
solid
icon="bi-box-arrow-in-right"

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import type { BackendError } from '~/types'
import { computed, ref, onMounted } from 'vue'
import { computed, ref, onMounted, nextTick } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
@ -44,9 +44,6 @@ const submit = async () => {
isLoading.value = false
}
const emailInput = ref()
onMounted(() => emailInput.value.focus())
</script>
<template>