refactor(ui): use similar props in Header as in Section; use visual style props from Heading component

This commit is contained in:
upsiflu 2025-03-23 21:34:38 +01:00
parent 5e0efff73f
commit 167e663661
19 changed files with 109 additions and 38 deletions

View File

@ -278,7 +278,10 @@ fetchOwnedApps()
main
stack
>
<Header :h1="t('components.auth.Settings.header.accountSettings')" />
<Header
page-heading
:h1="t('components.auth.Settings.header.accountSettings')"
/>
<Layout
form
@submit.prevent="submitSettings()"

View File

@ -121,7 +121,10 @@ const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value]
no-gap
align-left
>
<Header :h1="labels.title">
<Header
page-heading
:h1="labels.title"
>
<template #action>
<RadioButton
v-if="store.state.favorites.count > 0"

View File

@ -136,7 +136,10 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
stack
main
>
<Header :h1="t('components.library.Albums.header.browse')" />
<Header
page-heading
:h1="t('components.library.Albums.header.browse')"
/>
<Layout
form
flex

View File

@ -135,7 +135,9 @@ const paginateOptions = computed(() => sortedUniq([12, 30, 50, paginateBy.value]
stack
main
>
<Header :h1="t('components.library.Artists.header.browse')" />
<Header :h1="t('components.library.Artists.header.browse')"
page-heading
/>
<Layout
form
flex

View File

@ -70,7 +70,10 @@ fetchData()
main
stack
>
<Header :h1="t('components.Sidebar.header.explore')" />
<Header
page-heading
:h1="t('components.Sidebar.header.explore')"
/>
<album-widget
:filters="{scope: scope, playable: true, ordering: '-creation_date', ...qualityFilters}"
:limit="4"

View File

@ -137,6 +137,7 @@ const { to: upload } = useModal('upload')
main
>
<Header
page-heading
:h1="t('components.library.Podcasts.header.browse')"
/>
<Layout

View File

@ -119,7 +119,10 @@ const paginateOptions = computed(() => sortedUniq([12, 25, 50, paginateBy.value]
stack
gap-64
>
<Header :h1="t('components.library.Radios.header.browse')" />
<Header
page-heading
:h1="t('components.library.Radios.header.browse')"
/>
<Section
align-left
:h2="t('components.library.Radios.header.instance')"

View File

@ -1,5 +1,5 @@
<script setup lang="ts">
import type { RouterLinkProps } from 'vue-router'
import type { ComponentProps } from 'vue-component-type-helpers'
import { useAttrs } from 'vue'
import Layout from '~/components/ui/Layout.vue'
@ -12,18 +12,17 @@ const actionComponents
= { Button, Link }
const props = defineProps<{
[M in 'no-items' | 'tiny-items' | 'small-items' | 'medium-items']?: true }
& { [H in 'h1' | 'h2' | 'h3']?: string }
& { action?: { text: string } &(RouterLinkProps | { onClick: (...args: any[]) => void | Promise<void> }) }>()
const heading
= props.h1
? ({ h1: props.h1, pageHeading: true }) as const
: props.h2
? ({ h2: props.h2 }) as const
: ({ h3: props.h3 }) as const
const { style, ...fallthroughProps } = useAttrs()
columnsPerItem?: 1 | 2 | 3 | 4
alignLeft?: boolean
action?: { text: string } & (ComponentProps<typeof Link> | ComponentProps<typeof Button>)
icon?: string
} & {
[H in `h${ '1' | '2' | '3' | '4' | '5' | '6' }`]? : string
} & {
[S in 'page-heading' | 'section-heading' | 'subsection-heading' | 'caption' | 'title' | 'radio' | 'secondary' ]? : true
} & {
[Operation in 'expand' | 'collapse']?: () => void
}>()
</script>
<template>
@ -51,20 +50,34 @@ const { style, ...fallthroughProps } = useAttrs()
:size="68"
style="align-self: baseline;"
/>
<div
v-if="icon"
style="display: flex; justify-content: center; align-items: center; width: 48px;"
>
<i
:class="['bi', icon]"
style="font-size: 18px;"
/>
</div>
<slot name="topleft" />
<Heading
v-bind="heading"
style="align-self: baseline; padding:0 0 24px 0; margin:0;"
v-bind="props"
style="
align-self: baseline;
padding: 0 0 24px 0;
margin: 0;
"
/>
<Spacer grow />
<!-- Action! You can either specify `to` or `onClick`. -->
<component
:is="'onClick' in action ? actionComponents.Button : actionComponents.Link"
v-if="action"
:style="`margin-right: ${('primary' in props || 'secondary' in props || 'destructive' in props) ? '0px' : '-16px'}`"
thin-font
min-content
align-self="baseline"
v-bind="{...fallthroughProps, ...action}"
:class="$style.action"
v-bind="action"
>
{{ action?.text }}
</component>
@ -79,3 +92,10 @@ const { style, ...fallthroughProps } = useAttrs()
</Layout>
</Layout>
</template>
<style module lang="scss">
// Visually push ghost link and non-solid button to the edge
.action:global(.interactive:not(:is(.primary, .solid, .destructive, .secondary)):is(button, a.ghost)) {
margin-right: -16px;
}
</style>

View File

@ -100,15 +100,18 @@ const markAllAsRead = async () => {
<template>
<Layout
v-title="labels.title"
main
stack
v-title="labels.title"
class="main page-notifications"
>
<div
v-if="additionalNotifications"
>
<Header :h1="t('views.Notifications.header.messages')" />
<Header
page-heading
:h1="t('views.Notifications.header.messages')"
/>
<Layout flex>
<div
v-if="showInstanceSupportMessage"
@ -223,7 +226,10 @@ const markAllAsRead = async () => {
</Alert>
</Layout>
</div>
<Header :h1="t('views.Notifications.header.notifications')" />
<Header
page-heading
:h1="t('views.Notifications.header.notifications')"
/>
<Toggle
id="show-read-notifications"
v-model="filters.is_read"

View File

@ -45,7 +45,10 @@ const title = computed(() => labels.value[props.type])
</script>
<template>
<Header :h1="title" />
<Header
page-heading
:h1="title"
/>
<invitation-form v-if="type === 'invitations'" />
<accounts-table
v-if="type === 'accounts'"

View File

@ -180,7 +180,10 @@ await nextTick()
:class="['ui', {'loading': isLoading}]"
>
<Loader v-if="isLoading" />
<Header :h1="labels.settings" />
<Header
page-heading
:h1="labels.settings"
/>
<div
v-if="settingsData"
id="settings-grid"

View File

@ -22,8 +22,7 @@ const labels = computed(() => ({
<template>
<Header
align-left
no-items
page-heading
:h1="t('views.admin.library.EditsList.header.edits')"
/>
<edits-card-list

View File

@ -60,7 +60,10 @@ const createDomain = async () => {
form
@submit.prevent="createDomain"
>
<Header :h1="t('views.admin.moderation.DomainsList.header.domains')" />
<Header
page-heading
:h1="t('views.admin.moderation.DomainsList.header.domains')"
/>
<Alert
v-if="errors && errors.length > 0"
red

View File

@ -108,7 +108,10 @@ const labels = computed(() => ({
v-title="labels.reports"
stack
>
<Header :h1="t('views.admin.moderation.ReportsList.header.reports')" />
<Header
page-heading
:h1="t('views.admin.moderation.ReportsList.header.reports')"
/>
<div class="ui inline form">
<div class="fields">
<div class="ui field">

View File

@ -98,7 +98,10 @@ const labels = computed(() => ({
</script>
<template>
<Header :h1="t('views.admin.moderation.RequestsList.header.userRequests')" />
<Header
page-heading
:h1="t('views.admin.moderation.RequestsList.header.userRequests')"
/>
<Spacer />
<div class="ui inline form">
<div class="fields">

View File

@ -33,7 +33,8 @@ const { t } = useI18n()
>
<Header
align-left
medium-items
page-heading
:columns-per-item="4"
:h1="t('views.auth.ProfileBase.link.overview')"
>
<template #action>

View File

@ -99,7 +99,10 @@ const updateUploads = (count: number) => {
main
>
<Loader v-if="isLoading" />
<Header :h1="object.name">
<Header
page-heading
:h1="object.name"
>
<template #action>
<Popover>
<template #default="{ toggleOpen }">

View File

@ -84,6 +84,7 @@ const deleteRadio = async () => {
<Header
v-if="!isLoading && radio"
v-title="radio.name"
page-heading
:h1="radio.name"
/>
<h2 class="sub header">

View File

@ -11,13 +11,21 @@ import Header from '~/components/ui/Header.vue'
# Page header
Place the `Header` at the beginning of a page. Choose an appropriate heading level: `h1` or `h2` or `h3`. Choose `h1` unless the header is part of a page subsection or a modal.
Place the `Header` at the beginning of a page. Choose an appropriate heading level: `h1` or `h2` or `h3`. Choose `h1` unless the header is part of a page subsection or a modal. You can use all props for [Heading](../heading.md), including the [stylistic variants](../heading.md#visual-sizes-for-page-sections-and-subsections) such as `radio` or `page-heading`.
```vue-html
<Header h1="My title" />
<Header
page-heading
h1="My title"
/>
```
<Header h1="My title" />
<Header
page-heading
h1="My title"
/>
For a detailed explanation of the props, read [the entry on `Section`](section.md)
### Add an image