Genericise template stories, fix TopBar icons, and add DetailPage
Replace domain-specific (education/PDP) recipe stories with generic content. Fix TopBar action buttons using properly styled light-on-dark buttons instead of invisible IconButton tertiary. Use the real NSW waratah SVG logo. Add shared _story-helpers for TopBar actions and logo. Add DetailPage template for single-record/profile/document views with constrained width and tab support. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
163
src/components/templates/DetailPage/DetailPage.stories.tsx
Normal file
163
src/components/templates/DetailPage/DetailPage.stories.tsx
Normal file
@@ -0,0 +1,163 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import { useState } from 'react'
|
||||
import { DetailPage } from './DetailPage'
|
||||
import { AppShell } from '@/components/templates/AppShell/AppShell'
|
||||
import { TopBar } from '@/components/organisms/TopBar/TopBar'
|
||||
import { SideNav, SideNavItem, SideNavGroup, SideNavDivider } from '@/components/organisms/SideNav/SideNav'
|
||||
import { PageHeader } from '@/components/organisms/PageHeader/PageHeader'
|
||||
import { Card, CardHeader, CardTitle, CardContent } from '@/components/molecules/Card/Card'
|
||||
import { Badge } from '@/components/atoms/Badge/Badge'
|
||||
import { Avatar } from '@/components/atoms/Avatar/Avatar'
|
||||
import { Button } from '@/components/atoms/Button/Button'
|
||||
import { Tabs, TabList, Tab, TabPanel } from '@/components/atoms/Tabs/Tabs'
|
||||
import { NswLogo, TopBarAction } from '@/components/templates/_story-helpers'
|
||||
import { Menu, Bell, Home, FileText, LayoutGrid, Users, Settings, Mail, Phone, MapPin, Edit } from 'lucide-react'
|
||||
|
||||
const meta: Meta<typeof DetailPage> = {
|
||||
title: 'Templates/DetailPage',
|
||||
component: DetailPage,
|
||||
tags: ['autodocs', 'template'],
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
docs: {
|
||||
description: {
|
||||
component: 'Detail page template for viewing a single record, profile, or document. Single-column layout with constrained max-width for readability.',
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
export default meta
|
||||
|
||||
type Story = StoryObj<typeof DetailPage>
|
||||
|
||||
const InfoRow = ({ label, value, icon }: { label: string; value: string; icon: React.ReactNode }) => (
|
||||
<div className="flex items-center gap-3 py-3">
|
||||
<span className="flex size-8 shrink-0 items-center justify-center rounded-full bg-info/10 text-info [&>svg]:size-4">{icon}</span>
|
||||
<div>
|
||||
<p className="text-caption text-text-secondary">{label}</p>
|
||||
<p className="text-body text-text">{value}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
export const ProfileView: Story = {
|
||||
name: 'Profile detail',
|
||||
render: () => {
|
||||
const [collapsed, setCollapsed] = useState(false)
|
||||
const [activeTab, setActiveTab] = useState('overview')
|
||||
return (
|
||||
<AppShell
|
||||
topBar={
|
||||
<TopBar
|
||||
title="Team Directory"
|
||||
leading={<TopBarAction icon={<Menu />} label="Menu" onClick={() => setCollapsed(!collapsed)} />}
|
||||
logo={<NswLogo />}
|
||||
>
|
||||
<TopBarAction icon={<Bell />} label="Notifications" />
|
||||
<Avatar initials="AB" size="sm" />
|
||||
</TopBar>
|
||||
}
|
||||
sideNav={
|
||||
<SideNav collapsed={collapsed}>
|
||||
<SideNavItem icon={<Home />}>Home</SideNavItem>
|
||||
<SideNavItem icon={<Users />} active>Team</SideNavItem>
|
||||
<SideNavItem icon={<LayoutGrid />}>Projects</SideNavItem>
|
||||
<SideNavItem icon={<FileText />}>Documents</SideNavItem>
|
||||
<SideNavDivider />
|
||||
<SideNavItem icon={<Settings />}>Settings</SideNavItem>
|
||||
</SideNav>
|
||||
}
|
||||
sideNavCollapsed={collapsed}
|
||||
>
|
||||
<DetailPage
|
||||
header={
|
||||
<PageHeader title="Alex Chen" subtitle="Senior Engineer — Platform Team" theme="light">
|
||||
<div className="mt-2 flex items-center gap-3">
|
||||
<Badge variant="success">Active</Badge>
|
||||
<Badge variant="info-light">Full-time</Badge>
|
||||
</div>
|
||||
</PageHeader>
|
||||
}
|
||||
actions={
|
||||
<Tabs value={activeTab} onChange={setActiveTab}>
|
||||
<TabList>
|
||||
<Tab value="overview">Overview</Tab>
|
||||
<Tab value="projects">Projects</Tab>
|
||||
<Tab value="activity">Activity</Tab>
|
||||
</TabList>
|
||||
</Tabs>
|
||||
}
|
||||
>
|
||||
<Tabs value={activeTab} onChange={setActiveTab}>
|
||||
<TabPanel value="overview">
|
||||
<div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
|
||||
<Card variant="surface" className="lg:col-span-2">
|
||||
<CardHeader>
|
||||
<CardTitle>Contact information</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="divide-y divide-border">
|
||||
<InfoRow icon={<Mail />} label="Email" value="alex.chen@example.com" />
|
||||
<InfoRow icon={<Phone />} label="Phone" value="+61 2 9876 5432" />
|
||||
<InfoRow icon={<MapPin />} label="Location" value="Sydney CBD, Level 12" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card variant="surface">
|
||||
<CardHeader>
|
||||
<CardTitle>Quick actions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-3">
|
||||
<Button variant="secondary" leftIcon={<Mail size={18} />} className="w-full justify-start">Send email</Button>
|
||||
<Button variant="secondary" leftIcon={<Edit size={18} />} className="w-full justify-start">Edit profile</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</TabPanel>
|
||||
<TabPanel value="projects">
|
||||
<Card variant="surface">
|
||||
<CardContent className="p-8 text-center text-text-secondary">Project list content</CardContent>
|
||||
</Card>
|
||||
</TabPanel>
|
||||
<TabPanel value="activity">
|
||||
<Card variant="surface">
|
||||
<CardContent className="p-8 text-center text-text-secondary">Activity feed content</CardContent>
|
||||
</Card>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</DetailPage>
|
||||
</AppShell>
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const DocumentView: Story = {
|
||||
name: 'Document detail',
|
||||
render: () => (
|
||||
<DetailPage
|
||||
header={<PageHeader title="Project Brief" subtitle="Created 15 March 2024" noBackground />}
|
||||
maxWidth="lg"
|
||||
>
|
||||
<Card variant="surface">
|
||||
<CardContent className="space-y-4 p-6">
|
||||
<h2 className="text-h3 font-bold text-text">Overview</h2>
|
||||
<p className="text-body leading-relaxed text-text-secondary">
|
||||
This document outlines the scope, objectives, and timeline for the upcoming platform migration project.
|
||||
The project aims to consolidate three legacy systems into a single unified platform.
|
||||
</p>
|
||||
<h3 className="text-h4 font-bold text-text">Objectives</h3>
|
||||
<ul className="list-disc space-y-2 pl-6 text-body text-text-secondary">
|
||||
<li>Reduce operational costs by 40% through system consolidation</li>
|
||||
<li>Improve data consistency across all business units</li>
|
||||
<li>Provide a modern, accessible user interface</li>
|
||||
<li>Enable real-time reporting and analytics</li>
|
||||
</ul>
|
||||
<h3 className="text-h4 font-bold text-text">Timeline</h3>
|
||||
<p className="text-body leading-relaxed text-text-secondary">
|
||||
The project is planned across three phases over 18 months, with the first phase targeting
|
||||
core data migration and the second phase focusing on user-facing features.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</DetailPage>
|
||||
),
|
||||
}
|
||||
Reference in New Issue
Block a user