Blocks

Application Layout Block

Reviewed

A responsive customer-health shell with independent navigation, mobile access, and a focused review workflow.

App shell

Responsive customer-health workspace

Use this composition for application screens with persistent desktop navigation and a viewport-owned work area. At narrow iframe widths the sidebar becomes a flush-edge DomDrawer, while DomSelect, DomProfileMenu, DomStatusPill, DomDialog, and account rows compose a realistic review workflow.

1200px

vue
<script setup>
import { ref } from 'vue';
import {
	DomAvatar,
	DomButton,
	DomCard,
	DomDialog,
	DomDrawer,
	DomEmptyState,
	DomIconButton,
	DomProfileMenu,
	DomSelect,
	DomStatusPill,
} from '@getdom/studio/vue';
import { builtInIconSelectorItems } from '../../../../forms/icon-selector/iconSelectorItems.js';

const MENU_ICON = iconPath('Menu');
const openReviewCount = ref(4);

const navigationGroups = [
	{
		label: 'Workspace',
		items: [
			{ id: 'overview', label: 'Overview', description: 'Portfolio summary', icon: iconPath('Dashboard') },
			{ id: 'health', label: 'Customer health', description: 'Accounts needing review', icon: iconPath('Heart'), count: 'reviews' },
			{ id: 'accounts', label: 'Accounts', description: 'Customers and contacts', icon: iconPath('Users') },
			{ id: 'playbooks', label: 'Playbooks', description: 'Repeatable success plans', icon: iconPath('Sparkles') },
		],
	},
	{
		label: 'Operations',
		items: [
			{ id: 'tasks', label: 'Tasks', description: 'Assigned work', icon: iconPath('Check'), count: 8 },
			{ id: 'reports', label: 'Reports', description: 'Usage and outcomes', icon: iconPath('Chart bar') },
			{ id: 'automations', label: 'Automations', description: 'Scheduled workflows', icon: iconPath('Rocket') },
			{ id: 'integrations', label: 'Integrations', description: 'Connected services', icon: iconPath('Globe') },
		],
	},
	{
		label: 'Administration',
		items: [
			{ id: 'billing', label: 'Billing', description: 'Plan and invoices', icon: iconPath('Receipt') },
			{ id: 'access', label: 'Team access', description: 'Members and roles', icon: iconPath('Shield') },
			{ id: 'settings', label: 'Settings', description: 'Workspace preferences', icon: iconPath('Settings') },
		],
	},
];

const periodOptions = [
	{ value: '7', label: 'Last 7 days', description: 'Use recent product signals and conversations.' },
	{ value: '30', label: 'Last 30 days', description: 'Balance new activity with an established baseline.' },
	{ value: 'quarter', label: 'Last quarter', description: 'Review longer-term adoption and renewal movement.' },
];

const profileMenuItems = [
	{
		type: 'label',
		value: 'signed-in-as',
		label: 'Logged in as',
		description: 'maya@atlas.studio',
	},
	{ separator: true },
	{
		value: 'profile',
		label: 'Profile',
		description: 'Account details and preferences',
		icon: 'profile',
		href: '#profile',
	},
	{
		value: 'workspace',
		label: 'Workspace settings',
		description: 'Team, billing, and integrations',
		icon: 'onboarding',
		href: '#workspace',
	},
	{
		value: 'setup',
		label: 'Workspace setup',
		description: 'Two onboarding tasks remain',
		icon: 'onboarding',
		children: [
			{ value: 'team', label: 'Invite customer-success team', type: 'task', completed: true },
			{ value: 'health-score', label: 'Configure health score', type: 'task', completed: true },
			{ value: 'renewals', label: 'Connect renewal dates', type: 'task', completed: false },
			{ value: 'playbook', label: 'Publish risk playbook', type: 'task', completed: false },
		],
	},
	{ separator: true },
	{
		value: 'logout',
		label: 'Log out',
		description: 'End the current session',
		icon: 'logout',
		tone: 'danger',
	},
];

const healthMetrics = [
	{ label: 'Healthy accounts', value: '82%', change: '+4.8%', detail: '204 of 248 accounts' },
	{ label: 'Needs attention', value: '12', change: '-3', detail: '4 require review today' },
	{ label: 'Expansion signal', value: '$42k', change: '+12%', detail: 'Potential annual revenue' },
];

