<script setup>
import { Button } from "@dicehub/phi/components/button";
import { LayerCard } from "@dicehub/phi/components/layer-card";
import { PhArrowRight } from "@phosphor-icons/vue";
</script>
<template>
<LayerCard>
<LayerCard.Secondary class="flex items-center justify-between">
<span>Next Steps</span>
<Button
:icon="PhArrowRight"
:icon-props="{ size: 16 }"
aria-label="Go to next steps"
shape="square"
size="sm"
variant="ghost"
/>
</LayerCard.Secondary>
<LayerCard.Primary>Get started with Phi</LayerCard.Primary>
</LayerCard>
</template>Installation
Barrel
import { LayerCard } from "@dicehub/phi";Granular
import { LayerCard } from "@dicehub/phi/components/layer-card";Usage
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<LayerCard style="width: 250px;">
<LayerCard.Secondary>Documentation</LayerCard.Secondary>
<LayerCard.Primary>Learn how to use Phi components</LayerCard.Primary>
</LayerCard>
</template>LayerCard also supports a simple surface-style mode for cases where you do not need a secondary header row. Render content directly inside LayerCard instead of wrapping it in LayerCard.Primary.
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<LayerCard style="width: 250px; padding: 1rem;">
Learn how to use Phi components
</LayerCard>
</template>Examples
Basic Card
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<LayerCard style="width: 250px;">
<LayerCard.Secondary>Getting Started</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm text-subtle">Quick start guide for new users</p>
</LayerCard.Primary>
</LayerCard>
</template>Surface-style Card
For simple card containers, render content directly inside LayerCard without LayerCard.Primary.
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<LayerCard style="width: 250px; padding: 1rem;">
<p class="text-sm text-subtle">Quick start guide for new users</p>
</LayerCard>
</template>Multiple Cards
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<div class="flex gap-4">
<LayerCard style="width: 200px;">
<LayerCard.Secondary>Components</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm">Browse all components</p>
</LayerCard.Primary>
</LayerCard>
<LayerCard style="width: 200px;">
<LayerCard.Secondary>Examples</LayerCard.Secondary>
<LayerCard.Primary>
<p class="text-sm">View code examples</p>
</LayerCard.Primary>
</LayerCard>
</div>
</template>Filter Toolbar with Small Tabs
Combine a small input with compact filter controls inside LayerCard for dense filter toolbars.
<script setup>
import { computed, ref } from "vue";
import { Badge } from "@dicehub/phi/components/badge";
import { Input } from "@dicehub/phi/components/input";
import { LayerCard } from "@dicehub/phi/components/layer-card";
const origins = [
{ origin: "challenges.cloudflare.com", s2xx: 1, s4xx: 0, duration: "95.4ms" },
{ origin: "Unknown", s2xx: 19, s4xx: 7, duration: "463.7ms" },
{ origin: "api.example.com", s2xx: 42, s4xx: 3, duration: "128.1ms" },
];
const filter = ref("all");
const search = ref("");
const filteredOrigins = computed(() =>
origins.filter((origin) => {
if (filter.value === "2xx" && origin.s2xx === 0) return false;
if (filter.value === "4xx" && origin.s4xx === 0) return false;
if (["3xx", "5xx"].includes(filter.value)) return false;
return origin.origin.toLowerCase().includes(search.value.toLowerCase());
}),
);
</script>
<template>
<LayerCard style="width: min(100%, 540px);">
<LayerCard.Secondary>Subrequests</LayerCard.Secondary>
<LayerCard.Primary>
<div class="toolbar">
<Input v-model="search" size="sm" placeholder="Filter origins..." />
<button @click="filter = 'all'">All</button>
<button @click="filter = '2xx'">2xx</button>
<button @click="filter = '4xx'">4xx</button>
</div>
<div v-for="origin in filteredOrigins" :key="origin.origin">
<span>{{ origin.origin }}</span>
<Badge v-if="origin.s2xx > 0" variant="success">2xx {{ origin.s2xx }}</Badge>
<Badge v-if="origin.s4xx > 0" variant="error">4xx {{ origin.s4xx }}</Badge>
<span>{{ origin.duration }}</span>
</div>
</LayerCard.Primary>
</LayerCard>
</template>Test IDs
LayerCard.Primary and LayerCard.Secondary accept standard HTML attributes, including data-testid for testing.
<script setup>
import { LayerCard } from "@dicehub/phi/components/layer-card";
</script>
<template>
<LayerCard style="width: 250px;">
<LayerCard.Secondary data-testid="card-header">
Getting Started
</LayerCard.Secondary>
<LayerCard.Primary data-testid="card-body">
<p class="text-sm text-subtle">Quick start guide for new users</p>
</LayerCard.Primary>
</LayerCard>
</template>API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
as | string | "div" | HTML element used for the rendered component. |
default slot | slot | - | Card content. Use LayerCard.Secondary and LayerCard.Primary for the layered treatment. |
class | string | - | - |
id | string | - | - |
lang | string | - | - |
title | string | - | - |