feat(ui): allow custom width (via composable props)

This commit is contained in:
upsiflu 2024-12-30 11:46:49 +01:00
parent a588726a54
commit 2ebda850c7
3 changed files with 44 additions and 16 deletions

View File

@ -105,7 +105,7 @@ const federationEnabled = computed(() => {
<Card :title="t('components.About.header.signup')"
v-if="!store.state.auth.authenticated"
style="--width:256px"
width="256px"
>
<template v-if="openRegistrations">
@ -156,7 +156,7 @@ const federationEnabled = computed(() => {
<Card :title="t('components.About.message.greeting', {username: store.state.auth.username})"
v-else
style="--width:256px"
width= "256px"
>
<p v-if="defaultUploadQuota">
@ -171,7 +171,7 @@ const federationEnabled = computed(() => {
</Card>
<Card :title="podName"
style="--width:256px"
width="256px"
>
<section
:class="['ui', 'head', {'with-background': banner}, 'vertical', 'center', 'aligned', 'stripe', 'segment']"
@ -234,7 +234,7 @@ const federationEnabled = computed(() => {
<Layout flex style="justify-content: center;">
<Card style="--width:256px"
<Card width="256px"
to="/"
:title="t('components.About.header.publicContent')"
icon="bi-box-arrow-up-right"
@ -243,7 +243,7 @@ const federationEnabled = computed(() => {
{{ t('components.About.description.publicContent') }}
</Card>
<Card style="--width:256px"
<Card width="256px"
:title="t('components.About.link.findOtherPod')"
to="https://funkwhale.audio/#get-started"
icon="bi-box-arrow-up-right"
@ -251,7 +251,7 @@ const federationEnabled = computed(() => {
{{ t('components.About.description.publicContent') }}
</Card>
<Card style="--width:256px"
<Card width="256px"
:title="t('components.About.header.findApp')"
to="https://funkwhale.audio/apps"
icon="bi-box-arrow-up-right"

View File

@ -1,4 +1,4 @@
import type { KeysOfUnion } from "type-fest"
import type { Entries, KeysOfUnion } from "type-fest"
export type WidthProps =
| { minContent?: true }
@ -8,9 +8,10 @@ export type WidthProps =
| { medium?: true }
| { auto?: true }
| { full?: true }
| { width?: string }
export type Key = KeysOfUnion<WidthProps>
const styles : Record<Key, string> = {
const styles = {
minContent: 'width: min-content;',
tiny: "width: 124px; grid-column: span 2;",
buttonWidth: "width: 136px; grid-column: span 2; flex-grow:0;",
@ -18,7 +19,19 @@ const styles : Record<Key, string> = {
medium: "width: 280px; grid-column: span 4;",
auto: "width: auto;",
full: "width: auto; grid-column: 1 / -1; align-self: auto; flex-grow:1;",
};
width: (w:string)=>`width: ${w}; flex-grow:0;`,
} as const satisfies Record<Key, string|((w:string)=>string)>;
const getStyle = (props : Partial<WidthProps>) => (key : Key) =>
(typeof styles[key] !== 'string' && key in props) ?
styles[key](
// TODO: Make the typescript compiler understand `key in props`
// @ts-ignore
props[key]
)
: styles[key]
// All keys are exclusive
const conflicts: Set<Key>[] = [
@ -30,22 +43,25 @@ const conflicts: Set<Key>[] = [
* Widths are designed to work both in a page-grid context and in a flex or normal context.
*
* (1) Add `& WidthProps` to your `Props` type
* (2) Call `v-bind="propsToWidth(props)"` on your component template
* (2) Call `v-bind="width(props)"` on your component template
* (3) Now your component accepts width props such as `small`, `medium`, `stretch`.
*
* @param props Your component's props (or ...rest props if you have destructured them already)
* @returns the corresponding `style` object
* @returns the corresponding `{ style }` object
*/
export const width = (props: Partial<WidthProps>, defaults: Key[] = []) => ({
export const width = <TProps extends Partial<WidthProps>>(
props: TProps,
defaults: Key[] = []
) => ({
style:
Object.entries(props).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 as Key)))
.concat([key as Key])
acc.filter(accKey => !conflicts.find(set => set.has(accKey) && set.has(key)))
.concat([key])
: acc
),
defaults
).map(key => styles[key])
).map(getStyle(props))
.join(' ')
})

View File

@ -26,6 +26,7 @@ const here = route.path
<Card small title='small' />
<Card medium title='medium' />
<Card auto title='auto' />
<Card width="170.5px" title='width=170.5px' />
<Card full title='full' />
```
@ -35,5 +36,16 @@ const here = route.path
<Card small title='small' />
<Card medium title='medium' />
<Card auto title='auto' />
<Card width="170.5px" title='width=170.5px' />
<Card full title='full' />
</Layout>
## Widths in the grid
::: details Default widths
![alt text](image-1.png)
:::
[Designing Pages — The grid](designing-pages#grid)