Stack

Lays its children out in a single column.

Create a list

Works can be added to it at any time.

Name

<script setup lang="ts">
  import { Button, Card, Heading, Input, Stack, Text } from '@hina-ui/vue'
</script>

<template>
  <Card class="w-full max-w-sm">
    <Stack>
      <Stack gap="xs">
        <Heading :level="3" size="md">Create a list</Heading>
        <Text tone="muted" size="sm">Works can be added to it at any time.</Text>
      </Stack>
      <Stack gap="xs">
        <Text size="sm">Name</Text>
        <Input model-value="Light novels I read this year" />
      </Stack>
      <Button>Create</Button>
    </Stack>
  </Card>
</template>
vue

Usage

import { Stack } from '@hina-ui/vue'
ts

Stack is a vertical flex container: its children run down the page, spaced by gap.

First item
Second item
Third item
<script setup lang="ts">
  import { Card, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack class="w-full max-w-xs">
    <Card>First item</Card>
    <Card>Second item</Card>
    <Card>Third item</Card>
  </Stack>
</template>
vue

Examples

Gap

gap takes steps rather than arbitrary values. The default md comes from --hn-stack-gap, which is 16 pixels at the regular density and 12 at the compact one; the other five steps are 0, 4, 8, 24 and 32 pixels.

none

xs

sm

md

lg

xl

<script setup lang="ts">
  import { Card, Inline, Stack, Text } from '@hina-ui/vue'

  const gaps = ['none', 'xs', 'sm', 'md', 'lg', 'xl'] as const
</script>

<template>
  <Inline align="start" class="gap-8">
    <Stack v-for="gap in gaps" :key="gap" gap="xs">
      <Text tone="muted" size="sm">{{ gap }}</Text>
      <Stack :gap="gap">
        <Card class="bg-inset size-10" :padded="false" />
        <Card class="bg-inset size-10" :padded="false" />
        <Card class="bg-inset size-10" :padded="false" />
      </Stack>
    </Stack>
  </Inline>
</template>
vue

Cross-axis alignment

align decides how the children line up horizontally. Left unset, they stretch to the width of the container, which is what flex does on its own.

start

center

end

stretch

<script setup lang="ts">
  import { Button, Inline, Stack, Text } from '@hina-ui/vue'

  const aligns = ['start', 'center', 'end', 'stretch'] as const
</script>

<template>
  <Inline align="start" class="gap-6">
    <Stack v-for="align in aligns" :key="align" gap="xs" class="w-44">
      <Text tone="muted" size="sm">{{ align }}</Text>
      <Stack :align="align" gap="sm" class="bg-inset rounded-md p-3">
        <Button size="sm" variant="soft" tone="neutral">Short</Button>
        <Button size="sm" variant="soft" tone="neutral">A longer button</Button>
      </Stack>
    </Stack>
  </Inline>
</template>
vue

Main-axis distribution

justify decides how the children are distributed vertically, which shows only once the container has a height of its own. between pushes the first and last to the ends.

Storage

12.4 GB used of 20 GB.

<script setup lang="ts">
  import { Button, Card, Heading, Stack, Text } from '@hina-ui/vue'
</script>

<template>
  <Card class="h-64 w-full max-w-xs">
    <Stack justify="between" class="h-full">
      <Stack gap="xs">
        <Heading :level="3" size="md">Storage</Heading>
        <Text tone="muted" size="sm">12.4 GB used of 20 GB.</Text>
      </Stack>
      <Button variant="soft" tone="neutral">Upgrade</Button>
    </Stack>
  </Card>
</template>
vue

Root element

as changes the rendered tag; use ul or ol for a list.

It also accepts Vue components, such as :as="RouterLink" or :as="NuxtLink". Import the component or obtain it through resolveComponent; object, functional and async components are supported. Layout classes, extra attributes, event listeners and the default slot are forwarded without an extra wrapper. Custom components must forward attributes and classes to their rendered root.

  • Items render as li
  • The container renders as ul
<script setup lang="ts">
  import { Card, Stack } from '@hina-ui/vue'
</script>

<template>
  <Stack as="ul" gap="sm" class="w-full max-w-xs">
    <Card as="li">Items render as li</Card>
    <Card as="li">The container renders as ul</Card>
  </Stack>
</template>
vue

API

Prop
Type
Default
Description
gap
'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl'
'md'
Space between the children
align
'start' | 'center' | 'end' | 'stretch'
—
Cross-axis alignment
justify
'start' | 'center' | 'end' | 'between' | 'around' | 'evenly'
—
Main-axis distribution
as
string | Component
'div'
The rendered tag or Vue component
class
string
—
Classes appended to the container
Slot
Description
default
The children