const accounts = ref([
	{
		name: 'Northstar Labs',
		initials: 'NL',
		plan: 'Enterprise · renewal in 42 days',
		detail: 'Product adoption fell after the analytics team changed.',
		status: 'High risk',
		tone: 'danger',
		score: 38,
		trend: '−18',
		lastTouch: '6 days ago',
		owner: 'Maya Chen',
		ownerInitials: 'MC',
		reviewed: false,
	},
	{
		name: 'Meridian Health',
		initials: 'MH',
		plan: 'Growth · renewal in 73 days',
		detail: 'Two champions have not completed onboarding.',
		status: 'At risk',
		tone: 'warning',
		score: 54,
		trend: '−9',
		lastTouch: 'Yesterday',
		owner: 'Alex Morgan',
		ownerInitials: 'AM',
		reviewed: false,
	},
	{
		name: 'Willow Finance',
		initials: 'WF',
		plan: 'Enterprise · renewal in 118 days',
		detail: 'API usage is healthy, but weekly active users are down.',
		status: 'Watch',
		tone: 'info',
		score: 67,
		trend: '−4',
		lastTouch: '3 hours ago',
		owner: 'Priya Shah',
		ownerInitials: 'PS',
		reviewed: false,
	},
	{
		name: 'Juniper Works',
		initials: 'JW',
		plan: 'Growth · renewal in 156 days',
		detail: 'Admin engagement recovered after a new success plan.',
		status: 'Recovering',
		tone: 'success',
		score: 74,
		trend: '+11',
		lastTouch: '35 minutes ago',
		owner: 'Maya Chen',
		ownerInitials: 'MC',
		reviewed: false,
	},
]);

const activity = [
	{ actor: 'MC', title: 'Maya added a Northstar review note', meta: '12 minutes ago' },
	{ actor: 'AM', title: 'Alex scheduled a Meridian check-in', meta: '48 minutes ago' },
	{ actor: 'PS', title: 'Priya updated the Willow success plan', meta: '2 hours ago' },
	{ actor: 'AT', title: 'Atlas automation recalculated 248 scores', meta: 'Today, 09:30' },
];

const activePage = ref(navigationGroups[0].items[1]);
const reportingPeriod = ref('30');
const mobileNavigationOpen = ref(false);
const reviewDialogOpen = ref(false);
const selectedAccount = ref(null);
const interfaceNotice = ref('');

/**
 * Resolve an icon from DOM Studio's built-in icon inventory.
 *
 * @param {string} label Built-in icon label.
 * @returns {string} SVG path data accepted by DOM Studio icon components.
 */
function iconPath(label) {
	return builtInIconSelectorItems.find((item) => item.label === label)?.path || '';
}

/**
 * Select a destination and dismiss the temporary mobile navigation.
 *
 * @param {{ id: string, label: string, description: string, icon: string }} page Navigation destination.
 * @returns {void}
 */
function selectPage(page) {
	activePage.value = page;
	mobileNavigationOpen.value = false;
	interfaceNotice.value = '';
}

/**
 * Open the temporary navigation drawer used at narrow iframe widths.
 *
 * @returns {void}
 */
function openMobileNavigation() {
	mobileNavigationOpen.value = true;
}

/**
 * Start an account review from either the primary action or an account row.
 *
 * @param {Object} [account] Account to place into the review dialog.
 * @returns {void}
 */
function startReview(account = accounts.value.find((item) => !item.reviewed)) {
	selectPage(navigationGroups[0].items[1]);
	selectedAccount.value = account || accounts.value[0];
	reviewDialogOpen.value = true;
}

/**
 * Close the account review without changing its completion state.
 *
 * @returns {void}
 */
function closeReview() {
	reviewDialogOpen.value = false;
}

/**
 * Mark the selected account review as complete and update its visible status.
 *
 * @returns {void}
 */
function completeReview() {
	if (!selectedAccount.value) return;
	const wasReviewed = selectedAccount.value.reviewed;
	selectedAccount.value.reviewed = true;
	selectedAccount.value.status = 'Reviewed';
	selectedAccount.value.tone = 'success';
	if (!wasReviewed) openReviewCount.value = Math.max(0, openReviewCount.value - 1);
	interfaceNotice.value = `${selectedAccount.value.name} is reviewed and ready for the next customer-success action.`;
	reviewDialogOpen.value = false;
}

/**
 * Simulate preparing the current health report for export.
 *
 * @returns {void}
 */
