318 lines
6.9 KiB
Markdown
318 lines
6.9 KiB
Markdown
<script setup lang="ts">
|
|
import { ref } from 'vue'
|
|
|
|
import Card from '~/components/ui/Card.vue'
|
|
import Alert from '~/components/ui/Alert.vue'
|
|
import Layout from '~/components/ui/Layout.vue'
|
|
import Spacer from '~/components/ui/layout/Spacer.vue'
|
|
import Tab from '~/components/ui/Tab.vue'
|
|
import Tabs from '~/components/ui/Tabs.vue'
|
|
import Toggle from '~/components/ui/Toggle.vue'
|
|
import Button from '~/components/ui/Button.vue'
|
|
|
|
const isGrowing = ref(true)
|
|
const noGap = ref(true)
|
|
</script>
|
|
|
|
# Layout
|
|
|
|
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>
|
|
<Tab title="Flex (default)" icon="⠖">
|
|
|
|
Items are laid out in a row and wrapped as they overflow the container.
|
|
By default, all items in a row assume the same (maximum) height.
|
|
|
|
```vue-html
|
|
<Layout flex>
|
|
<Card title="A" style="width:100px; min-width:100px"></Card>
|
|
<Card title="B" :tags="['funk', 'dunk', 'punk']"></Card>
|
|
<Card title="C" style="width:100px; min-width:100px"></Card>
|
|
<Card title="D"></Card>
|
|
</Layout>
|
|
```
|
|
|
|
<div class="preview">
|
|
<Layout flex>
|
|
<Card title="A" style="width:100px; min-width:100px"></Card>
|
|
<Card title="B" :tags="['funk', 'dunk', 'punk']"></Card>
|
|
<Card title="C" style="width:100px; min-width:100px"></Card>
|
|
<Card title="D"></Card>
|
|
</Layout>
|
|
</div>
|
|
|
|
::: info Use additional `flexbox` properties
|
|
|
|
Find a list of all styles here: [Flexbox guide on css-tricks.com](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
|
|
|
|
<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>
|
|
</Layout>
|
|
</div>
|
|
</Layout>
|
|
|
|
:::
|
|
|
|
</Tab>
|
|
<Tab title="Grid" icon="ꖛ">
|
|
|
|
Align items both vertically and horizontally
|
|
|
|
##### Override the `:column-width` (in px):
|
|
|
|
<Layout flex>
|
|
|
|
```vue-html{1}
|
|
<Layout grid :column-width=90>
|
|
<Alert>A</Alert>
|
|
<Alert>B</Alert>
|
|
...
|
|
</Layout>
|
|
```
|
|
|
|
<div class="preview">
|
|
<Layout grid :column-width=90>
|
|
<Alert>A</Alert>
|
|
<Alert>B</Alert>
|
|
<Alert>C</Alert>
|
|
<Alert>D</Alert>
|
|
<Alert>E</Alert>
|
|
<Alert>F</Alert>
|
|
<Alert>G</Alert>
|
|
</Layout>
|
|
</div>
|
|
|
|
</Layout>
|
|
|
|
##### Let elements span multiple rows or columns:
|
|
|
|
```vue-html{2,4}
|
|
<Layout grid>
|
|
<Card title="A" class="span-2-columns"></Card>
|
|
<Card title="B"></Card>
|
|
<Card title="C" class="span-2-rows"></Card>
|
|
<Card title="D"></Card>
|
|
</Layout>
|
|
```
|
|
|
|
<Layout grid>
|
|
<Card title="A" class="span-2-columns">
|
|
|
|
```vue
|
|
<Card class="span-2-columns"></Card>
|
|
```
|
|
|
|
</Card>
|
|
<Card title="B"></Card>
|
|
<Card title="C" class="span-2-rows">
|
|
|
|
```vue
|
|
<Card class="span-2-rows"></Card>
|
|
```
|
|
|
|
</Card>
|
|
<Card title="D"></Card>
|
|
</Layout>
|
|
|
|
</Tab>
|
|
|
|
<Tab title="Stack" icon="𝌆">
|
|
|
|
Add space between vertically stacked items
|
|
|
|
<Layout flex>
|
|
|
|
```vue-html
|
|
<Layout stack>
|
|
<Card title="A"></Card>
|
|
<Card title="B"></Card>
|
|
<Card title="C"></Card>
|
|
<Card title="D"></Card>
|
|
<Card title="E"></Card>
|
|
</Layout>
|
|
```
|
|
|
|
<div class="preview">
|
|
<Layout stack>
|
|
<Card title="A"></Card>
|
|
<Card title="B"></Card>
|
|
<Card title="C"></Card>
|
|
<Card title="D"></Card>
|
|
<Card title="E"></Card>
|
|
</Layout>
|
|
</div>
|
|
|
|
</Layout>
|
|
|
|
</Tab>
|
|
|
|
<Tab title="Columns" icon="𝌆">
|
|
|
|
Let items flow like words on a printed newspaper, Great for very long lists of buttons or links.
|
|
|
|
<Layout stack>
|
|
|
|
```vue-html
|
|
<Layout columns :column-width="120">
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
|
|
Normal paragraph. Text flows like in a newspaper. Set the column width in px. Columns will be equally distributed over the width of the container.
|
|
|
|
<Card small title="Cards...">...break over columns...</Card>
|
|
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
</Layout>
|
|
```
|
|
|
|
<div class="preview">
|
|
<Layout columns :column-width="120">
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
|
|
---
|
|
|
|
Normal paragraph. Text flows like in a newspaper. Set the column width in px. Columns will be equally distributed over the width of the container.
|
|
|
|
---
|
|
|
|
<Card small title="Cards...">...break over columns...</Card>
|
|
|
|
---
|
|
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
<Button icon="bi-star"/>
|
|
</Layout>
|
|
</div>
|
|
|
|
</Layout>
|
|
|
|
</Tab>
|
|
|
|
</Tabs>
|
|
|
|
## Common props
|
|
|
|
### `no-gap`: Remove the gap between items
|
|
|
|
<Layout flex>
|
|
|
|
```vue
|
|
<script setup>
|
|
const noGap = ref(true);
|
|
</script>
|
|
|
|
<template>
|
|
<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" />
|
|
</Layout>
|
|
</template>
|
|
```
|
|
|
|
<div class="preview">
|
|
<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" />
|
|
</Layout>
|
|
</div>
|
|
|
|
</Layout>
|
|
|
|
### Add fixed or flexible Spacers
|
|
|
|
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>
|
|
|
|
```vue
|
|
<script setup>
|
|
const isGrowing = ref(true);
|
|
</script>
|
|
|
|
<template>
|
|
<Toggle v-model="isGrowing" />
|
|
|
|
<Layout stack style="height:30em;">
|
|
<Alert>A</Alert>
|
|
<Alert>B</Alert>
|
|
<Spacer :grow="isGrowing || undefined" />
|
|
<Alert>C (footer)</Alert>
|
|
</Layout>
|
|
</template>
|
|
```
|
|
|
|
<div class="preview">
|
|
<Toggle v-model="isGrowing" /> {{ isGrowing ? 'grow' : '-' }}
|
|
|
|
---
|
|
|
|
<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>
|
|
</div>
|
|
|
|
</Layout>
|
|
|
|
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`:
|
|
|
|
<Layout flex>
|
|
|
|
```vue
|
|
<template>
|
|
<Toggle v-model="isGrowing" />
|
|
|
|
<Layout stack style="height:25em;">
|
|
<Alert>A</Alert>
|
|
<Spacer :size="-32" :grow="isGrowing || undefined" />
|
|
<Alert>B1</Alert>
|
|
<Alert>B2</Alert>
|
|
<Spacer :size="-32" :grow="isGrowing || undefined" />
|
|
<Alert>C (footer)</Alert>
|
|
</Layout>
|
|
</template>
|
|
```
|
|
|
|
<div class="preview" style="width:0">
|
|
<Toggle v-model="isGrowing" />
|
|
|
|
---
|
|
|
|
<Layout stack style="height:25em; background:rgba(155,200,20,.3)">
|
|
<Alert>A</Alert>
|
|
<Spacer :size="-32" :grow="isGrowing || undefined" />
|
|
<Alert>B1</Alert>
|
|
<Alert>B2</Alert>
|
|
<Spacer :size="-32" :grow="isGrowing || undefined" />
|
|
<Alert>C (footer)</Alert>
|
|
</Layout>
|
|
</div>
|
|
|
|
</Layout>
|