Vitral 0.2
Layout

WrapPanel

Lays children out in a line and wraps to the next when it is full, across or down, with an optional uniform size.

Import

main.ts
import { WrapPanel } from '@vitral/vue';

Horizontal

Each child keeps its own width. Drag the frame's corner to resize it and watch the lines re-flow.

ButtonCheckBoxComboBoxDatePickerExpanderGridListBoxMenuNumericUpDownProgressBarRadioButtonSliderSplitViewTabControlTextBoxToggleSwitchTreeView
<script setup lang="ts">import { WrapPanel } from '@vitral/vue'; const words = ['Button', 'CheckBox', 'ComboBox', 'DatePicker', 'Expander', 'Grid', 'ListBox', 'Menu', 'NumericUpDown', 'ProgressBar', 'RadioButton', 'Slider', 'SplitView', 'TabControl', 'TextBox', 'ToggleSwitch', 'TreeView'];</script> <template>    <WrapPanel class="frame resizable">        <span v-for="(word, i) in words" :key="word" class="box" :class="`c${(i % 5) + 1}`">{{ word }}</span>    </WrapPanel></template> <style scoped>.frame {    width: 100%;    padding: 0.5rem;    border: 1px dashed color-mix(in srgb, var(--vt-text-color) 30%, transparent);    border-radius: var(--vt-border-radius-md);} .resizable {    resize: horizontal;    overflow: auto;    min-width: 12rem;} .box {    --c: var(--vt-chart-1);    padding: 0.375rem 0.625rem;    font-size: 0.8125rem;    color: var(--vt-text-color);    background: color-mix(in srgb, var(--c) 18%, transparent);    border: 1px solid color-mix(in srgb, var(--c) 55%, transparent);    border-radius: var(--vt-border-radius-sm);} .c1 {    --c: var(--vt-chart-1);} .c2 {    --c: var(--vt-chart-2);} .c3 {    --c: var(--vt-chart-3);} .c4 {    --c: var(--vt-chart-4);} .c5 {    --c: var(--vt-chart-5);}</style>

ItemWidth and ItemHeight

item-width="120" item-height="72": every child the same size, whatever its content.

Photos
Mail
Maps
Music
Video
News
Store
Weather
Clock
Notes
<script setup lang="ts">import { WrapPanel } from '@vitral/vue'; const tiles = ['Photos', 'Mail', 'Maps', 'Music', 'Video', 'News', 'Store', 'Weather', 'Clock', 'Notes'];</script> <template>    <WrapPanel class="frame resizable" :item-width="120" :item-height="72" :spacing="8">        <div v-for="(tile, i) in tiles" :key="tile" class="box tile" :class="`c${(i % 5) + 1}`">{{ tile }}</div>    </WrapPanel></template> <style scoped>.frame {    width: 100%;    padding: 0.5rem;    border: 1px dashed color-mix(in srgb, var(--vt-text-color) 30%, transparent);    border-radius: var(--vt-border-radius-md);} .resizable {    resize: horizontal;    overflow: auto;    min-width: 12rem;} .box {    --c: var(--vt-chart-1);    padding: 0.375rem 0.625rem;    font-size: 0.8125rem;    color: var(--vt-text-color);    background: color-mix(in srgb, var(--c) 18%, transparent);    border: 1px solid color-mix(in srgb, var(--c) 55%, transparent);    border-radius: var(--vt-border-radius-sm);} .tile {    display: flex;    align-items: flex-end;    font-weight: 600;} .c1 {    --c: var(--vt-chart-1);} .c2 {    --c: var(--vt-chart-2);} .c3 {    --c: var(--vt-chart-3);} .c4 {    --c: var(--vt-chart-4);} .c5 {    --c: var(--vt-chart-5);}</style>

Vertical

Fills columns top to bottom; needs a height to wrap in.

ButtonCheckBoxComboBoxDatePickerExpanderGridListBoxMenuNumericUpDownProgressBarRadioButtonSliderSplitViewTabControlTextBoxToggleSwitchTreeView
<script setup lang="ts">import { WrapPanel } from '@vitral/vue'; const words = ['Button', 'CheckBox', 'ComboBox', 'DatePicker', 'Expander', 'Grid', 'ListBox', 'Menu', 'NumericUpDown', 'ProgressBar', 'RadioButton', 'Slider', 'SplitView', 'TabControl', 'TextBox', 'ToggleSwitch', 'TreeView'];</script> <template>    <WrapPanel class="frame short" orientation="vertical" :item-width="140">        <span v-for="(word, i) in words" :key="word" class="box" :class="`c${(i % 5) + 1}`">{{ word }}</span>    </WrapPanel></template> <style scoped>.frame {    width: 100%;    padding: 0.5rem;    border: 1px dashed color-mix(in srgb, var(--vt-text-color) 30%, transparent);    border-radius: var(--vt-border-radius-md);} .short {    height: 10rem;    overflow: auto;} .box {    --c: var(--vt-chart-1);    padding: 0.375rem 0.625rem;    font-size: 0.8125rem;    color: var(--vt-text-color);    background: color-mix(in srgb, var(--c) 18%, transparent);    border: 1px solid color-mix(in srgb, var(--c) 55%, transparent);    border-radius: var(--vt-border-radius-sm);} .c1 {    --c: var(--vt-chart-1);} .c2 {    --c: var(--vt-chart-2);} .c3 {    --c: var(--vt-chart-3);} .c4 {    --c: var(--vt-chart-4);} .c5 {    --c: var(--vt-chart-5);}</style>

API

Read from packages/vue/src/components/WrapPanel/types.ts, so it says what the component actually accepts.

Props

NameTypeDescription
orientation'vertical' | 'horizontal'`horizontal` (the default) fills rows and wraps downwards; `vertical` fills columns and needs a height to wrap in.
itemWidthnumber | stringEvery child gets this width. A number of pixels or any CSS length.
itemHeightnumber | stringEvery child gets this height.
spacingnumber | stringSpace between children and between lines. Defaults to the `wrappanel.spacing` token.
asstring | Component—

Plus pt, dt and unstyled from BaseProps, see pass-through and unstyled mode.

Slots

NameSlot propsDescription
default——