cleanplate 0.2.9 → 0.3.0
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.
- package/dist/components/media-object/MediaObject.d.ts +14 -1
- package/dist/components/media-object/MediaObject.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.es.css +1 -1
- package/dist/index.es.js +4 -4
- package/dist/index.js +3 -3
- package/docs/MediaObject.md +120 -224
- package/llms.txt +5 -4
- package/package.json +1 -1
package/docs/MediaObject.md
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
# MediaObject Component
|
|
2
2
|
|
|
3
|
-
Purpose:
|
|
3
|
+
Purpose: Combines fixed media (`Avatar`: icon, image, or initials) with a dense text stack (primary title, optional subtitle, optional clipped preview). Supports an optional **trailing rail** for metadata aligned to the title row (e.g. date) and an action anchored to the last text row (e.g. star), matching mobile inbox/list cards. Built-in text colors use semantic tokens (`--text-default`, `--text-subtle`, `--text-muted`).
|
|
4
4
|
|
|
5
5
|
## Props / Inputs
|
|
6
6
|
|
|
7
7
|
| Prop | Type | Required | Default | Description |
|
|
8
8
|
| --- | --- | --- | --- | --- |
|
|
9
|
-
| title | string | yes | — |
|
|
10
|
-
| mediaIcon | string | no | "" |
|
|
11
|
-
| mediaImage | string | no | "" | Image URL
|
|
12
|
-
| mediaAvatar | string | no | "" |
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
9
|
+
| title | string | yes | — | Primary line (e.g. name, sender). Rendered emphasized. |
|
|
10
|
+
| mediaIcon | `MaterialIconName` \| string | no | "" | Material Symbol name passed to `Avatar`. |
|
|
11
|
+
| mediaImage | string | no | "" | Image URL for `Avatar`. |
|
|
12
|
+
| mediaAvatar | string | no | "" | Display name used for initials and avatar color generation (when image/icon not shown). |
|
|
13
|
+
| subtitle | `React.ReactNode` | no | — | Optional middle line (e.g. subject). Omit for two-line layouts. |
|
|
14
|
+
| description | `React.ReactNode` | no | — | Optional preview/snippet line(s); muted, multi-line ellipsis via `--cp-media-object-desc-lines`. |
|
|
15
|
+
| descriptionLineClamp | number | no | 2 | Max lines for `description` before truncation. |
|
|
16
|
+
| meta | `React.ReactNode` | no | — | Trailing rail, **first text row**. Strings/numbers get subdued meta typography; pass JSX for custom styling. |
|
|
17
|
+
| action | `React.ReactNode` | no | — | Trailing rail, **last content row** (e.g. `Icon`/button); right-aligned with the snippet row when present. |
|
|
18
|
+
| margin | string \| `SpacingOption[]` | no | "0" | Outer margin spacing tokens (`m-*` utilities). |
|
|
19
|
+
| padding | string \| `SpacingOption[]` | no | "0" | Inner padding spacing tokens (`p-*` utilities). |
|
|
20
|
+
| className | string | no | "media-object" | Extra classes on the root `<div>`. |
|
|
21
|
+
| onClick | function | no | — | Click handler on the root; forwarded to `Avatar` when provided. |
|
|
22
|
+
| ...rest | `React.HTMLAttributes<HTMLDivElement>` | no | — | Standard div props (`id`, `data-*`, `aria-*`, etc.). |
|
|
19
23
|
|
|
20
24
|
## Types
|
|
21
25
|
|
|
22
|
-
### MediaObjectMargin
|
|
26
|
+
### MediaObjectMargin / MediaObjectPadding
|
|
23
27
|
```typescript
|
|
24
28
|
type MediaObjectMargin = string | SpacingOption[];
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
### MediaObjectPadding
|
|
28
|
-
```typescript
|
|
29
29
|
type MediaObjectPadding = string | SpacingOption[];
|
|
30
30
|
```
|
|
31
31
|
|
|
@@ -37,11 +37,15 @@ type SpacingOption = typeof SPACING_OPTIONS[number];
|
|
|
37
37
|
### MediaObjectProps
|
|
38
38
|
```typescript
|
|
39
39
|
interface MediaObjectProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
40
|
-
mediaIcon?: string;
|
|
40
|
+
mediaIcon?: MaterialIconName | string;
|
|
41
41
|
mediaImage?: string;
|
|
42
42
|
mediaAvatar?: string;
|
|
43
43
|
title: string;
|
|
44
|
-
|
|
44
|
+
subtitle?: React.ReactNode;
|
|
45
|
+
description?: React.ReactNode;
|
|
46
|
+
descriptionLineClamp?: number;
|
|
47
|
+
meta?: React.ReactNode;
|
|
48
|
+
action?: React.ReactNode;
|
|
45
49
|
margin?: MediaObjectMargin;
|
|
46
50
|
padding?: MediaObjectPadding;
|
|
47
51
|
className?: string;
|
|
@@ -51,253 +55,145 @@ interface MediaObjectProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
51
55
|
|
|
52
56
|
## Usage Examples
|
|
53
57
|
|
|
54
|
-
###
|
|
55
|
-
|
|
56
|
-
```jsx
|
|
57
|
-
import { MediaObject } from "cleanplate";
|
|
58
|
-
|
|
59
|
-
export const Example = () => (
|
|
60
|
-
<MediaObject
|
|
61
|
-
mediaIcon="person"
|
|
62
|
-
title="User Profile"
|
|
63
|
-
description="Manage your account settings and preferences"
|
|
64
|
-
/>
|
|
65
|
-
);
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
### With image
|
|
58
|
+
### Title + description (classic two-line row)
|
|
69
59
|
|
|
70
60
|
```jsx
|
|
71
61
|
import { MediaObject } from "cleanplate";
|
|
72
62
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
/>
|
|
79
|
-
);
|
|
63
|
+
<MediaObject
|
|
64
|
+
mediaIcon="person"
|
|
65
|
+
title="User Profile"
|
|
66
|
+
description="Manage your account settings and preferences"
|
|
67
|
+
/>
|
|
80
68
|
```
|
|
81
69
|
|
|
82
|
-
###
|
|
83
|
-
|
|
84
|
-
```jsx
|
|
85
|
-
import { MediaObject } from "cleanplate";
|
|
86
|
-
|
|
87
|
-
export const Example = () => (
|
|
88
|
-
<MediaObject
|
|
89
|
-
mediaAvatar="John Doe"
|
|
90
|
-
title="John Doe"
|
|
91
|
-
description="Senior Developer with 5+ years of experience"
|
|
92
|
-
/>
|
|
93
|
-
);
|
|
94
|
-
```
|
|
70
|
+
### Inbox-style row (three lines + date + star)
|
|
95
71
|
|
|
96
|
-
|
|
72
|
+
Prefer `subtitle` + `description` plus `meta` / `action` for mail-style listings. Strings in `meta` use muted sizing; arbitrary JSX is allowed for custom summaries.
|
|
97
73
|
|
|
98
74
|
```jsx
|
|
99
|
-
import { MediaObject } from "cleanplate";
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
75
|
+
import { Button, Icon, MediaObject } from "cleanplate";
|
|
76
|
+
|
|
77
|
+
<MediaObject
|
|
78
|
+
mediaAvatar="Ada Lovelace"
|
|
79
|
+
title="Ada Lovelace"
|
|
80
|
+
subtitle="» Weekly digest — infra"
|
|
81
|
+
description="Deployments, deprecation notices, and the FAQ refresh you requested."
|
|
82
|
+
meta="Thu"
|
|
83
|
+
descriptionLineClamp={2}
|
|
84
|
+
action={
|
|
85
|
+
<Button type="button" variant="icon" aria-label="Star thread" margin="m-0">
|
|
86
|
+
<Icon name="star_border" />
|
|
87
|
+
</Button>
|
|
88
|
+
}
|
|
89
|
+
/>
|
|
107
90
|
```
|
|
108
91
|
|
|
109
|
-
###
|
|
92
|
+
### Subtitle without snippet
|
|
110
93
|
|
|
111
94
|
```jsx
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
title="Featured Item"
|
|
119
|
-
description="This item has custom spacing"
|
|
120
|
-
margin="m-3"
|
|
121
|
-
padding="p-2"
|
|
122
|
-
/>
|
|
123
|
-
<MediaObject
|
|
124
|
-
mediaIcon="heart"
|
|
125
|
-
title="Another Item"
|
|
126
|
-
description="With multiple margin tokens"
|
|
127
|
-
margin={["m-1", "m-b-3"]}
|
|
128
|
-
padding={["p-1", "p-x-2"]}
|
|
129
|
-
/>
|
|
130
|
-
</>
|
|
131
|
-
);
|
|
95
|
+
<MediaObject
|
|
96
|
+
mediaIcon="payments"
|
|
97
|
+
title="Invoice #4021"
|
|
98
|
+
subtitle="Reminder: payable on receipt."
|
|
99
|
+
meta="Unpaid"
|
|
100
|
+
/>
|
|
132
101
|
```
|
|
133
102
|
|
|
134
|
-
###
|
|
103
|
+
### Action only on the trailing rail
|
|
135
104
|
|
|
136
105
|
```jsx
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
description="High-quality wireless headphones"
|
|
144
|
-
onClick={() => console.log("Media object clicked")}
|
|
145
|
-
/>
|
|
146
|
-
);
|
|
106
|
+
<MediaObject
|
|
107
|
+
mediaIcon="shopping_bag"
|
|
108
|
+
title="Reorder suggestions"
|
|
109
|
+
description="Based on your last three carts."
|
|
110
|
+
action={<Icon name="more_vert" />}
|
|
111
|
+
/>
|
|
147
112
|
```
|
|
148
113
|
|
|
149
|
-
###
|
|
114
|
+
### Meta as custom JSX
|
|
150
115
|
|
|
151
116
|
```jsx
|
|
152
|
-
import { MediaObject } from "cleanplate";
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
description="Senior Developer • john.doe@example.com"
|
|
165
|
-
/>
|
|
166
|
-
<Button variant="outline" size="small" margin="m-t-3">
|
|
167
|
-
Edit Profile
|
|
168
|
-
</Button>
|
|
169
|
-
</div>
|
|
170
|
-
);
|
|
117
|
+
import { MediaObject, Typography } from "cleanplate";
|
|
118
|
+
|
|
119
|
+
<MediaObject
|
|
120
|
+
mediaAvatar="Jane"
|
|
121
|
+
title="Jane Doe"
|
|
122
|
+
description="Ping when you merge."
|
|
123
|
+
meta={
|
|
124
|
+
<Typography variant="small" margin="m-0" isBold align="right">
|
|
125
|
+
3 new
|
|
126
|
+
</Typography>
|
|
127
|
+
}
|
|
128
|
+
/>
|
|
171
129
|
```
|
|
172
130
|
|
|
173
|
-
###
|
|
131
|
+
### With image or avatar initials
|
|
174
132
|
|
|
175
133
|
```jsx
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
mediaImage="https://example.com/product.jpg"
|
|
188
|
-
title="Wireless Headphones"
|
|
189
|
-
description="High-quality wireless headphones with noise cancellation"
|
|
190
|
-
/>
|
|
191
|
-
<div style={{ marginTop: "12px", display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
|
192
|
-
<Typography variant="h5">$199.99</Typography>
|
|
193
|
-
<Button size="small" variant="outline">Add to Cart</Button>
|
|
194
|
-
</div>
|
|
195
|
-
</div>
|
|
196
|
-
);
|
|
134
|
+
<MediaObject
|
|
135
|
+
mediaImage="https://example.com/avatar.jpg"
|
|
136
|
+
title="John Doe"
|
|
137
|
+
description="Senior Developer at Tech Corp"
|
|
138
|
+
/>
|
|
139
|
+
|
|
140
|
+
<MediaObject
|
|
141
|
+
mediaAvatar="John Doe"
|
|
142
|
+
title="John Doe"
|
|
143
|
+
description="Shows initials until an image overrides."
|
|
144
|
+
/>
|
|
197
145
|
```
|
|
198
146
|
|
|
199
|
-
###
|
|
147
|
+
### Title only
|
|
200
148
|
|
|
201
149
|
```jsx
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
export const Example = () => (
|
|
205
|
-
<div>
|
|
206
|
-
<MediaObject
|
|
207
|
-
mediaIcon="notifications"
|
|
208
|
-
title="New Message"
|
|
209
|
-
description="You have received a new message from Jane Smith"
|
|
210
|
-
margin="m-b-2"
|
|
211
|
-
/>
|
|
212
|
-
<MediaObject
|
|
213
|
-
mediaIcon="schedule"
|
|
214
|
-
title="Meeting Reminder"
|
|
215
|
-
description="Team standup in 30 minutes"
|
|
216
|
-
margin="m-b-2"
|
|
217
|
-
/>
|
|
218
|
-
<MediaObject
|
|
219
|
-
mediaIcon="done"
|
|
220
|
-
title="Task Completed"
|
|
221
|
-
description="Your project 'Website Redesign' has been updated"
|
|
222
|
-
/>
|
|
223
|
-
</div>
|
|
224
|
-
);
|
|
150
|
+
<MediaObject mediaIcon="settings" title="Settings" />
|
|
225
151
|
```
|
|
226
152
|
|
|
227
|
-
###
|
|
153
|
+
### Margin / padding tokens
|
|
228
154
|
|
|
229
155
|
```jsx
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
title="Privacy & Security"
|
|
243
|
-
description="Control your privacy settings and security options"
|
|
244
|
-
margin="m-b-2"
|
|
245
|
-
/>
|
|
246
|
-
<MediaObject
|
|
247
|
-
mediaIcon="notifications"
|
|
248
|
-
title="Notifications"
|
|
249
|
-
description="Configure how and when you receive notifications"
|
|
250
|
-
/>
|
|
251
|
-
</div>
|
|
252
|
-
);
|
|
156
|
+
<MediaObject
|
|
157
|
+
mediaIcon="star"
|
|
158
|
+
title="Featured"
|
|
159
|
+
description="With spacing utilities"
|
|
160
|
+
margin="m-b-3"
|
|
161
|
+
padding="p-2"
|
|
162
|
+
/>
|
|
163
|
+
<MediaObject
|
|
164
|
+
margin={["m-1", "m-b-3"]}
|
|
165
|
+
padding={["p-1", "p-x-2"]}
|
|
166
|
+
title="Row"
|
|
167
|
+
/>
|
|
253
168
|
```
|
|
254
169
|
|
|
255
|
-
###
|
|
170
|
+
### Clickable row
|
|
256
171
|
|
|
257
172
|
```jsx
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
{ name: "Mike Johnson", role: "Manager", avatar: "https://example.com/avatar3.jpg" }
|
|
265
|
-
];
|
|
266
|
-
|
|
267
|
-
return (
|
|
268
|
-
<div>
|
|
269
|
-
{users.map((user, index) => (
|
|
270
|
-
<MediaObject
|
|
271
|
-
key={index}
|
|
272
|
-
mediaImage={user.avatar}
|
|
273
|
-
title={user.name}
|
|
274
|
-
description={user.role}
|
|
275
|
-
margin={index < users.length - 1 ? "m-b-2" : "m-0"}
|
|
276
|
-
/>
|
|
277
|
-
))}
|
|
278
|
-
</div>
|
|
279
|
-
);
|
|
280
|
-
};
|
|
173
|
+
<MediaObject
|
|
174
|
+
mediaImage="/product.jpg"
|
|
175
|
+
title="Wireless Headphones"
|
|
176
|
+
description="Noise cancelling"
|
|
177
|
+
onClick={() => {}}
|
|
178
|
+
/>
|
|
281
179
|
```
|
|
282
180
|
|
|
283
181
|
## Behavior Notes
|
|
284
182
|
|
|
285
|
-
-
|
|
286
|
-
-
|
|
287
|
-
-
|
|
288
|
-
-
|
|
289
|
-
-
|
|
290
|
-
-
|
|
291
|
-
-
|
|
292
|
-
-
|
|
293
|
-
- Margin and padding
|
|
294
|
-
-
|
|
295
|
-
- All standard HTML div attributes can be passed through, allowing for custom `id`, `data-*`, `aria-*`, and other attributes.
|
|
296
|
-
- The component is designed to be responsive and adapts to different screen sizes.
|
|
183
|
+
- **Layout**: Root uses flex (media column + responsive grid body). Without `meta` or `action`, the body is one column of stacked text with **zero row-gap** between lines for inbox-like density.
|
|
184
|
+
- **Trailing rail**: If `meta` and/or `action` is passed, the body adds a second grid column: `meta` always occupies **column 2, row 1** aligned with `title`; `action` occupies **column 2, last text row**, aligned toward the snippet row. When **only one** logical text row remains and **both** `meta` and `action` exist, both stack in one compact trailing cell (`gap` 2px).
|
|
185
|
+
- **`descriptionLineClamp`** sets the CSS custom property `--cp-media-object-desc-lines` on the snippet wrapper so consumers can clamp 1–N lines preview text.
|
|
186
|
+
- **Media slot**: Implemented with `Avatar` (`name={mediaAvatar}`, `image`, `icon`). Combination rules when multiple props are set match `Avatar` (see `docs/Avatar.md`); typical usage passes one dominant source (photo URL vs icon vs name for initials).
|
|
187
|
+
- **`meta` primitives**: Strings and numbers render with component meta typography (muted `--text-muted`); pass React nodes when you control color/weight entirely.
|
|
188
|
+
- **`title`** is always a string rendered as emphasized primary text (`--text-default`).
|
|
189
|
+
- **`subtitle`** and **`description`** accept `React.ReactNode`; empty string / falsy hides the slot.
|
|
190
|
+
- **Styling**: Text stacks use semantic tokens (`--text-default`, `--text-subtle`, `--text-muted`); rules live in CSS modules—not the `Typography` component—so inbox-style line-heights stay consistent.
|
|
191
|
+
- **Spacing**: Margin and padding use the same spacing token shape as elsewhere (`string` or `SpacingOption[]` arrays).
|
|
192
|
+
- **Interaction**: Whole row is clickable when `onClick` is supplied; avatar receives the same handler for consistency.
|
|
297
193
|
|
|
298
194
|
## Related Components / Links
|
|
299
195
|
|
|
300
|
-
- Avatar
|
|
301
|
-
-
|
|
302
|
-
-
|
|
303
|
-
- Container
|
|
196
|
+
- **Avatar** — media slot (`mediaAvatar`, `mediaImage`, `mediaIcon`).
|
|
197
|
+
- **Icon**, **Button** — common `action` content.
|
|
198
|
+
- **Table** — `mobileColumns` maps rows into `MediaObject` on narrow viewports (`title`, `description`, optional `mediaAvatar`; still compatible without `subtitle` / rail).
|
|
199
|
+
- **Container** — often wraps stacked `MediaObject` rows.
|
package/llms.txt
CHANGED
|
@@ -65,10 +65,11 @@ All component documentation is located in the `docs/` folder. The following docu
|
|
|
65
65
|
|
|
66
66
|
### MediaObject Component
|
|
67
67
|
- File: `docs/MediaObject.md`
|
|
68
|
-
- Purpose:
|
|
69
|
-
- Key Features:
|
|
70
|
-
-
|
|
71
|
-
-
|
|
68
|
+
- Purpose: Avatar + dense text stack (required `title`, optional `subtitle`, optional line-clamped `description`) plus optional trailing **rail**: `meta` (row 1, e.g. date) and/or `action` (last row, e.g. star). Fits profiles, notifications, inbox-style rows, Table mobile cards.
|
|
69
|
+
- Key Features: `mediaIcon`/`mediaImage`/`mediaAvatar` → `Avatar`; `subtitle`; `meta`/`action`; `descriptionLineClamp` → `--cp-media-object-desc-lines`; semantic text tokens (`--text-default`/`--text-subtle`/`--text-muted`); sparse grid row-gap for list density
|
|
70
|
+
- Props (see full table in doc): title, subtitle?, description?, descriptionLineClamp? (default 2), meta?, action?, margin, padding, onClick?, ...div HTMLAttributes
|
|
71
|
+
- Types: MediaObjectProps, MediaObjectMargin, MediaObjectPadding, SpacingOption; `mediaIcon` accepts MaterialIconName
|
|
72
|
+
- Related Components: Avatar (media); Icon/Button often in `action`; Table (mobile view); Typography not wired internally—text styles live in MediaObject.module.scss
|
|
72
73
|
|
|
73
74
|
### Avatar Component
|
|
74
75
|
- File: `docs/Avatar.md`
|