Skip to content

Stage ​

Page shell: fixed sidebar (22% / 200px inner) + content column (max 1300px) + footer. Collapses to an off-canvas drawer under 800px with focus trap and Esc.

The page frame of an official site: a fixed sidebar beside the content on wide screens, a drawer behind a menu button on phones, and an optional background and footer. Use it once, at the root of a page.

BlessStage owns the viewport, so it can't sit inside a doc page:

Open Stage on a page of its own ↗

vue
<script setup lang="ts">
import { ref } from "vue";
import { withBase } from "vitepress";
import {
  BlessBadge,
  BlessDash,
  BlessSection,
  BlessSidebarNav,
  BlessStage,
  BlessText,
} from "blessing-ui";
import { navItems } from "./_nav";
const active = ref("#news");
const open = ref(false);
</script>

<template>
  <BlessStage v-model:open="open">
    <template #background>
      <div
        style="
          height: 100%;
          background: repeating-linear-gradient(
            45deg,
            var(--bless-color-surface) 0 12px,
            var(--bless-color-bg) 12px 24px
          );
        "
      />
    </template>
    <template #sidebar>
      <BlessText
        as="p"
        size="xl"
        weight="thin"
        leading="none"
        style="margin-bottom: var(--bless-space-8)"
        >Blessing</BlessText
      >
      <BlessSidebarNav
        :items="navItems"
        :active
        @select="
          (i, e) => {
            if (!i.external) {
              e.preventDefault();
              active = i.href;
              open = false;
            }
          }
        "
      />
      <BlessText as="p" size="xs" muted style="margin-top: var(--bless-space-8)"
        ><a :href="withBase('/components/stage')">← back to docs</a></BlessText
      >
    </template>

    <BlessSection title="News">
      <BlessText as="p" v-for="n in 3" :key="n"
        >2019.04.0{{ n }}<BlessDash /><BlessBadge v-if="n === 1" /> Blu-ray Disc BOX 発売決定 —
        {{ active }}</BlessText
      >
    </BlessSection>
    <BlessSection title="ストーリー" watermark="Story">
      <BlessText as="p" v-for="n in 6" :key="n"
        >第{{ n }}話 — resize under 800px for the drawer</BlessText
      >
    </BlessSection>

    <template #footer>
      <BlessText size="2xs" muted>© Blessing UI</BlessText>
    </template>
  </BlessStage>
</template>
  • On phones the sidebar becomes a drawer: the menu button says whether it's open, opening moves focus into it, and Esc or the scrim closes it (Esc returns focus to the button). Closed, it is inert.
  • #sidebar, the default slot (inside <main>), #footer and #background. menuLabel names the button.

Usage ​

ts
import { BlessStage, BlessSidebarNav } from "blessing-ui";

API ​

Props

NameTypeDefaultDescription
menuLabelstring"Menu"the phone menu button's name; aria-expanded says whether it's open
openbooleanfalsemobile drawer state; v-model:open optional

Events

NamePayloadDescription
update:open[value: boolean]

Slots

NameScopeDescription
background—
sidebar—
default—
footer—

Released under the MIT License. Character names and artwork belong to their owners.