Prose

A rich text container that styles the native tags inside it.

Spice and Wolf

This is rich text coming from a backend. Paragraphs, headings, lists and quotations are all handled by the container, so the caller does not style each tag.

The sound of turning pages is the only noise a library allows.
  • Volume One: Setting Out
  • Volume Two: Open Sea
<script setup lang="ts">
  import { Prose } from '@hina-ui/vue'
</script>

<template>
  <Prose class="max-w-xl">
    <h2>Spice and Wolf</h2>
    <p>
      This is rich text coming from a backend. Paragraphs, headings, lists and quotations are all
      handled by the container, so the caller does not style each tag.
    </p>
    <blockquote>The sound of turning pages is the only noise a library allows.</blockquote>
    <ul>
      <li>Volume One: Setting Out</li>
      <li>Volume Two: Open Sea</li>
    </ul>
  </Prose>
</template>
vue

Usage

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

Put a fragment of HTML inside the container and its native tags pick up the typography styles. Use it for rendered Markdown, rich text from an API, or content produced by an editor.

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

<template>
  <Prose class="max-w-lg" v-html="'<h3>A heading</h3><p>Some HTML from an API.</p>'" />
</template>
vue

Examples

Tags it covers

Headings, paragraphs, lists, description lists, quotations, code, tables, rules, marks and keys are all covered, and they match their component counterparts.

A paragraph can hold bold text , a link , inline code , a mark and a Ctrl key.

  1. An ordered list
  2. Matching the component
Formats
EPUB, PDF

VolumePages
Volume One288
<script setup lang="ts">
  import { Prose } from '@hina-ui/vue'
</script>

<template>
  <Prose class="max-w-xl">
    <p>
      A paragraph can hold
      <strong>bold text</strong>
      ,
      <a href="#elements">a link</a>
      ,
      <code>inline code</code>
      ,
      <mark>a mark</mark>
      and a
      <kbd>Ctrl</kbd>
      key.
    </p>
    <ol>
      <li>An ordered list</li>
      <li>Matching the component</li>
    </ol>
    <dl>
      <dt>Formats</dt>
      <dd>EPUB, PDF</dd>
    </dl>
    <hr />
    <table>
      <thead>
        <tr>
          <th>Volume</th>
          <th>Pages</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Volume One</td>
          <td>288</td>
        </tr>
      </tbody>
    </table>
  </Prose>
</template>
vue

Container tag

as chooses the tag to render, defaulting to div. A whole article can use article.

Rendered as an article

The container tag comes from as; the body styling is unchanged.

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

<template>
  <Prose as="article" class="max-w-lg">
    <h3>Rendered as an article</h3>
    <p>The container tag comes from as; the body styling is unchanged.</p>
  </Prose>
</template>
vue

Outer margins

Elements are spaced vertically, but the top margin of the first child and the bottom margin of the last are removed, so the container leaves no extra gap inside a card.

No margins at the ends

The outer margins of the first and last elements are removed, so the content sits flush with the padding of the card.

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

<template>
  <Card padded class="w-full max-w-lg">
    <Prose>
      <h3>No margins at the ends</h3>
      <p>
        The outer margins of the first and last elements are removed, so the content sits flush with
        the padding of the card.
      </p>
    </Prose>
  </Card>
</template>
vue

Behaviour

  • The line height is 1.7, and long words or URLs wrap instead of overflowing.
  • Styling applies only to native tags inside the container; nothing outside is affected.

API

Props

Prop
Type
Default
Description
as
string | Component
'div'
Element or component to render
asChild
boolean
false
Render nothing, merging into the single child
class
string
—
Classes appended to the root

Slots

Slot
Description
default
The rich text content