cleanplate 0.1.11 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +193 -60
  2. package/dist/components/accordion/Accordion.d.ts +23 -12
  3. package/dist/components/accordion/Accordion.d.ts.map +1 -1
  4. package/dist/components/accordion/index.d.ts +2 -1
  5. package/dist/components/accordion/index.d.ts.map +1 -1
  6. package/dist/components/app-shell/AppShell.d.ts +35 -3
  7. package/dist/components/app-shell/AppShell.d.ts.map +1 -1
  8. package/dist/components/app-shell/index.d.ts +2 -1
  9. package/dist/components/app-shell/index.d.ts.map +1 -1
  10. package/dist/components/bottom-sheet/BottomSheet.d.ts +17 -16
  11. package/dist/components/bottom-sheet/BottomSheet.d.ts.map +1 -1
  12. package/dist/components/bottom-sheet/index.d.ts +2 -1
  13. package/dist/components/bottom-sheet/index.d.ts.map +1 -1
  14. package/dist/components/breadcrumb/BreadCrumb.d.ts +26 -0
  15. package/dist/components/breadcrumb/BreadCrumb.d.ts.map +1 -0
  16. package/dist/components/breadcrumb/index.d.ts +3 -2
  17. package/dist/components/breadcrumb/index.d.ts.map +1 -1
  18. package/dist/components/footer/Footer.d.ts +21 -16
  19. package/dist/components/footer/Footer.d.ts.map +1 -1
  20. package/dist/components/footer/index.d.ts +2 -1
  21. package/dist/components/footer/index.d.ts.map +1 -1
  22. package/dist/components/header/Header.d.ts +32 -28
  23. package/dist/components/header/Header.d.ts.map +1 -1
  24. package/dist/components/header/index.d.ts +2 -1
  25. package/dist/components/header/index.d.ts.map +1 -1
  26. package/dist/components/icon/material-icon-names.d.ts +5 -5
  27. package/dist/components/icon/material-icon-names.d.ts.map +1 -1
  28. package/dist/components/menu-list/MenuList.d.ts +32 -22
  29. package/dist/components/menu-list/MenuList.d.ts.map +1 -1
  30. package/dist/components/menu-list/index.d.ts +2 -1
  31. package/dist/components/menu-list/index.d.ts.map +1 -1
  32. package/dist/components/page-header/PageHeader.d.ts +22 -3
  33. package/dist/components/page-header/PageHeader.d.ts.map +1 -1
  34. package/dist/components/page-header/index.d.ts +2 -1
  35. package/dist/components/page-header/index.d.ts.map +1 -1
  36. package/dist/components/toast/Toast.d.ts +20 -12
  37. package/dist/components/toast/Toast.d.ts.map +1 -1
  38. package/dist/components/toast/index.d.ts +2 -1
  39. package/dist/components/toast/index.d.ts.map +1 -1
  40. package/dist/index.css +1 -1
  41. package/dist/index.es.css +1 -1
  42. package/dist/index.es.js +3 -3
  43. package/dist/index.js +3 -3
  44. package/docs/Accordion.md +125 -0
  45. package/docs/Alert.md +131 -0
  46. package/docs/Animated.md +101 -0
  47. package/docs/AppShell.md +145 -0
  48. package/docs/Avatar.md +130 -0
  49. package/docs/Badge.md +83 -0
  50. package/docs/BottomSheet.md +78 -0
  51. package/docs/BreadCrumb.md +133 -0
  52. package/docs/Button.md +189 -0
  53. package/docs/ConfirmDialog.md +139 -0
  54. package/docs/Container.md +230 -0
  55. package/docs/Dropdown.md +175 -0
  56. package/docs/Footer.md +93 -0
  57. package/docs/FormControls.md +115 -0
  58. package/docs/Header.md +115 -0
  59. package/docs/Icon.md +225 -0
  60. package/docs/MediaObject.md +303 -0
  61. package/docs/MenuList.md +113 -0
  62. package/docs/Modal.md +152 -0
  63. package/docs/PageHeader.md +134 -0
  64. package/docs/Pagination.md +142 -0
  65. package/docs/Pills.md +104 -0
  66. package/docs/Spinner.md +115 -0
  67. package/docs/Stepper.md +131 -0
  68. package/docs/Table.md +194 -0
  69. package/docs/Toast.md +96 -0
  70. package/docs/Typography.md +231 -0
  71. package/llms.txt +293 -0
  72. package/package.json +6 -1
