Item Modal Content
The full case-study / work-item content layout — header, carousel, HTML prose, pagination, Discover More, and media viewer — wired together in one component.
ItemModalContent composes the complete inner layout for a case study or work item:
ItemHeaderLayout— title, subtitle, project type, period, deliverables.PortfolioCarousel— Embla + MeshGradient carousel fromcarouselMedia. Pass athemeprop to colour the mesh.- Prose body —
htmlContentrendered viaHTMLContentRenderer(error-boundary protected). Images in the HTML are made clickable (zoom-in cursor) and open inMediaViewer. ItemPagination— mobile-only prev/next navigation.DiscoverMore— passdiscoverMoreItemsfrom the caller (zero app-data coupling).ItemModalFooter— footer.MediaViewer— full-screen lightbox for content images.
Layout switches between a centred 680 px column (case-study) and a 80/20 main-plus-sidebar layout (work) based on itemType.
Installation
npx shadcn@latest add @adv/item-modal-contentPulls in: @adv/item-header-blocks, @adv/media-carousel, @adv/item-pagination, @adv/media-viewer, @adv/discover-more, @adv/item-modal-footer. Also requires next-themes.
Usage
import { ItemModalContent } from '@/components/ui/ItemModalContent';
import type { WorkItemData, WorkTheme } from '@/components/ui/ItemModalContent';
import type { DiscoverMoreItem } from '@/components/ui/DiscoverMore';
const item: WorkItemData = {
id: 'aurora',
title: 'Aurora Dashboard',
role: 'Product Design',
period: '2024',
company: 'Acme Corp',
description: 'Analytics for modern teams.',
carouselMedia: [{ id: 1, title: 'Overview', image: '/cover.jpg', category: 'Product' }],
htmlContent: '<p>Full prose goes here.</p>',
};
const theme: WorkTheme = {
dark: { accent: '#2b3a42', accentHover: '#3e5564', meshColors: ['#3e5564','#2b3a42','#f79850','#d4704e'] },
light: { accent: '#6b7280', accentHover: '#94a3b8', meshColors: ['#94a3b8','#e5e7eb','#ffd8b0','#f3b995'] },
};
const discoverItems: DiscoverMoreItem[] = [
{ id: 'field-notes', title: 'Field Notes', image: '/cover2.jpg', company: 'Acme Corp' },
];
<ItemModalContent
data={item}
itemType="case-study"
prevItem={{ id: 'prev', title: 'Previous Project' }}
nextItem={null}
basePath="/work/acme/case/"
theme={theme}
discoverMoreItems={discoverItems}
/>Example
Props
| Prop | Type | Default | Description |
|---|---|---|---|
data | WorkItemData | — | The work/case-study item data object. |
itemType | "work" | "case-study" | — | Switches layout between 680 px prose column and main+sidebar. |
prevItem | { id; title } | null | — | Previous item for mobile pagination. |
nextItem | { id; title } | null | — | Next item for mobile pagination. |
basePath | string | — | URL prefix for pagination links. |
theme | WorkTheme | — | Optional dark/light theme for carousel MeshGradient colors. |
discoverMoreItems | DiscoverMoreItem[] | [] | Items for the Discover More section. Caller is responsible for providing and filtering these. |
WorkItemData
export interface WorkItemData {
id: string;
title: string;
role: string;
period: string;
company: string;
logo?: string;
description: string;
image?: string;
link?: string;
carouselMedia?: any[];
htmlContent?: string;
[k: string]: any;
}WorkTheme
export interface ThemeVariant {
accent: string;
accentHover: string;
meshColors: [string, string, string, string];
}
export interface WorkTheme {
dark: ThemeVariant;
light: ThemeVariant;
}Intro Gate — Case Study
A drop-in gate that plays an IntroSequence on first visit and then renders the full ItemPageLayout + ItemModalContent. Completion is persisted to localStorage.
Intro Sequence
A multi-section intro renderer that drives animated text, horizontal scroll, meta, and static sections before gating case-study content.