Skip to content

Scaffold

Implements the basic visual layout structure. Supports both Material Design and iOS styles (defaulting to iOS style background).

This class provides APIs for showing drawers, snack bars, and bottom sheets.

Usage

vue
<template>
  <div class="demo-container" style="width: 375px">
    <div style="margin-bottom: 10px; text-align: center">
      <Button @click="isIOS = !isIOS">
        <Text>Switch to {{ isIOS ? "Material" : "iOS" }} Style</Text>
      </Button>
    </div>

    <div style="height: 600px; width: 375px; border: 1px solid #eee">
      <!-- iOS Style -->
      <Scaffold v-if="isIOS">
        <template #navigationBar>
          <CupertinoNavigationBar middle="iOS Scaffold">
            <template #leading>
              <Button @click="console.log('Back')">
                <Text :style="{ color: '#007AFF', fontSize: 17 }">Back</Text>
              </Button>
            </template>
            <template #trailing>
              <Button @click="console.log('Edit')">
                <Text :style="{ color: '#007AFF', fontSize: 17 }">Edit</Text>
              </Button>
            </template>
          </CupertinoNavigationBar>
        </template>
        <ListView :padding="EdgeInsets.all(16)">
          <Container
            v-for="i in 20"
            :key="i"
            :height="44"
            color="white"
            :margin="EdgeInsets.only({ bottom: 1 })"
            alignment="centerLeft"
            :padding="EdgeInsets.symmetric({ horizontal: 16 })"
            width="100%"
          >
            <Row cross-axis-alignment="center" width="100%">
              <Text>iOS Item {{ i }}</Text>
              <Spacer />
              <Text :style="{ color: '#999' }">Details</Text>
            </Row>
          </Container>
        </ListView>
        <template #bottomTabBar>
          <Container
            :height="50"
            width="100%"
            color="#F9F9F9"
            :border="{ top: { width: 0.5, color: '#CCC' } }"
          >
            <Row main-axis-alignment="space-around" cross-axis-alignment="center" expanded>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon" style="color: #007aff">★</div>
                <Text :style="{ fontSize: 10, color: '#007AFF' }">Favorites</Text>
              </Column>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon" style="color: #999">●</div>
                <Text :style="{ fontSize: 10, color: '#999' }">Recents</Text>
              </Column>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon" style="color: #999">👤</div>
                <Text :style="{ fontSize: 10, color: '#999' }">Contacts</Text>
              </Column>
            </Row>
          </Container>
        </template>
      </Scaffold>

      <!-- Material Style -->
      <Scaffold v-else background-color="#f5f5f5">
        <template #appBar>
          <AppBar title="Scaffold Demo" center-title :elevation="2">
            <template #leading>
              <Button @click="console.log('Menu')">
                <div class="icon">☰</div>
              </Button>
            </template>
            <template #actions>
              <Button @click="console.log('Search')">
                <div class="icon">🔍</div>
              </Button>
              <Button @click="console.log('More')">
                <div class="icon">⋮</div>
              </Button>
            </template>
          </AppBar>
        </template>

        <ListView :padding="EdgeInsets.all(16)">
          <Container
            v-for="i in 20"
            :key="i"
            :height="80"
            color="white"
            :margin="EdgeInsets.only({ bottom: 16 })"
            :decoration="itemDecoration"
            alignment="center"
            width="100%"
          >
            <Text>Item {{ i }}</Text>
          </Container>
        </ListView>

        <template #floatingActionButton>
          <Container
            :width="56"
            :height="56"
            :decoration="fabDecoration"
            alignment="center"
            @click="console.log('FAB Clicked')"
          >
            <Text :style="fabTextStyle">+</Text>
          </Container>
        </template>

        <template #bottomNavigationBar>
          <Container :height="56" color="white" :decoration="bottomNavDecoration" width="100%">
            <Row main-axis-alignment="space-around" cross-axis-alignment="center" expanded>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon">🏠</div>
                <Text :style="navLabelStyle">Home</Text>
              </Column>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon">💼</div>
                <Text :style="navLabelStyle">Work</Text>
              </Column>
              <Column main-axis-alignment="center" cross-axis-alignment="center">
                <div class="icon">👤</div>
                <Text :style="navLabelStyle">Profile</Text>
              </Column>
            </Row>
          </Container>
        </template>
      </Scaffold>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from "vue";
import {
  Scaffold,
  AppBar,
  CupertinoNavigationBar,
  ListView,
  Container,
  Text,
  Button,
  EdgeInsets,
  BoxDecoration,
  BorderRadius,
  BoxShadow,
  BoxShape,
  TextStyle,
  FontWeight,
  Row,
  Column,
  Spacer,
} from "fluekit";

const isIOS = ref(true);

const itemDecoration = BoxDecoration({
  borderRadius: BorderRadius.circular(8),
  boxShadow: [
    BoxShadow({
      color: "rgba(0,0,0,0.05)",
      blurRadius: 4,
      offset: { x: 0, y: 2 },
    }),
  ],
});

const fabDecoration = BoxDecoration({
  color: "#FF4081",
  shape: BoxShape.circle,
  boxShadow: [
    BoxShadow({
      color: "rgba(0,0,0,0.3)",
      blurRadius: 6,
      offset: { x: 0, y: 3 },
    }),
  ],
});

const fabTextStyle = TextStyle({
  color: "white",
  fontSize: 24,
  fontWeight: FontWeight.bold,
});

const bottomNavDecoration = BoxDecoration({
  boxShadow: [
    BoxShadow({
      color: "rgba(0,0,0,0.1)",
      blurRadius: 4,
      offset: { x: 0, y: -2 },
    }),
  ],
});

const navLabelStyle = TextStyle({
  fontSize: 12,
  color: "#666",
});
</script>

<style scoped>
.icon {
  font-size: 20px;
  cursor: pointer;
}
</style>

API

Scaffold Props

NameTypeDefaultDescription
backgroundColorstring | ColorCupertinoColors.systemBackgroundThe color of the material used for the body of the scaffold.

Scaffold Slots

NameDescription
navigationBarAn iOS-style navigation bar to display at the top of the scaffold.
appBarA Material Design app bar (legacy/alternative).
bodyThe primary content of the scaffold.
bottomTabBarAn iOS-style bottom tab bar.
bottomNavigationBarA Material Design bottom navigation bar (legacy/alternative).
floatingActionButtonA button displayed floating above body, in the bottom right corner.
drawerA panel displayed to the side of the body.
endDrawerA panel displayed to the side of the body, opposite the drawer.

AppBar

A material design app bar.

AppBar Props

NameTypeDefaultDescription
titlestring-The primary widget displayed in the app bar.
backgroundColorstring'#2196F3'The background color of the app bar.
heightnumber56The height of the app bar.
centerTitlebooleanfalseWhether the title should be centered.
elevationnumber4The z-coordinate at which to place this app bar relative to its parent.
paddingEdgeInsetshorizontal: 16The padding around the content.

AppBar Slots

NameDescription
titleCustom title widget. Overrides title prop.
leadingA widget to display before the title.
actionsA list of Widgets to display in a row after the title.