package/docs/Alert.md ADDED
@@ -0,0 +1,131 @@
1
+ # Alert Component
2
+
3
+ Purpose: Displays a short message with an optional variant icon and dismiss button. Use it for inline feedback (success, error, warning, info) or neutral notices. When dismissed, the alert unmounts (returns null). **Margin** uses the **framework-wide spacing suffix rule** (same for all components); see `llms.txt`.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | message | string | no | — | Main message text shown in the alert. |
10
+ | size | "small" \| "medium" \| "large" | no | "medium" | Size of the alert and its icon/close button. |
11
+ | variant | "success" \| "error" \| "warning" \| "info" \| "default" | no | "info" | Visual variant; each has a matching icon (e.g. success → check_circle, error → error). |
12
+ | canDismiss | boolean | no | false | When true, shows a close button that calls onDismiss and unmounts the alert. |
13
+ | onDismiss | function | no | — | Called when the user dismisses the alert (clicks the close button). |
14
+ | margin | string \| string[] | no | ["0"] | Spacing **suffix** for outer margin. The component adds the `m-` prefix (e.g. `"0"` → m-0, `"b-2"` → m-b-2). Use a single string or array: `"0"`, `["b-2"]`. |
15
+
16
+ ## Types
17
+
18
+ ### AlertSize
19
+ ```typescript
20
+ type AlertSize = "small" | "medium" | "large";
21
+ ```
22
+
23
+ ### AlertVariant
24
+ ```typescript
25
+ type AlertVariant = "success" | "error" | "warning" | "info" | "default";
26
+ ```
27
+
28
+ ### SpacingOption
29
+ ```typescript
30
+ type SpacingOption = (typeof SPACING_OPTIONS)[number];
31
+ ```
32
+
33
+ ### AlertMargin
34
+ ```typescript
35
+ type AlertMargin = string | SpacingOption[];
36
+ ```
37
+
38
+ ### AlertProps
39
+ ```typescript
40
+ interface AlertProps {
41
+ message?: string;
42
+ size?: AlertSize;
43
+ variant?: AlertVariant;
44
+ canDismiss?: boolean;
45
+ onDismiss?: () => void;
46
+ margin?: AlertMargin;
47
+ }
48
+ ```
49
+
50
+ ## Usage Examples
51
+
52
+ ### Basic
53
+
54
+ ```jsx
55
+ import { Alert } from "cleanplate";
56
+
57
+ export const Example = () => (
58
+ <Alert message="Your changes were saved." variant="success" />
59
+ );
60
+ ```
61
+
62
+ ### Variants
63
+
64
+ ```jsx
65
+ import { Alert } from "cleanplate";
66
+
67
+ export const Example = () => (
68
+ <>
69
+ <Alert message="Default message" variant="default" margin="b-2" />
70
+ <Alert message="Info message" variant="info" margin="b-2" />
71
+ <Alert message="Warning message" variant="warning" margin="b-2" />
72
+ <Alert message="Error message" variant="error" margin="b-2" />
73
+ <Alert message="Success message" variant="success" />
74
+ </>
75
+ );
76
+ ```
77
+
78
+ ### Sizes
79
+
80
+ ```jsx
81
+ import { Alert } from "cleanplate";
82
+
83
+ export const Example = () => (
84
+ <>
85
+ <Alert message="Small alert" variant="info" size="small" margin="b-2" />
86
+ <Alert message="Medium alert" variant="info" size="medium" margin="b-2" />
87
+ <Alert message="Large alert" variant="info" size="large" />
88
+ </>
89
+ );
90
+ ```
91
+
92
+ ### Dismissible
93
+
94
+ ```jsx
95
+ import { Alert } from "cleanplate";
96
+
97
+ export const Example = () => (
98
+ <Alert
99
+ message="This can be dismissed."
100
+ variant="info"
101
+ canDismiss
102
+ onDismiss={() => console.log("Dismissed")}
103
+ />
104
+ );
105
+ ```
106
+
107
+ ### With Container
108
+
109
+ ```jsx
110
+ import { Alert, Container } from "cleanplate";
111
+
112
+ export const Example = () => (
113
+ <Container padding="4">
114
+ <Alert message="Alert inside a container" variant="warning" margin="b-2" />
115
+ </Container>
116
+ );
117
+ ```
118
+
119
+ ## Behavior Notes
120
+
121
+ - **Icon:** Each variant maps to an icon via `getVariantIcon` (e.g. error → "error", success → "check_circle", info → "info", warning → "warning", default → "info").
122
+ - **Dismiss:** When `canDismiss` is true, a close button is shown. Clicking it sets internal visibility to false, calls `onDismiss`, and the component returns `null` (removed from the tree).
123
+ - **Spacing:** `margin` accepts the **spacing suffix**; the component adds the `m-` prefix via `getSpacingClass`. Use suffix form (e.g. `"0"`, `"b-2"`) when passing values.
124
+ - **Root element:** A `div`; Alert does not extend HTML attributes, so only the documented props are supported.
125
+
126
+ ## Related Components / Links
127
+
128
+ - Typography (used internally for the message text)
129
+ - Container (layout and spacing around alerts)
130
+ - Button (used internally for the dismiss button when canDismiss is true)
131
+ - Icon (used for the variant icon and the close icon)
@@ -0,0 +1,101 @@
1
+ # Animated Component
2
+
3
+ Purpose: Atom that adds scroll-triggered entrance (or exit) animations to any content. Uses IntersectionObserver to detect when the element enters the viewport, then applies a CSS animation class. Use it to animate headings, cards, avatars, or any wrapper content as the user scrolls. Supports polymorphic `as`, delay for staggering, and margin (suffix API).
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | animationType | AnimationType | no | "fade-in-bottom" | Animation when in view: fade-in-top, fade-in-right, fade-in-bottom, fade-in-left, fade-out-top, fade-out-right, fade-out-bottom, fade-out-left. |
10
+ | as | React.ElementType | no | "span" | Root element or component to render. |
11
+ | margin | string \| SpacingOption[] | no | ["0"] | Margin spacing. Suffix or array of spacing suffixes; component adds `m-` prefix. |
12
+ | delay | number | no | 0 | Delay in ms; maps to class `delay-{delay}` (e.g. 200 → delay-200) for staggered animations. |
13
+ | className | string | no | "" | Additional class names for the root element. |
14
+ | isBlock | boolean | no | false | If true, applies block display. |
15
+ | ...rest | React.HTMLAttributes<HTMLElement> | no | — | Any other HTML attributes forwarded to the root element. |
16
+
17
+ ## Types
18
+
19
+ ### SpacingOption
20
+ ```typescript
21
+ type SpacingOption = (typeof SPACING_OPTIONS)[number];
22
+ ```
23
+
24
+ ### AnimatedMargin
25
+ ```typescript
26
+ type AnimatedMargin = string | SpacingOption[];
27
+ ```
28
+
29
+ ### AnimationType
30
+ ```typescript
31
+ type AnimationType = (typeof ANIMATION_TYPE_OPTIONS)[number];
32
+ // "fade-in-top" | "fade-in-right" | "fade-in-bottom" | "fade-in-left" |
33
+ // "fade-out-top" | "fade-out-right" | "fade-out-bottom" | "fade-out-left"
34
+ ```
35
+
36
+ ### AnimationDelay
37
+ ```typescript
38
+ type AnimationDelay = (typeof ANIMATION_DELAY_OPTIONS)[number];
39
+ // number (e.g. 100, 200, ... 3000)
40
+ ```
41
+
42
+ ### AnimatedProps
43
+ ```typescript
44
+ interface AnimatedProps extends Omit<React.HTMLAttributes<HTMLElement>, "className"> {
45
+ animationType?: AnimationType;
46
+ as?: React.ElementType;
47
+ margin?: AnimatedMargin;
48
+ delay?: number;
49
+ className?: string;
50
+ isBlock?: boolean;
51
+ }
52
+ ```
53
+
54
+ ## Usage Examples
55
+
56
+ ### Basic
57
+
58
+ ```jsx
59
+ import { Animated } from "cleanplate";
60
+
61
+ <Animated animationType="fade-in-bottom">
62
+ <h2>Animates when in view</h2>
63
+ </Animated>
64
+ ```
65
+
66
+ ### Staggered delay
67
+
68
+ ```jsx
69
+ <Animated animationType="fade-in-bottom">First</Animated>
70
+ <Animated animationType="fade-in-bottom" delay={200}>Second</Animated>
71
+ <Animated animationType="fade-in-bottom" delay={400}>Third</Animated>
72
+ ```
73
+
74
+ ### With `as` and isBlock
75
+
76
+ ```jsx
77
+ <Animated as="div" isBlock animationType="fade-in-bottom">
78
+ <section>Block-level content</section>
79
+ </Animated>
80
+ ```
81
+
82
+ ### Animation types
83
+
84
+ ```jsx
85
+ <Animated animationType="fade-in-top">Content</Animated>
86
+ <Animated animationType="fade-in-bottom">Content</Animated>
87
+ <Animated animationType="fade-in-left">Content</Animated>
88
+ <Animated animationType="fade-in-right">Content</Animated>
89
+ ```
90
+
91
+ ## Behavior Notes
92
+
93
+ - **IntersectionObserver:** The root element is observed on mount. When it intersects the viewport, the animation class is applied and the observer unobserves it (one-shot per mount).
94
+ - **Delay:** The `delay` value is used to build a class name `delay-{delay}`. Styles must define the corresponding `animation-delay` for that class (e.g. `.delay-200 { animation-delay: 200ms; }`).
95
+ - **Spacing:** `margin` uses the suffix API; the component adds the `m-` prefix via `getSpacingClass`.
96
+
97
+ ## Related Components / Links
98
+
99
+ - Container (layout around animated content)
100
+ - Typography, Avatar, Badge, Button (common content wrapped by Animated)
101
+ - Header, BottomSheet, MenuList (use Animated internally)
@@ -0,0 +1,145 @@
1
+ # AppShell Component
2
+
3
+ Purpose: Full-page layout that combines an optional Header (top), optional Footer (bottom), and an optional MenuList as a left sidebar, with main content in the center. Use for dashboard-style apps where the sidebar holds primary navigation and the header holds logo and utilities (e.g. user menu). Sidebar is hidden below 1024px; pass the same menu items to the header for the header’s mobile menu.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | children | ReactNode | yes | — | Main content (page area). |
10
+ | header | ReactNode \| HeaderProps | no | — | Top bar: pass Header props object or custom ReactNode. Omit to hide header. |
11
+ | footer | ReactNode \| FooterProps | no | — | Bottom bar: pass Footer props object or custom ReactNode. Omit to hide footer. |
12
+ | sidebar | AppShellSidebarConfig | no | — | Sidebar config (MenuList as vertical nav on the left). Omit to hide sidebar. |
13
+ | sidebarWidth | string | no | "240px" | Width of the sidebar (e.g. "240px", "16rem"). |
14
+ | className | string | no | "" | Additional class name for the root element. |
15
+ | contentClassName | string | no | "" | Additional class name for the main content wrapper. |
16
+
17
+ ## Types
18
+
19
+ ### AppShellSidebarConfig
20
+ ```typescript
21
+ interface AppShellSidebarConfig {
22
+ items: MenuListItem[]; // Menu items for the sidebar
23
+ activeItem?: string; // Value of the currently active item
24
+ onMenuClick?: (item: MenuListItem) => void;
25
+ size?: MenuListSize; // small | medium | large
26
+ variant?: MenuListVariant; // light | dark
27
+ }
28
+ ```
29
+
30
+ ### AppShellProps
31
+ ```typescript
32
+ interface AppShellProps {
33
+ children: React.ReactNode;
34
+ header?: React.ReactNode | HeaderProps;
35
+ footer?: React.ReactNode | FooterProps;
36
+ sidebar?: AppShellSidebarConfig;
37
+ sidebarWidth?: string;
38
+ className?: string;
39
+ contentClassName?: string;
40
+ }
41
+ ```
42
+
43
+ ## Usage Examples
44
+
45
+ ### Full dashboard (sidebar + header + footer)
46
+
47
+ ```jsx
48
+ import { useState } from "react";
49
+ import { AppShell, Container, Typography, Avatar } from "cleanplate";
50
+
51
+ const MENU_ITEMS = [
52
+ { label: "Dashboard", value: "/", icon: "speed" },
53
+ { label: "Settings", value: "/settings", icon: "settings" },
54
+ ];
55
+
56
+ const Dashboard = () => {
57
+ const [active, setActive] = useState("/");
58
+ const onMenuClick = (item) => setActive(item.value);
59
+ return (
60
+ <AppShell
61
+ sidebar={{
62
+ items: MENU_ITEMS,
63
+ activeItem: active,
64
+ onMenuClick,
65
+ variant: "light",
66
+ }}
67
+ header={{
68
+ logoUrl="/logo.svg",
69
+ menuItems: MENU_ITEMS,
70
+ activeMenuItem: active,
71
+ onMenuItemClick: onMenuClick,
72
+ headerRight: <Avatar name="User" />,
73
+ }}
74
+ footer={{ brandName: "Acme Inc" }}
75
+ sidebarWidth="260px"
76
+ >
77
+ <Container padding="4">
78
+ <Typography variant="h4">Dashboard</Typography>
79
+ </Container>
80
+ </AppShell>
81
+ );
82
+ };
83
+ ```
84
+
85
+ ### Sidebar only
86
+
87
+ ```jsx
88
+ <AppShell
89
+ sidebar={{
90
+ items: menuItems,
91
+ activeItem: activeItem,
92
+ onMenuClick: (item) => setActiveItem(item.value),
93
+ }}
94
+ sidebarWidth="240px"
95
+ >
96
+ <Container padding="4">
97
+ <Typography variant="p">Main content</Typography>
98
+ </Container>
99
+ </AppShell>
100
+ ```
101
+
102
+ ### Header and footer only (no sidebar)
103
+
104
+ ```jsx
105
+ <AppShell
106
+ header={{
107
+ logoUrl="/logo.svg",
108
+ menuItems,
109
+ activeMenuItem: active,
110
+ onMenuItemClick: (item) => setActive(item.value),
111
+ headerRight: <Avatar name="User" />,
112
+ }}
113
+ footer={{ brandName: "My App" }}
114
+ >
115
+ <Container padding="4">
116
+ <Typography variant="p">Content</Typography>
117
+ </Container>
118
+ </AppShell>
119
+ ```
120
+
121
+ ### Content only (minimal shell)
122
+
123
+ ```jsx
124
+ <AppShell>
125
+ <Container padding="4">
126
+ <Typography variant="h4">Welcome</Typography>
127
+ </Container>
128
+ </AppShell>
129
+ ```
130
+
131
+ ## Behavior Notes
132
+
133
+ - **Layout:** Root is a flex column with `min-height: 100vh`. Header and footer slots are full width; body is a flex row (sidebar + main). Main area is scrollable.
134
+ - **Header / footer:** When `header` or `footer` is a plain object with Header/Footer props (e.g. `menuItems` for header), the component renders `<Header {...header} />` or `<Footer {...footer} />`. Otherwise it renders the ReactNode as-is.
135
+ - **Sidebar:** Rendered in an `<aside aria-label="Main navigation">` with MenuList `direction="vertical"`. Width from `sidebarWidth` (inline style).
136
+ - **Responsive:** At viewport width ≤ 1024px the sidebar is hidden via CSS. Pass the same `menuItems` and `activeMenuItem` / `onMenuItemClick` to `header` so the header’s mobile menu provides navigation.
137
+ - **No root spacing props:** AppShell does not expose margin/padding; use `className` or `contentClassName` for layout.
138
+
139
+ ## Related Components / Links
140
+
141
+ - Header (rendered in header slot when header is Header props; use same menu items for mobile)
142
+ - Footer (rendered in footer slot when footer is Footer props)
143
+ - MenuList (used in sidebar with direction="vertical")
144
+ - Container (wrap page content inside children)
145
+ - Typography, Avatar (common in header and main)
package/docs/Avatar.md ADDED
@@ -0,0 +1,130 @@
1
+ # Avatar Component
2
+
3
+ Purpose: Displays user initials, an image, or a Material icon in a consistent circle. Use it for user identity in headers, lists, MediaObject, or anywhere you need a compact avatar. Supports sizes, spacing (margin), and optional click handling.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | name | string | no | "" | Display name; used for initials and `title` when no image/icon. Also used for image `alt` and for generating background color when showing initials. |
10
+ | image | string | no | "" | Image URL; when set, shows image instead of initials or icon. |
11
+ | icon | MaterialIconName | no | — | Material icon name; when set (and no image), shows icon instead of initials. |
12
+ | size | "small" \| "medium" | no | "medium" | Size of the avatar. |
13
+ | margin | string \| string[] | no | "m-0" | Spacing **suffix** for outer margin. The component adds the `m-` prefix (e.g. `"0"` → m-0, `"b-2"` → m-b-2). Use a single string or array: `"0"`, `["2", "b-3"]`. |
14
+ | onClick | function | no | — | Click handler for the root div. |
15
+ | className | string | no | "" | Additional class names for the root element. |
16
+ | ...rest | React.HTMLAttributes<HTMLDivElement> | no | — | Any other div attributes (e.g. `id`, `data-*`, `aria-*`, `style`) are forwarded. |
17
+
18
+ ## Types
19
+
20
+ ### SpacingOption
21
+ ```typescript
22
+ type SpacingOption = (typeof SPACING_OPTIONS)[number];
23
+ ```
24
+
25
+ ### AvatarSize
26
+ ```typescript
27
+ type AvatarSize = "small" | "medium";
28
+ ```
29
+
30
+ ### AvatarMargin
31
+ ```typescript
32
+ type AvatarMargin = string | SpacingOption[];
33
+ ```
34
+
35
+ ### AvatarProps
36
+ ```typescript
37
+ interface AvatarProps extends React.HTMLAttributes<HTMLDivElement> {
38
+ name?: string;
39
+ image?: string;
40
+ icon?: MaterialIconName; // from "../icon/material-icon-names"
41
+ size?: AvatarSize;
42
+ margin?: AvatarMargin;
43
+ onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
44
+ className?: string;
45
+ }
46
+ ```
47
+
48
+ ## Usage Examples
49
+
50
+ ### Name (initials)
51
+
52
+ ```jsx
53
+ import { Avatar } from "cleanplate";
54
+
55
+ export const Example = () => (
56
+ <>
57
+ <Avatar name="John Doe" size="medium" />
58
+ <Avatar name="Jane Smith" size="small" margin="2" />
59
+ </>
60
+ );
61
+ ```
62
+
63
+ ### Icon
64
+
65
+ ```jsx
66
+ import { Avatar } from "cleanplate";
67
+
68
+ export const Example = () => (
69
+ <>
70
+ <Avatar icon="person" size="medium" />
71
+ <Avatar icon="account_circle" size="small" />
72
+ </>
73
+ );
74
+ ```
75
+
76
+ ### Image
77
+
78
+ ```jsx
79
+ import { Avatar } from "cleanplate";
80
+
81
+ export const Example = () => (
82
+ <Avatar
83
+ name="John Doe"
84
+ image="https://example.com/photo.jpg"
85
+ size="medium"
86
+ />
87
+ );
88
+ ```
89
+
90
+ ### Clickable avatar
91
+
92
+ ```jsx
93
+ import { Avatar } from "cleanplate";
94
+
95
+ export const Example = () => (
96
+ <Avatar
97
+ name="John Doe"
98
+ size="medium"
99
+ onClick={() => console.log("Avatar clicked")}
100
+ />
101
+ );
102
+ ```
103
+
104
+ ### With Container
105
+
106
+ ```jsx
107
+ import { Avatar, Container } from "cleanplate";
108
+
109
+ export const Example = () => (
110
+ <Container display="flex" gap="2" align="center">
111
+ <Avatar name="Alice" size="small" margin="0" />
112
+ <Avatar icon="person" size="medium" margin="0" />
113
+ <Avatar image="https://example.com/bob.jpg" name="Bob" size="medium" margin="0" />
114
+ </Container>
115
+ );
116
+ ```
117
+
118
+ ## Behavior Notes
119
+
120
+ - **Display priority:** If `image` is set, the image is shown. Else if `icon` is set, the Material icon is shown. Otherwise initials from `name` are shown.
121
+ - **Initials:** Derived from the first letter of each word in `name` (up to 2 characters), e.g. "John Doe" → "JD".
122
+ - **Background color:** When showing initials, background color is generated deterministically from `name` (hash-based).
123
+ - **Spacing:** `margin` accepts the **spacing suffix**; the component adds the `m-` prefix via `getSpacingClass`. Use suffix form (e.g. `"0"`, `"2"`, `"b-3"`) when passing values explicitly.
124
+ - **Root element:** A `div`; all standard HTML div attributes and ref are supported via `...rest`.
125
+
126
+ ## Related Components / Links
127
+
128
+ - MediaObject (often uses Avatar via `mediaAvatar` for the media slot)
129
+ - Container (layout and spacing around avatars)
130
+ - Icon (Avatar can show an icon via the `icon` prop; uses Material icon names)
package/docs/Badge.md ADDED
@@ -0,0 +1,83 @@
1
+ # Badge Component
2
+
3
+ Purpose: Displays a short label with a colored background. Use it for status (e.g. success, error, warning), tags, or counts. Renders as an inline-block element with five variants (default, info, success, warning, error). Optional `className` for custom styling.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | label | string | no | — | Text shown inside the badge. |
10
+ | variant | "default" \| "info" \| "warning" \| "error" \| "success" | no | "default" | Visual variant (gray, blue, orange, red, green). |
11
+ | className | string | no | "" | Additional class names for the root element. |
12
+
13
+ ## Types
14
+
15
+ ### BadgeVariant
16
+ ```typescript
17
+ type BadgeVariant = "default" | "info" | "warning" | "error" | "success";
18
+ ```
19
+
20
+ ### BadgeProps
21
+ ```typescript
22
+ interface BadgeProps {
23
+ label?: string;
24
+ variant?: BadgeVariant;
25
+ className?: string;
26
+ }
27
+ ```
28
+
29
+ ## Usage Examples
30
+
31
+ ### Basic
32
+
33
+ ```jsx
34
+ import { Badge } from "cleanplate";
35
+
36
+ <Badge label="New" />
37
+ <Badge label="Active" variant="success" />
38
+ ```
39
+
40
+ ### Variants
41
+
42
+ ```jsx
43
+ <Badge label="Default" variant="default" />
44
+ <Badge label="Info" variant="info" />
45
+ <Badge label="Success" variant="success" />
46
+ <Badge label="Warning" variant="warning" />
47
+ <Badge label="Error" variant="error" />
48
+ ```
49
+
50
+ ### With Table (customRender)
51
+
52
+ ```jsx
53
+ import { Table, Badge } from "cleanplate";
54
+
55
+ const columns = [
56
+ { id: "name", title: "Name" },
57
+ {
58
+ id: "status",
59
+ title: "Status",
60
+ customRender: (rowData, column) => (
61
+ <Badge label={String(rowData.status)} variant="success" />
62
+ ),
63
+ },
64
+ ];
65
+ <Table columns={columns} data={data} />;
66
+ ```
67
+
68
+ ### Custom className
69
+
70
+ ```jsx
71
+ <Badge label="Custom" variant="info" className="my-badge" />
72
+ ```
73
+
74
+ ## Behavior Notes
75
+
76
+ - **Element:** Renders as a `<p>` with `display: inline-block` in styles.
77
+ - **Label:** Optional; can be omitted or empty.
78
+ - **Variants:** Each variant maps to a CSS class that sets background color via design tokens (e.g. `var(--blue)` for info, `var(--green)` for success).
79
+
80
+ ## Related Components / Links
81
+
82
+ - Table (often use Badge in column `customRender` for status or tag columns)
83
+ - Container (for layout when showing multiple badges)
@@ -0,0 +1,78 @@
1
+ # BottomSheet Component
2
+
3
+ Purpose: Slides up from the bottom of the screen. Use for additional content, forms, or actions without leaving the current context. Controlled by `isOpen` and `onClose`. Supports drag-to-close, snap points (30%, 60%, 90% of viewport), touch and mouse gestures, body scroll lock when open, and margin spacing.
4
+
5
+ ## Props / Inputs
6
+
7
+ | Prop | Type | Required | Default | Description |
8
+ | --- | --- | --- | --- | --- |
9
+ | isOpen | boolean | yes | — | Whether the bottom sheet is open. |
10
+ | onClose | () => void | no | — | Called when the user drags to close (past threshold). |
11
+ | margin | string \| SpacingOption[] | no | — | Spacing suffix(s) for outer margin; component adds m- prefix. |
12
+ | className | string | no | "" | Additional class names for the sheet panel. |
13
+ | children | ReactNode | no | — | Content rendered inside the sheet. |
14
+
15
+ ## Types
16
+
17
+ ### BottomSheetMargin
18
+ ```typescript
19
+ type BottomSheetMargin = string | SpacingOption[];
20
+ ```
21
+
22
+ ### BottomSheetProps
23
+ ```typescript
24
+ interface BottomSheetProps {
25
+ isOpen: boolean;
26
+ onClose?: () => void;
27
+ margin?: BottomSheetMargin;
28
+ className?: string;
29
+ children?: React.ReactNode;
30
+ }
31
+ ```
32
+
33
+ ## Usage Examples
34
+
35
+ ### Basic
36
+
37
+ ```jsx
38
+ import { useState } from "react";
39
+ import { BottomSheet, Button } from "cleanplate";
40
+
41
+ const App = () => {
42
+ const [isOpen, setIsOpen] = useState(false);
43
+ return (
44
+ <>
45
+ <Button onClick={() => setIsOpen(true)}>Open</Button>
46
+ <BottomSheet isOpen={isOpen} onClose={() => setIsOpen(false)}>
47
+ <p>Content here</p>
48
+ </BottomSheet>
49
+ </>
50
+ );
51
+ };
52
+ ```
53
+
54
+ ### With Container and Typography
55
+
56
+ ```jsx
57
+ <BottomSheet isOpen={isOpen} onClose={handleClose}>
58
+ <Container padding="4">
59
+ <Typography variant="h5" margin="m-0 m-b-2">Title</Typography>
60
+ <Typography variant="p">Body text</Typography>
61
+ </Container>
62
+ </BottomSheet>
63
+ ```
64
+
65
+ ## Behavior Notes
66
+
67
+ - **isOpen / onClose:** Controlled visibility. `onClose` is called when the user drags past the close threshold.
68
+ - **Snap points:** Sheet snaps to 30%, 60%, or 90% of viewport height.
69
+ - **DOM:** Overlay div wrapping the sheet panel; handle area for drag; content area for children.
70
+ - **Body overflow:** Set to `hidden` when open, restored on close or unmount.
71
+ - **Margin:** Uses the suffix API (e.g. `"0"` → m-0).
72
+
73
+ ## Related Components / Links
74
+
75
+ - Modal (full overlay dialog)
76
+ - ConfirmDialog (simple confirmation overlay)
77
+ - Button (commonly used to trigger opening)
78
+ - Container, Typography (layout and content inside the sheet)