refactor(ui): layout section header without subdivision ('no-items') for use case with only full-width items

This commit is contained in:
upsiflu 2025-01-06 20:32:47 +01:00
parent f39b3353a3
commit adf3bffc9b
2 changed files with 18 additions and 7 deletions

View File

@ -7,7 +7,7 @@ import Button from '~/components/ui/Button.vue'
import Link from '~/components/ui/Link.vue'
const props = defineProps<{
[M in 'tiny-items' | 'small-items' | 'medium-items']?: true }
[M in 'no-items' | 'tiny-items' | 'small-items' | 'medium-items']?: true }
& { alignLeft?: boolean;}
& { [H in 'h1' | 'h2' | 'h3']?: string }
& { action?: { text: string } & (RouterLinkProps | { onClick: (...args: any[]) => void | Promise<void> }) }>()
@ -18,7 +18,8 @@ const [headingLevel, title] =
: ['h3', props.h3]
const numberOfColumnsPerItem =
'tinyItems' in props && props.tinyItems ? 2 : 'smallItems' in props && props['smallItems'] ? 3 : 4
'noItems' in props && props.noItems ? 1 : 'tinyItems' in props && props.tinyItems ? 2 : 'smallItems' in props && props['smallItems'] ? 3 : 4
const headerGrid =
`auto / repeat(auto-fit, calc(46px * ${numberOfColumnsPerItem} + 32px * ${numberOfColumnsPerItem - 1}))`
@ -27,7 +28,8 @@ const headerGrid =
<template>
<section>
<Layout header :grid="headerGrid"
:style="`${'alignLeft' in props && props.alignLeft ? 'justify-content: start' : ''}; margin-top: -64px;`"
:style="`${'alignLeft' in props && props.alignLeft ? 'justify-content: start' : ''};
margin-top: -64px;`"
>
<!-- The title row's width is a multiple of the expected items' column span -->
@ -41,14 +43,14 @@ const headerGrid =
/>
<!-- Flexible row content -->
<!-- Note that the `h3` uses its padding to create the 24px bottom gap -->
<component :is="headingLevel" style="align-self: baseline; padding:0 0 24px 10px; margin:0;">
<component :is="headingLevel" style="align-self: baseline; padding:0 0 24px 0; margin:0;">
{{ title }}
</component>
<Spacer grow />
<!-- Action! You can either specify `to` or `onClick`. -->
<Button v-if="props.action && 'onClick' in props.action"
ghost thinFont auto align-self="baseline"
style="grid-column:-1;"
ghost thin-font minWidth align-self="baseline"
:style="`margin-right: ${('primary' in props || 'secondary' in props || 'destructive' in props) ? '0px' : '-16px'}`"
:onClick="props.action.onClick"
v-bind="$attrs"
>
@ -56,6 +58,7 @@ const headerGrid =
</Button>
<Link v-if="props.action && 'to' in props.action"
ghost force-underline thinFont align-self="baseline"
:style="`margin-right: ${('primary' in props || 'secondary' in props || 'destructive' in props) ? '0px' : '-16px'}`"
:to="props.action.to"
v-bind="$attrs"
>

View File

@ -122,7 +122,9 @@ Sections divide the page vertically. Choose an appropriate heading level for eac
### Make the section header align with the section contents
Do you want to align the header to tiny, small or medium items?
Do you want to align the header to no, tiny, small or medium items?
If all items stretch all columns (`style=grid-column: 1 / -1`), use `no-items`.
```vue-html
<Section medium-items />
@ -180,6 +182,12 @@ You can add spacers (negatice or positive) if you want to manually make one dist
:::
::: tip Let items cover the whole grid width
To prevent items from being put on a grid, add `style="grid-column: 1 / -1"` which means that they span "all existing columns".
:::
## Example
```vue-html