Project started 🥂

This commit is contained in:
2026-06-02 01:13:22 +03:00
commit 612d0f0125
146 changed files with 15242 additions and 0 deletions
+232
View File
@@ -0,0 +1,232 @@
import { useState } from 'react';
import {
Button, IconButton, TextField, TextArea, SearchField, Select,
Switch, Checkbox, RadioGroup, RadioItem, Control, SegmentedControl,
Slider, Stepper, Tabs, TabsList, TabsContent, Progress, Badge, Chip,
Card, List, Row, Menu, MenuTrigger, MenuContent, MenuItem, MenuSeparator,
Tooltip, Spinner, Callout, Table, THead, TBody, Tr, Th, Td,
Dialog, DialogClose, AlertDialog, Window, useTheme,
} from 'modern-sk';
const sectionStyle: React.CSSProperties = {
display: 'flex',
flexDirection: 'column',
gap: '0.75rem',
};
const rowWrap: React.CSSProperties = {
display: 'flex',
flexWrap: 'wrap',
gap: '0.75rem',
alignItems: 'center',
};
const labelStyle: React.CSSProperties = {
fontSize: '0.75rem',
fontWeight: 600,
textTransform: 'uppercase',
letterSpacing: '0.05em',
color: 'var(--color-text-3)',
};
function Section({ title, children }: { title: string; children: React.ReactNode }) {
return (
<Card style={{ padding: '1.25rem', ...sectionStyle }}>
<span style={labelStyle}>{title}</span>
{children}
</Card>
);
}
export function HomePage() {
const { theme, setTheme } = useTheme();
const [search, setSearch] = useState('');
const [select, setSelect] = useState<string | undefined>();
const [seg, setSeg] = useState('list');
const [tab, setTab] = useState('one');
const [vol, setVol] = useState([60]);
const [count, setCount] = useState(3);
const [chips, setChips] = useState(['rock', 'jazz', 'ambient']);
const [switchOn, setSwitchOn] = useState(true);
const [radio, setRadio] = useState('a');
return (
<div style={{ overflow: 'auto', height: '100%' }}>
<div style={{ padding: '1.5rem', display: 'flex', flexDirection: 'column', gap: '1.25rem', maxWidth: '64rem', margin: '0 auto' }}>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
<div>
<h1 style={{ margin: 0, fontSize: '1.5rem', fontWeight: 700 }}> MCMA Component Kitchen Sink</h1>
<p style={{ margin: '0.25rem 0 0', color: 'var(--color-text-2)', fontSize: '0.875rem' }}>
modern-sk reference. Project base ready for development.
</p>
</div>
<Tooltip content={`Switch to ${theme === 'dark' ? 'light' : 'dark'}`}>
<Button variant="ghost" onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
{theme === 'dark' ? '☾ Dark' : '☀ Light'}
</Button>
</Tooltip>
</div>
<Section title="Buttons">
<div style={rowWrap}>
<Button variant="key">Key</Button>
<Button variant="primary">Primary</Button>
<Button variant="ember">Ember</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="primary" size="sm">Small</Button>
<Button variant="primary" disabled>Disabled</Button>
</div>
<div style={rowWrap}>
<IconButton variant="primary" aria-label="Play"></IconButton>
<IconButton variant="ghost" aria-label="Next"></IconButton>
<IconButton variant="ember" size="lg" aria-label="Stop"></IconButton>
<Stepper onDecrement={() => setCount((c) => c - 1)} onIncrement={() => setCount((c) => c + 1)} />
<span style={{ fontSize: '0.875rem', color: 'var(--color-text-2)' }}>count: {count}</span>
</div>
</Section>
<Section title="Inputs">
<div style={rowWrap}>
<TextField placeholder="Text field" style={{ width: '14rem' }} />
<SearchField icon="⌕" value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search…" style={{ width: '14rem' }} />
<Select
placeholder="Pick genre"
aria-label="Genre"
value={select}
onValueChange={setSelect}
items={[
{ value: 'rock', label: 'Rock' },
{ value: 'jazz', label: 'Jazz' },
{ value: 'ambient', label: 'Ambient' },
]}
/>
</div>
<TextArea placeholder="Text area / description…" rows={3} />
</Section>
<Section title="Toggles & selection">
<div style={rowWrap}>
<Control control={<Switch checked={switchOn} onCheckedChange={setSwitchOn} />}>Switch</Control>
<Control control={<Checkbox defaultChecked />}>Checkbox</Control>
</div>
<RadioGroup value={radio} onValueChange={setRadio} style={{ display: 'flex', gap: '1rem' }}>
<Control control={<RadioItem value="a" />}>Option A</Control>
<Control control={<RadioItem value="b" />}>Option B</Control>
<Control control={<RadioItem value="c" />}>Option C</Control>
</RadioGroup>
<SegmentedControl
value={seg}
onValueChange={setSeg}
items={[
{ value: 'list', label: 'List' },
{ value: 'grid', label: 'Grid' },
{ value: 'compact', label: 'Compact' },
]}
/>
</Section>
<Section title="Sliders & progress">
<Slider min={0} max={100} step={1} value={vol} onValueChange={setVol} marks notches="bottom" />
<span style={{ fontSize: '0.875rem', color: 'var(--color-text-2)' }}>value: {vol[0]}</span>
<Progress value={vol[0]} />
</Section>
<Section title="Badges, chips, spinner">
<div style={rowWrap}>
<Badge variant="lime" dot>On server</Badge>
<Badge variant="ember" dot>Error</Badge>
<Badge variant="neutral">Neutral</Badge>
<Badge variant="outline">Outline</Badge>
<Spinner size="sm" />
<Spinner size="lg" />
</div>
<div style={rowWrap}>
{chips.map((c) => (
<Chip key={c} onRemove={() => setChips((prev) => prev.filter((x) => x !== c))}>{c}</Chip>
))}
{chips.length === 0 && <span style={{ fontSize: '0.875rem', color: 'var(--color-text-3)' }}>all removed</span>}
</div>
</Section>
<Section title="Callouts">
<Callout variant="info">Info backend address resolves from runtime env relative /api/v1.</Callout>
<Callout variant="success">Success typecheck and lint pass clean.</Callout>
<Callout variant="warning">Warning most feature screens are still stubs.</Callout>
<Callout variant="danger">Danger destructive actions use AlertDialog.</Callout>
</Section>
<Section title="Tabs">
<Tabs value={tab} onValueChange={setTab}>
<TabsList items={[{ value: 'one', label: 'First' }, { value: 'two', label: 'Second' }, { value: 'three', label: 'Third' }]} />
<TabsContent value="one" style={{ padding: '0.75rem 0', color: 'var(--color-text-2)', fontSize: '0.875rem' }}>First panel</TabsContent>
<TabsContent value="two" style={{ padding: '0.75rem 0', color: 'var(--color-text-2)', fontSize: '0.875rem' }}>Second panel</TabsContent>
<TabsContent value="three" style={{ padding: '0.75rem 0', color: 'var(--color-text-2)', fontSize: '0.875rem' }}>Third panel</TabsContent>
</Tabs>
</Section>
<Section title="List & rows">
<List>
<Row style={{ padding: '0.5rem 0.75rem' }}>Track one Artist</Row>
<Row selected style={{ padding: '0.5rem 0.75rem' }}>Track two Artist (selected)</Row>
<Row style={{ padding: '0.5rem 0.75rem' }}>Track three Artist</Row>
</List>
</Section>
<Section title="Table">
<Table>
<THead>
<Tr><Th>Title</Th><Th>Artist</Th><Th>Duration</Th></Tr>
</THead>
<TBody>
<Tr><Td>Intro</Td><Td>Aphex</Td><Td>2:14</Td></Tr>
<Tr selected><Td>Windowlicker</Td><Td>Aphex</Td><Td>6:07</Td></Tr>
<Tr><Td>Avril 14th</Td><Td>Aphex</Td><Td>2:01</Td></Tr>
</TBody>
</Table>
</Section>
<Section title="Menu, Dialog, AlertDialog">
<div style={rowWrap}>
<Menu>
<MenuTrigger asChild>
<Button variant="ghost">Open menu </Button>
</MenuTrigger>
<MenuContent>
<MenuItem>Play</MenuItem>
<MenuItem shortcut="⌘N">Add to queue</MenuItem>
<MenuSeparator />
<MenuItem>Edit metadata</MenuItem>
</MenuContent>
</Menu>
<Dialog
trigger={<Button variant="primary">Open dialog</Button>}
title="Dialog title"
description="Composed from modern-sk primitives."
footer={<DialogClose asChild><Button variant="primary">Done</Button></DialogClose>}
>
<p style={{ color: 'var(--color-text-2)', fontSize: '0.875rem', margin: 0 }}>Dialog body content.</p>
</Dialog>
<AlertDialog
trigger={<Button variant="ember">Delete</Button>}
title="Delete track?"
description="This permanently removes the file from the server."
actionLabel="Delete"
destructive
onAction={() => undefined}
/>
</div>
</Section>
<Section title="Window">
<Window title="Now Playing" badge={<Badge variant="lime" dot>live</Badge>}>
<p style={{ color: 'var(--color-text-2)', fontSize: '0.875rem', margin: 0 }}>
Window chrome for grouped content.
</p>
</Window>
</Section>
</div>
</div>
);
}