62317f2ad7
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>
62 lines
1.6 KiB
TypeScript
62 lines
1.6 KiB
TypeScript
import type { HTMLAttributes, ReactNode } from "react";
|
|
import { cx } from "./utils";
|
|
import { IconBlock, type IconBlockProps } from "./IconBlock";
|
|
import type { IconName } from "./Icon";
|
|
|
|
export type EmptyStateProps = HTMLAttributes<HTMLDivElement> & {
|
|
/** Icône Remix à afficher dans un IconBlock. */
|
|
icon?: IconName;
|
|
/** Couleur de l'IconBlock. */
|
|
iconColor?: IconBlockProps["color"];
|
|
title: ReactNode;
|
|
description?: ReactNode;
|
|
/** Action principale (bouton, lien, etc.) */
|
|
action?: ReactNode;
|
|
/** Actions secondaires (lien doc, contact support…) */
|
|
secondaryAction?: ReactNode;
|
|
/** Variant compacte pour intégration dans un Card */
|
|
compact?: boolean;
|
|
};
|
|
|
|
/**
|
|
* EmptyState — état vide standardisé.
|
|
*
|
|
* Cas d'usage : table vide, recherche sans résultat, espace
|
|
* non encore configuré, fonctionnalité en cours d'arrivée.
|
|
*
|
|
* UX : toujours un *next step* clair (action) — jamais juste "rien".
|
|
*/
|
|
export function EmptyState({
|
|
icon = "search-2-line",
|
|
iconColor = "neutral",
|
|
title,
|
|
description,
|
|
action,
|
|
secondaryAction,
|
|
compact,
|
|
className,
|
|
...rest
|
|
}: EmptyStateProps) {
|
|
return (
|
|
<div
|
|
className={cx("mmg-empty", compact && "mmg-empty--compact", className)}
|
|
role="status"
|
|
{...rest}
|
|
>
|
|
<IconBlock
|
|
icon={icon}
|
|
color={iconColor}
|
|
size={compact ? "md" : "xl"}
|
|
/>
|
|
<h3 className="mmg-empty__title">{title}</h3>
|
|
{description && <p className="mmg-empty__desc">{description}</p>}
|
|
{(action || secondaryAction) && (
|
|
<div className="mmg-empty__actions">
|
|
{action}
|
|
{secondaryAction}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|