chore: initial DSMMG v0.2 — refonte architecturale complète
Mise en place du Design System ManageMate Group v0.2 — refonte du
système de tokens (préfixe --mmg-color-*), 9 presets accent
user-themable validés WCAG AA, overlays Radix UI + Floating UI,
Storybook 8 + Vitest + axe-core en CI, doc Astro Starlight,
DESIGN.md (format google-labs-code) et exports tokens DTCG/CSS/
TS/Figma/Tailwind v3 et v4.
- 4 packages monorepo pnpm : @managemate/{tokens,css,react,icons}
- 62 composants React headless-first (Sheet, HoverCard, ContextMenu,
Slider, ToggleGroup, AvatarGroup, UserCard, ProfileHeader,
MetricCard, PricingCard, FeatureCard, Text/Display/Eyebrow/Lead…)
- Lint contraste WCAG : 37/37 paires AA, branché CI
- Toast pile Sonner-style avec ResizeObserver
- Theming user (9 presets) sans casser sémantique fixe
- Identité Synapse (rose #D12B6A) préservée
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import type { ReactNode } from "react";
|
||||
import { Icon, type IconName } from "./Icon";
|
||||
|
||||
export type SidebarItem = {
|
||||
id?: string;
|
||||
label: ReactNode;
|
||||
href: string;
|
||||
icon?: IconName;
|
||||
current?: boolean;
|
||||
};
|
||||
|
||||
export type SidebarSection = {
|
||||
category?: ReactNode;
|
||||
items: SidebarItem[];
|
||||
};
|
||||
|
||||
export function AppShell({ children }: { children: ReactNode }) {
|
||||
return <div className="mmg-app-shell">{children}</div>;
|
||||
}
|
||||
|
||||
export type SidebarProps = {
|
||||
brand?: ReactNode;
|
||||
sections: SidebarSection[];
|
||||
footer?: ReactNode;
|
||||
};
|
||||
|
||||
export function Sidebar({ brand, sections, footer }: SidebarProps) {
|
||||
return (
|
||||
<aside className="mmg-sidebar">
|
||||
{brand && <div className="mmg-sidebar__header">{brand}</div>}
|
||||
<nav className="mmg-sidebar__body" aria-label="Navigation latérale">
|
||||
{sections.map((sec, i) => (
|
||||
<div key={i}>
|
||||
{sec.category && <div className="mmg-sidebar__category">{sec.category}</div>}
|
||||
{sec.items.map((item, j) => (
|
||||
<a
|
||||
key={item.id ?? j}
|
||||
href={item.href}
|
||||
aria-current={item.current ? "page" : undefined}
|
||||
className="mmg-sidebar__item"
|
||||
>
|
||||
{item.icon && <Icon name={item.icon} />}
|
||||
{item.label}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</nav>
|
||||
{footer && <div className="mmg-sidebar__footer">{footer}</div>}
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
export function AppMain({ children }: { children: ReactNode }) {
|
||||
return <div className="mmg-app-main">{children}</div>;
|
||||
}
|
||||
|
||||
export type TopbarProps = {
|
||||
title?: ReactNode;
|
||||
actions?: ReactNode;
|
||||
};
|
||||
|
||||
export function Topbar({ title, actions }: TopbarProps) {
|
||||
return (
|
||||
<header className="mmg-topbar">
|
||||
<h1 className="mmg-topbar__title">{title}</h1>
|
||||
{actions && <div className="mmg-topbar__actions">{actions}</div>}
|
||||
</header>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user