// frontend/src/pages/dev/StyleGuide.jsx
// Development reference only — showcases every UI component with all variants and states.
// Not linked from the sidebar. Route: /dev/styleguide (no auth required).
import { useState } from 'react'
import Button from '@/components/ui/Button'
import RowActions from '@/components/ui/RowActions'
import StatusBadge from '@/components/ui/StatusBadge'
import FormField from '@/components/ui/FormField'
import Modal from '@/components/ui/Modal'
import DataTable from '@/components/ui/DataTable'
import Pagination from '@/components/ui/Pagination'
import Spinner from '@/components/ui/Spinner'
import PageHeader from '@/components/ui/PageHeader'
import { ProfilePageHeader, ProfilePageHeaderActions } from '@/components/ui/ProfilePageHeader'
import Card from '@/components/ui/Card'
import Tabs from '@/components/ui/Tabs'
import { ToastProvider, useToast } from '@/components/ui/Toast'
import SearchBar from '@/components/ui/SearchBar'
import Select from '@/components/ui/Select'
import HeaderSearch from '@/components/ui/HeaderSearch'
import Breadcrumbs from '@/components/ui/Breadcrumbs'
import ConfirmDialog from '@/components/ui/ConfirmDialog'
import Icon, { ICON_NAMES } from '@/components/ui/Icon'
import PillButton from '@/components/ui/PillButton'
import SegmentedControl from '@/components/ui/SegmentedControl'
import IconButtonGroup from '@/components/ui/IconButtonGroup'
import DateTimePicker from '@/components/ui/DateTimePicker'
// Asset SVG URLs — grouped by folder (loaded at module init, no runtime fetch)
const _globalIconUrls = import.meta.glob('../../assets/global-icons/*.svg', { query: '?url', import: 'default', eager: true })
const _sideMenuIconUrls = import.meta.glob('../../assets/side-menu-icons/*.svg', { query: '?url', import: 'default', eager: true })
const _commsIconUrls = import.meta.glob('../../assets/comms/*.svg', { query: '?url', import: 'default', eager: true })
const _otherIconUrls = import.meta.glob('../../assets/other-icons/*.svg', { query: '?url', import: 'default', eager: true })
const _customerStatusUrls = import.meta.glob('../../assets/customer-status/*.svg', { query: '?url', import: 'default', eager: true })
// Helper: { '/path/to/foo-bar.svg': url } → [{ name: 'foo-bar', url }]
function urlMapToList(map) {
return Object.entries(map).map(([path, url]) => {
const name = path.split('/').pop().replace(/\.svg$/, '')
return { name, url }
}).sort((a, b) => a.name.localeCompare(b.name))
}
const ASSET_ICON_GROUPS = [
{ title: 'Global Icons', items: urlMapToList(_globalIconUrls) },
{ title: 'Side Menu Icons', items: urlMapToList(_sideMenuIconUrls) },
{ title: 'Comms', items: urlMapToList(_commsIconUrls) },
{ title: 'Other Icons', items: urlMapToList(_otherIconUrls) },
{ title: 'Customer Status', items: urlMapToList(_customerStatusUrls) },
]
// ---------------------------------------------------------------------------
// Layout helpers — local to this page only
// ---------------------------------------------------------------------------
function Section({ title, id, children }) {
return (
{title}
{children}
Current value: "{value}"
Every UI component with every variant and state. For development reference only.
Click a column header to sort. Drag column headers left/right to reorder. Use the grid icon (far right of header) to show/hide columns.
SearchBar expands to fill remaining space. Filter selects and page-size select are fixed-width with flexShrink: 0. Use flexWrap: 'nowrap' on the row so everything stays on one line.
The locked last column of every table. Click to open the action menu. Closes on any outside click.
All modals support: Escape to close, backdrop click to close, focus trap, and scroll lock.
This is the modal body. It can contain any content — forms, tables, confirmations.
Body content goes here.
Body content goes here.
Body content goes here.
Used exclusively in the fixed top bar. Background: --color-bg-elevated.
Fully rounded (--radius-full).
No border, no shadow. Active state uses --color-bg-island, no outline.
The default layout for all content pages with multiple variable-height sections.
Sections fill left-to-right across the top, then each new section drops into the shortest column automatically.
Use masonry-grid masonry-grid--N (N = 2, 3, or 4) as a wrapper inside .page-wrapper.
{`// Inside .page-wrapper — sections auto-flow into shortest column
…
…
… {/* drops into shortest column */}
// Available: masonry-grid--2 masonry-grid--3 masonry-grid--4
// Responsive: collapses to fewer columns at 1024px, single column at 768px`}
{`import DateTimePicker from '@/components/ui/DateTimePicker'
// value is an ISO string or ''; onChange receives an ISO string
setForm(f => ({ ...f, occurred_at: iso }))}
/>
// With validation error
`}