Inline

Lays its children out in a row, wrapping when they run out of room.

Shion Hoshimi

Shion Hoshimi

Translator

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

<template>
  <Card class="w-full max-w-md">
    <Inline justify="between">
      <Inline gap="sm">
        <Avatar size="lg" src="/avatars/selfie.webp" alt="Shion Hoshimi" />
        <Stack gap="none">
          <Text class="font-medium">Shion Hoshimi</Text>
          <Text tone="muted" size="sm">Translator</Text>
        </Stack>
      </Inline>
      <Inline gap="xs">
        <Tag>Verified</Tag>
        <Button size="sm" variant="soft" tone="neutral">Follow</Button>
      </Inline>
    </Inline>
  </Card>
</template>
vue

Usage

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

Inline is a horizontal flex container: its children sit centred on the cross axis and wrap when they run out of room.

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

<template>
  <Inline>
    <Button variant="soft" tone="neutral">Save</Button>
    <Button variant="soft" tone="neutral">Save as</Button>
    <Button variant="soft" tone="neutral">Export</Button>
  </Inline>
</template>
vue

Examples

Gap

gap takes steps rather than arbitrary values. The default md comes from --hn-inline-gap, which is 12 pixels at the regular density and 8 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>
  <Stack>
    <Stack v-for="gap in gaps" :key="gap" gap="xs">
      <Text tone="muted" size="sm">{{ gap }}</Text>
      <Inline :gap="gap">
        <Card class="bg-inset size-8" :padded="false" />
        <Card class="bg-inset size-8" :padded="false" />
        <Card class="bg-inset size-8" :padded="false" />
      </Inline>
    </Stack>
  </Stack>
</template>
vue

Cross-axis alignment

align decides how the children line up vertically; the default is centred. Use baseline when the text sizes differ, so the baselines line up instead of the boxes.

start

Heading

Body

Note

center

Heading

Body

Note

end

Heading

Body

Note

baseline

Heading

Body

Note

stretch

Heading

Body

Note

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

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

<template>
  <Stack>
    <Stack v-for="align in aligns" :key="align" gap="xs">
      <Text tone="muted" size="sm">{{ align }}</Text>
      <Inline :align="align" class="bg-inset rounded-md p-3">
        <Heading :level="3" size="xl">Heading</Heading>
        <Text>Body</Text>
        <Text tone="muted" size="sm">Note</Text>
      </Inline>
    </Stack>
  </Stack>
</template>
vue

Main-axis distribution

justify decides how the children are distributed horizontally. between pushes the first and last to the ends, which is how a heading row with a trailing button is written.

Reading history

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

<template>
  <Inline justify="between" class="bg-inset w-full rounded-md p-3">
    <Heading :level="3" size="md">Reading history</Heading>
    <Button size="sm" variant="soft" tone="neutral">Clear all</Button>
  </Inline>
</template>
vue

Wrapping

wrap defaults to true. Set it to false to keep everything on one line, together with overflow handling on the container around it.

wrap defaults to true, so items wrap when they run out of room

Sci-fiMysterySchoolComing of ageHealingSlice of lifeEnsembleIsekai

With wrap false they stay on one line

Sci-fiMysterySchoolComing of ageHealingSlice of lifeEnsembleIsekai
<script setup lang="ts">
  import { Inline, Stack, Tag, Text } from '@hina-ui/vue'

  const tags = [
    'Sci-fi',
    'Mystery',
    'School',
    'Coming of age',
    'Healing',
    'Slice of life',
    'Ensemble',
    'Isekai',
  ]
</script>

<template>
  <Stack class="w-full max-w-sm">
    <Stack gap="xs">
      <Text tone="muted" size="sm">
        wrap defaults to true, so items wrap when they run out of room
      </Text>
      <Inline gap="xs">
        <Tag v-for="tag in tags" :key="tag">{{ tag }}</Tag>
      </Inline>
    </Stack>
    <Stack gap="xs">
      <Text tone="muted" size="sm">With wrap false they stay on one line</Text>
      <Inline :wrap="false" gap="xs" class="overflow-hidden">
        <Tag v-for="tag in tags" :key="tag">{{ tag }}</Tag>
      </Inline>
    </Stack>
  </Stack>
</template>
vue

Root element

as changes the rendered tag; use nav for navigation.

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.

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

<template>
  <Inline as="nav" gap="lg" aria-label="Footer navigation">
    <Link href="#">About</Link>
    <Link href="#">Help</Link>
    <Link href="#">Terms</Link>
  </Inline>
</template>
vue

API

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