Vitral 0.2
Layout

UniformGrid

Uma grade de células iguais que calcula as linhas ou as colunas pelo número de filhos.

Importação

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

Quadrada, a partir dos filhos

Nem linhas nem colunas: a grade é o menor quadrado que comporta todos os filhos. Adicione alguns e veja-a crescer.

7 children
1
2
3
4
5
6
7
<script setup lang="ts">import { Button, UniformGrid } from '@vitral/vue';import { ref } from 'vue'; const count = ref(7);</script> <template>    <div class="controls">        <Button icon="minus" severity="secondary" aria-label="Remove a cell" :disabled="count <= 1" @click="count--" />        <Button icon="plus" severity="secondary" aria-label="Add a cell" @click="count++" />        <small style="color: var(--vt-text-muted-color)">{{ count }} children</small>    </div>    <UniformGrid class="frame square">        <div v-for="n in count" :key="n" class="box" :class="`c${((n - 1) % 5) + 1}`">{{ n }}</div>    </UniformGrid></template> <style scoped>.controls {    display: flex;    align-items: center;    gap: 0.5rem;    width: 100%;} .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);} .square {    max-width: 22rem;} .box {    --c: var(--vt-chart-1);    display: flex;    align-items: center;    justify-content: center;    min-height: 2.5rem;    padding: 0.375rem;    font-size: 0.8125rem;    text-align: center;    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>

Colunas dadas, linhas calculadas

columns="4" com dez filhos resulta em três linhas, cada uma da altura da célula mais alta.

1
2
3
4
5
A taller cell sets every row
7
8
9
10
<script setup lang="ts">import { UniformGrid } from '@vitral/vue';</script> <template>    <UniformGrid class="frame" :columns="4">        <div v-for="n in 10" :key="n" class="box" :class="[`c${((n - 1) % 5) + 1}`, { tall: n === 6 }]">{{ n === 6 ? 'A taller cell sets every row' : n }}</div>    </UniformGrid></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);} .box {    --c: var(--vt-chart-1);    display: flex;    align-items: center;    justify-content: center;    min-height: 2.5rem;    padding: 0.375rem;    font-size: 0.8125rem;    text-align: center;    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);} .tall {    min-height: 4.5rem;} .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>

FirstColumn

Um mês: sete colunas, e first-column definido como o dia da semana em que o mês começa.

setembro 2026
123456789101112131415161718192021222324252627282930
<script setup lang="ts">import { UniformGrid, useLocale } from '@vitral/vue';import { computed } from 'vue'; const { locale } = useLocale();const today = new Date();const monthStart = new Date(today.getFullYear(), today.getMonth(), 1);const daysInMonth = new Date(today.getFullYear(), today.getMonth() + 1, 0).getDate();const title = computed(() => `${locale.value.monthNames[today.getMonth()]} ${today.getFullYear()}`);const firstDay = computed(() => locale.value.firstDayOfWeek);const weekdays = computed(() => Array.from({ length: 7 }, (_, i) => locale.value.dayNamesMin[(i + firstDay.value) % 7]));const offset = computed(() => (monthStart.getDay() - firstDay.value + 7) % 7);</script> <template>    <div class="calendar">        <strong>{{ title }}</strong>        <UniformGrid :columns="7" :spacing="2" aria-hidden="true">            <span v-for="day in weekdays" :key="day" class="weekday">{{ day }}</span>        </UniformGrid>        <UniformGrid :columns="7" :first-column="offset" :spacing="2">            <span v-for="day in daysInMonth" :key="day" class="day" :class="{ today: day === today.getDate() }">{{ day }}</span>        </UniformGrid>    </div></template> <style scoped>.calendar {    display: flex;    flex-direction: column;    gap: 0.5rem;    width: 17rem;    padding: 0.75rem;    background: var(--vt-overlay-popover-background);    border: 1px solid var(--vt-overlay-popover-border-color);    border-radius: var(--vt-border-radius-lg);} .weekday {    font-size: 0.75rem;    text-align: center;    color: var(--vt-text-muted-color);} .day {    padding: 0.375rem 0;    text-align: center;    border-radius: var(--vt-border-radius-pill);} .day:hover {    background: var(--vt-content-hover-background);} .today {    color: var(--vt-primary-contrast-color);    background: var(--vt-primary-color);} .today:hover {    background: var(--vt-primary-hover-color);}</style>

API

Lido de packages/vue/src/components/UniformGrid/types.ts, então diz o que o componente aceita de fato.

Props

NomeTipoDescrição
rowsnumberNúmero de linhas. Omitido, é quantas os filhos precisarem.
columnsnumberNúmero de colunas. Omitido, é quantas os filhos precisarem; com as linhas também omitidas, a grade é quadrada.
firstColumnnumberCélulas vazias antes do primeiro filho. Vale quando `columns` está definido e o valor é menor que ele.
spacingnumber | stringEspaço entre as células. O padrão é o token `uniformgrid.spacing`.
asstring | Component—

Mais pt, dt e unstyled de BaseProps; veja pass-through e modo sem estilo.

Slots

NomeProps do slotDescrição
default——