feat(ui-docs): minor improvements and corrections

This commit is contained in:
upsiflu 2024-12-19 14:57:04 +01:00
parent 008d8e2a8a
commit e1bd30eb9d
7 changed files with 196 additions and 123 deletions

View File

@ -9,15 +9,15 @@ import Alert from './Alert.vue'
import Layout from './Layout.vue';
import Spacer from './layout/Spacer.vue';
interface Props extends Partial<RouterLinkProps> {
const props = defineProps<{
title: string
category?: true | "h1" | "h2" | "h3" | "h4" | "h5"
image?: string | { src: string, style?: "withPadding" }
tags?: string[]
small?: true
}
const props = defineProps<Props & (PastelProps | ColorProps | DefaultProps) & RaisedProps & VariantProps>()
tags?: string[]
image?: string | { src: string, style?: "withPadding" }
icon?: string
} & Partial<RouterLinkProps> & (PastelProps | ColorProps | DefaultProps) & RaisedProps & VariantProps>()
const image = typeof props.image === 'string' ? { src: props.image } : props.image
@ -28,6 +28,65 @@ const isExternalLink = computed(() => {
// const fallbackWidth =
</script>
<template>
<Layout stack
:class="{ [$style.card]: true, [$style['is-category']]: category }"
style="--gap:16px"
v-bind="propsToColor({...(props.to? { interactive: true, solid: true, default: true } : {}), ...props})"
>
<!-- Link -->
<a v-if="props.to && isExternalLink" :class="$style.covering" :href="to?.toString()" target="_blank" />
<RouterLink v-if="props.to && !isExternalLink" :class="$style.covering" :to="props.to" />
<!-- Image -->
<div v-if="$slots.image" :class="$style.image">
<slot name="image" :src="image" />
</div>
<img v-else-if="image" :src="image?.src"
:class="{ [$style.image]: true, [$style['with-padding']]: image?.style === 'withPadding' }" />
<Spacer v-else :size="props.small? 4 : 12" />
<!-- Icon -->
<i v-if="props.icon" :class="[$style.icon, 'bi', icon]" />
<!-- Title -->
<component :class="$style.title" :is="typeof category === 'string' ? category : 'h6'">{{ title }}</component>
<!-- Content -->
<Alert blue v-if="$slots.alert" :class="$style.alert">
<slot name="alert" />
</Alert>
<div v-if="tags" :class="$style.tags">
<Pill v-for="tag in tags" :key="tag">
#{{ tag }}
</Pill>
</div>
<Layout no-gap v-if="$slots.default" :class="$style.content">
<slot />
</Layout>
<!-- Footer and Action -->
<div v-if="$slots.footer" :class="$style.footer">
<slot name="footer" />
</div>
<div v-if="$slots.action" :class="$style.action">
<slot name="action" />
</div>
<Spacer v-if="!$slots.footer && !$slots.action" :size="props.small? 8 : 16" />
</Layout>
</template>
<style module>
.card {
/* Override --width with your preferred value */
@ -76,6 +135,14 @@ const isExternalLink = computed(() => {
}
}
>.icon {
position: absolute;
top: var(--fw-card-padding);
right: var(--fw-card-padding);
font-size: 1.2rem;
}
>.title {
padding: 0 var(--fw-card-padding);
line-height: 1.3em;
@ -146,54 +213,3 @@ const isExternalLink = computed(() => {
}
}
</style>
<template>
<Layout stack
:class="{ [$style.card]: true, [$style['is-category']]: category }"
style="--gap:16px"
v-bind="propsToColor({...(props.to? { interactive: true, solid: true, default: true } : {}), ...props})"
>
<!-- Link -->
<a v-if="props.to && isExternalLink" :class="$style.covering" :href="to?.toString()" target="_blank" />
<RouterLink v-if="props.to && !isExternalLink" :class="$style.covering" :to="props.to"
/>
<!-- Image -->
<div v-if="$slots.image" :class="$style.image">
<slot name="image" :src="image" />
</div>
<img v-else-if="image" :src="image?.src"
:class="{ [$style.image]: true, [$style['with-padding']]: image?.style === 'withPadding' }" />
<Spacer v-else :size="props.small? 4 : 12" />
<!-- Content -->
<component :class="$style.title" :is="typeof category === 'string' ? category : 'h6'">{{ title }}</component>
<Alert blue v-if="$slots.alert" :class="$style.alert">
<slot name="alert" />
</Alert>
<div v-if="tags" :class="$style.tags">
<Pill v-for="tag in tags" :key="tag">
#{{ tag }}
</Pill>
</div>
<Layout no-gap v-if="$slots.default" :class="$style.content">
<slot />
</Layout>
<!-- Footer and Action -->
<div v-if="$slots.footer" :class="$style.footer">
<slot name="footer" />
</div>
<div v-if="$slots.action" :class="$style.action">
<slot name="action" />
</div>
<Spacer v-if="!$slots.footer && !$slots.action" :size="props.small? 8 : 16" />
</Layout>
</template>

View File

@ -1,6 +1,9 @@
<script setup lang="ts">
const props = defineProps<
{ columnWidth?: number, noGap?:true }
const props = defineProps<{
columnWidth?: number,
noGap?:true,
noRule?:true
}
& { [P in "stack" | "grid" | "flex" | "columns"]?: true }
& { [C in "nav" | "aside" | "header" | "footer" | "main"]?:true }>()
const columnWidth = props.columnWidth ?? 320
@ -41,7 +44,7 @@ const columnWidth = props.columnWidth ?? 320
column-count: auto;
column-width: calc(v-bind(columnWidth) * 1px);
display: block;
column-rule: 1px solid var(--border-color);
column-rule: 1px solid v-bind("noRule ? 'transparent' : 'var(--border-color)'");
}
&.grid {
display: grid;

View File

@ -7,11 +7,15 @@ const minSize = 32
const measure = ref()
console.log("SIZE", size)
watchEffect(() => { measure.value = {
size: `${Math.max(size, minSize)}px`,
margin: `${Math.min(size/2-minSize/2, 0)}px`
margin: `${(size-Math.max(size, minSize))/2}px`
}
})
console.log("MEASURE", measure)
</script>
<template>

View File

@ -24,7 +24,10 @@ const { Theme } = DefaultTheme
}
.language-template:has(~.preview){
flex-grow:1000;
flex-grow:1;
&~.preview{
flex-grow:0;
}
}
.preview,
@ -36,8 +39,8 @@ const { Theme } = DefaultTheme
&:not(.transparent){
background-color:var(--background-color);
box-shadow: 0px 0px 16px 16px var(--background-color);
margin-top:16px;
padding-top:0;
margin:16px 0;
padding:0;
}

View File

@ -301,17 +301,14 @@ You can override the promise state by passing a false `is-loading` prop.
You can use [Bootstrap Icons](https://icons.getbootstrap.com/) in your button component
::: info
Icon buttons shrink down to the icon size if you don't pass any content. If you want to keep the button at full width with just an icon, add `&nbsp;` into the slot.
Icon buttons shrink down to the icon size if you don't pass any content. If you want to keep the button at full width with just an icon, add `width=standard`
:::
```vue-html
<Button color="secondary" icon="bi-three-dots-vertical" />
<Button color="secondary" is-round icon="bi-x" />
<Button icon="bi-save" />
<Button color="destructive" icon="bi-trash">
<Button icon="bi-three-dots-vertical" />
<Button round icon="bi-x" />
<Button primary icon="bi-save" width="standard" />
<Button destructive icon="bi-trash">
Delete
</Button>
```

View File

@ -59,12 +59,6 @@ You have to set a title for the card by passing a `title` prop.
## Card as a Link
::: warning
TODO: Test if it works. Set up a mock router in vitest.
:::
Add a `:to` prop, either containing an external link (`"https://..."`) or a Vue Router destination:
<Layout flex>
@ -103,7 +97,7 @@ Category cards are basic cards that contain only a title. To create a category c
## Add an Image
Pass an image source to the `image` prop or set `image.src` and `image.style`.
Pass an image source to the `image` prop or set both `image.src` and `image.style` by passing an object.
<Layout :columnWidth="200" grid>
@ -112,31 +106,56 @@ Pass an image source to the `image` prop or set `image.src` and `image.style`.
style="--width:208px"
title="For music lovers"
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb">
</Card>
/>
<Card
style="--width:208px"
title="For music lovers"
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
style:'withPadding' }">
</Card>
style:'withPadding' }"
/>
```
<Layout stack class="preview">
<Card
title="For music lovers"
style="--width:208px"
title="For music lovers"
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb" />
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
/>
<Card
title="For music lovers"
style="--width:208px"
title="For music lovers"
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
style:'withPadding' }" />
:image="{ src:'https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb',
style:'withPadding' }"
/>
</Layout>
</Layout>
## Add an Icon
<Layout columns>
```vue-html{4}
<Card
title="Uploading..."
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
icon="bi-cloud-arrow-up-fill"
/>
```
<Layout class="preview">
<Card
title="Uploading..."
image="https://images.unsplash.com/photo-1524650359799-842906ca1c06?ixlib=rb-1.2.1&dl=te-nguyen-Wt7XT1R6sjU-unsplash.jpg&w=640&q=80&fm=jpg&crop=entropy&cs=tinysrgb"
icon="bi-cloud-arrow-up-fill"
/>
</Layout>
</Layout>
You can combine this prop with any other prop configuration. If you combine it with an image, keep an eye on the contrast ratio between the icon color and the image.
## Add an Alert
```vue-html{2-4}

View File

@ -18,7 +18,7 @@ const noGap = ref(true)
The following containers are responsive. Change your window's size or select a device preset from your browser's dev tools to see how layouts are affected by available space.
<Tabs>
<Tabs class="solid" style="border: 32px solid var(--background-color);border-radius: 8px;outline: 1px solid var(--border-color);margin: 0 -32px;">
<Tab title="Flex (default)" icon="⠖">
Items are laid out in a row and wrapped as they overflow the container.
@ -49,10 +49,10 @@ Find a list of all styles here: [Flexbox guide on css-tricks.com](https://css-tr
<Layout flex>
<div class="preview" style="font-size:11px; font-weight:bold; mix-blend-mode:luminosity;">
<Layout flex style="--gap: 4px;"> --gap: 4px
<Alert style="align-self: flex-end">align-self: flex-end</Alert>
<Alert style="flex-grow: 1">flex-grow: 1</Alert>
<Alert style="height: 5rem;">height: 5rem</Alert>
<Alert style="width: 100%">width: 100%</Alert>
<Alert red style="align-self: flex-end">align-self: flex-end</Alert>
<Alert red style="flex-grow: 1">flex-grow: 1</Alert>
<Alert red style="height: 5rem;">height: 5rem</Alert>
<Alert red style="width: 100%">width: 100%</Alert>
</Layout>
</div>
</Layout>
@ -76,8 +76,7 @@ Align items both vertically and horizontally
</Layout>
```
<div class="preview">
<Layout grid :column-width=90>
<Layout grid :column-width="90" class="preview" :style="`width:${2 * 90 + 32}px`">
<Alert>A</Alert>
<Alert>B</Alert>
<Alert>C</Alert>
@ -86,7 +85,6 @@ Align items both vertically and horizontally
<Alert>F</Alert>
<Alert>G</Alert>
</Layout>
</div>
</Layout>
@ -156,7 +154,7 @@ Add space between vertically stacked items
Let items flow like words on a printed newspaper, Great for very long lists of buttons or links.
<Layout stack>
<Layout stack no-gap>
```vue-html
<Layout columns :column-width="120">
@ -198,6 +196,32 @@ Normal paragraph. Text flows like in a newspaper. Set the column width in px. Co
</Layout>
### `no-rule`: Remove the rule (thin line) between columns
<Layout grid>
```vue-html
<Layout columns colummn-width>
<div>Lorem ipsum dolor sit amet.</div>
</Layout>
<Layout columns no-rule>
<div>Lorem ipsum dolor sit amet.</div>
</Layout>
```
<Layout class="preview">
<Layout columns :column-width="120">
<div>Lorem ipsum dolor sit amet.</div>
</Layout>
<Layout columns no-rule :column-width="120">
<div>Lorem ipsum dolor sit amet.</div>
</Layout>
</Layout>
</Layout>
</Tab>
</Tabs>
@ -217,24 +241,24 @@ const noGap = ref(true);
<Toggle v-model="noGap" />
<Layout flex :no-gap="noGap || undefined">
<Card title="A" style="width:100px; min-width:100px" />
<Card title="B" />
<Card title="C" style="width:100px; min-width:100px" />
<Card title="D" />
<Card title="A" small />
<Card title="B" small />
<Card title="C" small />
<Card title="D" small />
</Layout>
</template>
```
<div class="preview">
<div class="preview" style="width:0">
<Toggle v-model="noGap" /> {{ noGap ? 'no-gap' : '-' }}
---
<Layout flex :no-gap="noGap || undefined">
<Card title="A" style="width:100px; min-width:100px" />
<Card title="B" />
<Card title="C" style="width:100px; min-width:100px" />
<Card title="D" />
<Card title="A" small />
<Card title="B" small />
<Card title="C" small />
<Card title="D" small />
</Layout>
</div>
@ -242,6 +266,13 @@ const noGap = ref(true);
### Add fixed or flexible Spacers
::: info Only available on:
- **stack**
- **flex**
:::
If you add a spacer with attribute `grow`, it will push the other item until the Layout fills the available space. This only works if the parent element itself grows beyond its minimal contents.
<Layout flex>
@ -254,11 +285,11 @@ const isGrowing = ref(true);
<template>
<Toggle v-model="isGrowing" />
<Layout stack style="height:30em;">
<Alert>A</Alert>
<Alert>B</Alert>
<Layout stack style="height:20em;">
<Alert red />
<Alert purple />
<Spacer :grow="isGrowing || undefined" />
<Alert>C (footer)</Alert>
<Alert blue />
</Layout>
</template>
```
@ -268,11 +299,11 @@ const isGrowing = ref(true);
---
<Layout stack style="height:30em; background:rgba(155,200,20,.3)">
<Alert>A</Alert>
<Alert>B</Alert>
<Spacer :grow="isGrowing || undefined" />
<Alert>C (footer)</Alert>
<Layout stack style="height:20em">
<Alert red />
<Alert purple />
<Spacer :grow="isGrowing || undefined" />
<Alert blue />
</Layout>
</div>
@ -280,7 +311,7 @@ const isGrowing = ref(true);
Multiple spacers will distribute their growth evenly.
Note that you can set the minimum space occupied by the `Spacer` with its `size` prop [(docs)](layout/spacer). Negative values can offset the gap of the `Layout`:
Note that you can set the minimum space occupied by the `Spacer` with its `size` prop [(docs)](layout/spacer). Negative values can offset the gap of the `Layout` (but, due to a limitation of flexbox, not eat into the space occupied by adjacent items):
<Layout flex>
@ -289,12 +320,12 @@ Note that you can set the minimum space occupied by the `Spacer` with its `size`
<Toggle v-model="isGrowing" />
<Layout stack style="height:25em;">
<Alert>A</Alert>
<Alert blue />
<Spacer :size="-32" :grow="isGrowing || undefined" />
<Alert>B1</Alert>
<Alert>B2</Alert>
<Alert green />
<Alert yellow />
<Spacer :size="-32" :grow="isGrowing || undefined" />
<Alert>C (footer)</Alert>
<Alert red />
</Layout>
</template>
```
@ -304,13 +335,13 @@ Note that you can set the minimum space occupied by the `Spacer` with its `size`
---
<Layout stack style="height:25em; background:rgba(155,200,20,.3)">
<Alert>A</Alert>
<Layout stack style="height:25em;">
<Alert blue />
<Spacer :size="-32" :grow="isGrowing || undefined" />
<Alert>B1</Alert>
<Alert>B2</Alert>
<Alert green />
<Alert yellow />
<Spacer :size="-32" :grow="isGrowing || undefined" />
<Alert>C (footer)</Alert>
<Alert red />
</Layout>
</div>