function prepareExport() {
	interfaceNotice.value = 'The customer health report is ready to download.';
}

/**
 * Reflect profile-menu actions in the demo without navigating away.
 *
 * @param {{ value?: string, item?: { label?: string } }} event DOM Studio profile-menu selection payload.
 * @returns {void}
 */
function handleProfileAction(event) {
	const label = event?.item?.label || event?.value || 'Account action';
	interfaceNotice.value = `${label} selected in this example.`;
}
</script>

<template>
	<div class="h-dvh min-h-[36rem] overflow-hidden bg-canvas text-canvas-fg">
		<div class="grid h-full min-w-0 grid-rows-[minmax(0,1fr)] md:grid-cols-[17rem_minmax(0,1fr)]">
			<aside class="hidden min-h-0 min-w-0 flex-col border-r border-border bg-secondary/55 md:flex">
				<div class="flex h-16 shrink-0 items-center gap-3 border-b border-border px-4">
					<DomAvatar name="Atlas Studio" initials="AS" size="sm" shape="rounded" />
					<div class="min-w-0">
						<p class="truncate text-sm font-semibold">Atlas Studio</p>
						<p class="truncate text-xs text-muted-fg">Customer success</p>
					</div>
				</div>

				<div class="shrink-0 px-3 pt-3">
					<DomButton class="w-full justify-start" size="sm" @click="startReview()">
						Review next account
					</DomButton>
				</div>

				<nav class="min-h-0 flex-1 overflow-y-auto px-3 py-4" aria-label="Workspace navigation">
					<div v-for="group in navigationGroups" :key="group.label" class="not-first:mt-5">
						<p class="mb-1 px-3 text-[0.68rem] font-semibold uppercase tracking-[0.14em] text-muted-fg">
							{{ group.label }}
						</p>
						<div class="space-y-1">
							<button
								v-for="item in group.items"
								:key="item.id"
								type="button"
								class="group flex w-full items-center gap-3 rounded-xl px-3 py-2 text-left text-sm transition"
								:class="activePage.id === item.id
									? 'bg-canvas font-semibold text-canvas-fg shadow-sm ring-1 ring-border/70'
									: 'text-muted-fg hover:bg-canvas/65 hover:text-canvas-fg'"
								:aria-current="activePage.id === item.id ? 'page' : undefined"
								@click="selectPage(item)"
							>
								<DomIconButton
									as="span"
									:icon="item.icon"
									label=""
									size="xs"
									class="pointer-events-none"
									aria-hidden="true"
								/>
								<span class="min-w-0 flex-1 truncate">{{ item.label }}</span>
								<span
									v-if="item.count"
									class="grid min-w-5 place-items-center rounded-full bg-primary/10 px-1.5 py-0.5 text-[0.68rem] font-semibold text-primary"
								>
									{{ item.count === 'reviews' ? openReviewCount : item.count }}
								</span>
							</button>
						</div>
					</div>
				</nav>

				<div class="shrink-0 border-t border-border p-3">
					<DomProfileMenu
						name="Maya Chen"
						email="maya@atlas.studio"
						initials="MC"
						show-name
						show-email
						:items="profileMenuItems"
						placement="top"
						align="left"
						width="min-w-[19rem]"
						class="block w-full [&>button]:w-full [&>button]:justify-start [&>button]:rounded-xl [&>button]:bg-transparent [&>button]:px-2 [&>button]:shadow-none [&>button]:hover:bg-canvas/70 [&>button>span]:flex-1"
						@select="handleProfileAction"
					/>
				</div>
			</aside>

			<section class="flex h-full min-w-0 flex-col">
				<header class="flex h-16 shrink-0 items-center gap-3 border-b border-border px-3 md:hidden">
					<DomIconButton
						:icon="MENU_ICON"
						label="Open workspace navigation"
						size="sm"
						:aria-expanded="mobileNavigationOpen ? 'true' : 'false'"
						@click="openMobileNavigation"
					/>
					<div class="flex min-w-0 flex-1 items-center gap-2.5">
						<DomAvatar name="Atlas Studio" initials="AS" size="xs" shape="rounded" />
						<div class="min-w-0">
							<p class="truncate text-sm font-semibold">Atlas Studio</p>
							<p class="truncate text-[0.68rem] text-muted-fg">{{ activePage.label }}</p>
						</div>
					</div>
					<DomProfileMenu
						name="Maya Chen"
						email="maya@atlas.studio"
						initials="MC"
						:show-name="false"
						:show-email="false"
						trigger-label="Open user menu"
						:items="profileMenuItems"
						placement="bottom"
						align="right"
						width="min-w-[19rem]"
						class="block [&>button]:size-10 [&>button]:justify-center [&>button]:rounded-full [&>button]:bg-transparent [&>button]:px-0 [&>button]:shadow-none [&>button>span>span:nth-child(2)]:sr-only [&>button>svg]:hidden"
						@select="handleProfileAction"
					/>
				</header>

				<main class="min-h-0 flex-1 overflow-y-auto">
					<div class="mx-auto w-full max-w-[96rem] p-4 sm:p-6 lg:p-8">
						<div class="flex flex-col gap-5 2xl:flex-row 2xl:items-end 2xl:justify-between">
							<div class="max-w-2xl">
								<p class="text-xs font-semibold uppercase tracking-[0.16em] text-muted-fg">Customer success</p>
								<h1 class="mt-2 text-2xl font-semibold tracking-tight sm:text-3xl">{{ activePage.label }}</h1>
								<p class="mt-2 text-sm leading-6 text-muted-fg">
									{{ activePage.id === 'health'
										? 'Prioritise accounts that need a human check-in before risk becomes churn.'
										: activePage.description + '. This destination is included to demonstrate working shell navigation.' }}
								</p>
							</div>

							<div v-if="activePage.id === 'health'" class="flex w-full flex-col gap-2 sm:w-auto sm:flex-row sm:items-end">
								<DomSelect
									v-model="reportingPeriod"
									label="Reporting period"
									:options="periodOptions"
									class="w-full sm:w-56"
									align="right"
									width="min-w-[18rem]"
								>
									<template #option="{ option }">
										<span class="block">
											<span class="block text-sm font-medium">{{ option.label }}</span>
											<span class="mt-0.5 block text-xs text-muted-fg">{{ option.description }}</span>
										</span>
									</template>
								</DomSelect>
								<DomButton variant="secondary" size="sm" @click="prepareExport">
									Export report
								</DomButton>
							</div>
						</div>

						<p
							v-if="interfaceNotice"
							class="mt-5 rounded-xl bg-success/10 px-4 py-3 text-sm font-medium text-success"
							role="status"
						>
							{{ interfaceNotice }}
						</p>

						<template v-if="activePage.id === 'health'">
							<section class="mt-7 border-y border-border" aria-labelledby="health-summary-heading">
								<h2 id="health-summary-heading" class="sr-only">Customer health summary</h2>
								<div class="grid sm:grid-cols-3">
									<div
										v-for="(metric, index) in healthMetrics"
										:key="metric.label"
										class="py-5 sm:px-5 sm:first:pl-0 sm:last:pr-0"
										:class="index ? 'border-t border-border sm:border-l sm:border-t-0' : ''"
									>
										<div class="flex items-baseline justify-between gap-3">
											<p class="text-sm font-medium text-muted-fg">{{ metric.label }}</p>
											<span class="text-xs font-semibold text-success">{{ metric.change }}</span>
										</div>
										<p class="mt-2 text-3xl font-semibold tracking-tight">{{ metric.value }}</p>
										<p class="mt-1 text-xs text-muted-fg">
											{{ metric.label === 'Needs attention' ? `${openReviewCount} require review today` : metric.detail }}
										</p>
									</div>
								</div>
							</section>

							<div class="mt-8 grid min-w-0 gap-8 xl:grid-cols-[minmax(0,1fr)_20rem]">
								<section class="min-w-0" aria-labelledby="accounts-heading">
									<div class="flex flex-wrap items-end justify-between gap-3">
										<div>
											<div class="flex items-center gap-2">
												<h2 id="accounts-heading" class="text-lg font-semibold tracking-tight">Accounts needing attention</h2>
												<DomStatusPill tone="warning" :label="`${openReviewCount} open`" size="sm" :dot="false" />
											</div>
											<p class="mt-1 text-sm text-muted-fg">Ordered by health risk and renewal proximity.</p>
										</div>
										<DomButton size="sm" @click="startReview()">Review next</DomButton>
									</div>

									<DomCard class="mt-4" padding="none">
										<ul class="divide-y divide-border" aria-label="Accounts requiring health review">
											<li v-for="account in accounts" :key="account.name" class="p-4 sm:p-5">
												<div class="flex min-w-0 items-start gap-3">
													<DomAvatar :name="account.name" :initials="account.initials" size="sm" shape="rounded" />
													<div class="min-w-0 flex-1">
														<div class="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-1">
															<h3 class="truncate text-sm font-semibold">{{ account.name }}</h3>
															<DomStatusPill :tone="account.tone" :label="account.status" size="sm" />
														</div>
														<p class="mt-0.5 text-xs text-muted-fg">{{ account.plan }}</p>
														<p class="mt-2 text-sm leading-6 text-muted-fg">{{ account.detail }}</p>

														<dl class="mt-3 grid grid-cols-2 gap-x-4 gap-y-3 text-xs sm:grid-cols-4">
															<div>
																<dt class="text-muted-fg">Health score</dt>
																<dd class="mt-1 font-semibold">{{ account.score }}/100</dd>
															</div>
															<div>
																<dt class="text-muted-fg">30-day trend</dt>
																<dd class="mt-1 font-semibold" :class="account.trend.startsWith('+') ? 'text-success' : 'text-destructive'">
																	{{ account.trend }}
																</dd>
															</div>
															<div>
																<dt class="text-muted-fg">Last touch</dt>
																<dd class="mt-1 font-semibold">{{ account.lastTouch }}</dd>
															</div>
															<div>
																<dt class="text-muted-fg">Owner</dt>
																<dd class="mt-1 flex items-center gap-1.5 font-semibold">
																	<DomAvatar :name="account.owner" :initials="account.ownerInitials" size="xs" />
																	<span class="truncate">{{ account.owner }}</span>
																</dd>
															</div>
														</dl>
													</div>
												</div>
												<div class="mt-4 flex justify-end">
													<DomButton
														:variant="account.reviewed ? 'secondary' : 'primary'"
														size="sm"
														@click="startReview(account)"
													>
														{{ account.reviewed ? 'Review again' : 'Review account' }}
													</DomButton>
												</div>
											</li>
										</ul>
									</DomCard>
								</section>

								<aside class="min-w-0 xl:border-l xl:border-border xl:pl-8" aria-labelledby="activity-heading">
									<div class="flex items-center justify-between gap-3">
										<h2 id="activity-heading" class="text-lg font-semibold tracking-tight">Recent activity</h2>
										<DomStatusPill tone="success" label="Live" size="sm" pulse />
									</div>
									<ol class="mt-4 space-y-5">
										<li v-for="item in activity" :key="item.title" class="flex gap-3">
											<DomAvatar :name="item.actor" :initials="item.actor" size="xs" />
											<div class="min-w-0">
												<p class="text-sm leading-5">{{ item.title }}</p>
												<p class="mt-1 text-xs text-muted-fg">{{ item.meta }}</p>
											</div>
										</li>
									</ol>
									<DomButton class="mt-5" variant="secondary" size="sm" @click="selectPage(navigationGroups[1].items[0])">
										View assigned tasks
									</DomButton>
								</aside>
							</div>
						</template>

						<DomEmptyState
							v-else
							class="mt-8"
							:title="`${activePage.label} is ready to compose`"
							:description="`The shell has switched to ${activePage.label.toLowerCase()}. Replace this focused placeholder with the matching DOM Studio data, form, or workflow components.`"
							:icon="activePage.icon"
							align="left"
							size="lg"
						>
							<template #actions>
								<DomButton @click="selectPage(navigationGroups[0].items[1])">Return to customer health</DomButton>
							</template>
						</DomEmptyState>
					</div>
				</main>
			</section>
		</div>

		<DomDrawer
			v-model="mobileNavigationOpen"
			class="md:hidden"
			side="left"
			width="min(88vw, 20rem)"
		>
			<template #header>
				<div class="flex min-w-0 items-center gap-3">
					<DomAvatar name="Atlas Studio" initials="AS" size="sm" shape="rounded" />
					<div class="min-w-0">
						<h2 class="truncate text-sm font-semibold">Atlas Studio</h2>
						<p class="truncate text-xs text-muted-fg">Customer success</p>
					</div>
				</div>
			</template>

			<div class="flex h-full min-h-0 flex-col">
				<div class="shrink-0 px-4 pt-4">
					<DomButton class="w-full justify-start" size="sm" @click="startReview()">
						Review next account
					</DomButton>
				</div>
				<nav class="min-h-0 flex-1 px-3 py-4" aria-label="Mobile workspace navigation">
					<div v-for="group in navigationGroups" :key="group.label" class="not-first:mt-5">
						<p class="mb-1 px-3 text-[0.68rem] font-semibold uppercase tracking-[0.14em] text-muted-fg">
							{{ group.label }}
						</p>
						<div class="space-y-1">
							<button
								v-for="item in group.items"
								:key="item.id"
								type="button"
								class="flex w-full items-center gap-3 rounded-xl px-3 py-2.5 text-left text-sm transition"
								:class="activePage.id === item.id
									? 'bg-secondary font-semibold text-secondary-fg'
									: 'text-muted-fg hover:bg-secondary hover:text-canvas-fg'"
								:aria-current="activePage.id === item.id ? 'page' : undefined"
								@click="selectPage(item)"
							>
								<DomIconButton
									as="span"
									:icon="item.icon"
									label=""
									size="xs"
									class="pointer-events-none"
									aria-hidden="true"
								/>
								<span class="min-w-0 flex-1 truncate">{{ item.label }}</span>
								<span
									v-if="item.count"
									class="grid min-w-5 place-items-center rounded-full bg-primary/10 px-1.5 py-0.5 text-[0.68rem] font-semibold text-primary"
								>
									{{ item.count === 'reviews' ? openReviewCount : item.count }}
								</span>
							</button>
						</div>
					</div>
				</nav>
			</div>

			<template #footer>
				<DomProfileMenu
					name="Maya Chen"
					email="maya@atlas.studio"
					initials="MC"
					show-name
					show-email
					:items="profileMenuItems"
					placement="top"
					align="left"
					width="min-w-[19rem]"
					class="block w-full [&>button]:w-full [&>button]:justify-start [&>button]:rounded-xl [&>button]:bg-transparent [&>button]:px-2 [&>button]:shadow-none [&>button>span]:flex-1"
					@select="handleProfileAction"
				/>
			</template>
		</DomDrawer>

		<DomDialog
			v-model="reviewDialogOpen"
			:title="selectedAccount ? `Review ${selectedAccount.name}` : 'Review account'"
			description="Capture the next human action before this account moves further into risk."
			size="lg"
		>
			<div v-if="selectedAccount" class="space-y-5">
				<div class="flex items-start gap-3 rounded-xl bg-secondary/60 p-4">
					<DomAvatar :name="selectedAccount.name" :initials="selectedAccount.initials" size="md" shape="rounded" />
					<div class="min-w-0 flex-1">
						<div class="flex flex-wrap items-center gap-2">
							<p class="font-semibold">{{ selectedAccount.name }}</p>
							<DomStatusPill :tone="selectedAccount.tone" :label="selectedAccount.status" size="sm" />
						</div>
						<p class="mt-1 text-sm text-muted-fg">{{ selectedAccount.plan }}</p>
					</div>
				</div>

				<div class="grid gap-4 sm:grid-cols-2">
					<div>
						<p class="text-xs font-semibold uppercase tracking-[0.14em] text-muted-fg">Why this surfaced</p>
						<p class="mt-2 text-sm leading-6">{{ selectedAccount.detail }}</p>
					</div>
					<div>
						<p class="text-xs font-semibold uppercase tracking-[0.14em] text-muted-fg">Suggested next step</p>
						<p class="mt-2 text-sm leading-6">Schedule a 30-minute outcome review with the account champion and owner.</p>
					</div>
				</div>

				<div class="border-t border-border pt-4">
					<p class="text-sm font-medium">Review checklist</p>
					<ul class="mt-3 space-y-2 text-sm text-muted-fg">
						<li class="flex items-center gap-2">
							<DomStatusPill tone="success" label="Usage signals checked" size="sm" />
						</li>
						<li class="flex items-center gap-2">
							<DomStatusPill tone="success" label="Account owner confirmed" size="sm" />
						</li>
						<li class="flex items-center gap-2">
							<DomStatusPill tone="warning" label="Customer follow-up needed" size="sm" />
						</li>
					</ul>
				</div>
			</div>

			<template #footer>
				<DomButton variant="secondary" @click="closeReview">Not now</DomButton>
				<DomButton @click="completeReview">Mark review complete</DomButton>
			</template>
		</DomDialog>
	</div>
</template>