@camtomlabs/malix-design-system 0.2.0 → 0.4.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/README.md +114 -1
- package/dist/index.cjs +476 -288
- package/dist/index.d.cts +130 -4
- package/dist/index.d.ts +130 -4
- package/dist/index.js +463 -277
- package/eslint-plugin.cjs +128 -0
- package/package.json +9 -4
- package/src/reset.css +212 -0
- package/src/styles.css +133 -0
package/README.md
CHANGED
|
@@ -23,11 +23,29 @@ npm install react react-dom
|
|
|
23
23
|
Import the bundled stylesheet once in your app's entry point (e.g. `main.tsx`, `layout.tsx`, or `_app.tsx`):
|
|
24
24
|
|
|
25
25
|
```ts
|
|
26
|
+
// Optional: opt-in reset scoped to @layer malix-reset.
|
|
27
|
+
// Import BEFORE styles.css so the layer order is established correctly.
|
|
28
|
+
import '@camtomlabs/malix-design-system/reset.css';
|
|
29
|
+
|
|
26
30
|
import '@camtomlabs/malix-design-system/styles.css';
|
|
27
31
|
```
|
|
28
32
|
|
|
29
33
|
That's it. All components are styled and ready to use.
|
|
30
34
|
|
|
35
|
+
### Why the reset is optional
|
|
36
|
+
|
|
37
|
+
`reset.css` lives inside `@layer malix-reset`, which means **any style you
|
|
38
|
+
write outside a layer will automatically win** — no specificity wars, no
|
|
39
|
+
`:not()` hacks. Use it if your project has a hostile global reset that
|
|
40
|
+
makes CSS Modules fight for background colors; skip it if you already
|
|
41
|
+
have your own reset.
|
|
42
|
+
|
|
43
|
+
Layer cascade order:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
malix-reset → malix-tokens → malix-components → app
|
|
47
|
+
```
|
|
48
|
+
|
|
31
49
|
## Usage
|
|
32
50
|
|
|
33
51
|
```tsx
|
|
@@ -43,6 +61,66 @@ export function MyPage() {
|
|
|
43
61
|
}
|
|
44
62
|
```
|
|
45
63
|
|
|
64
|
+
## Icons
|
|
65
|
+
|
|
66
|
+
Malix ships a canonical `<Icon>` wrapper that accepts any icon component
|
|
67
|
+
(lucide-react, phosphor-react, custom SVG) and enforces consistent
|
|
68
|
+
sizing and theming via `currentColor`.
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { Icon } from '@camtomlabs/malix-design-system';
|
|
72
|
+
import { Plus, Search, Trash } from 'lucide-react';
|
|
73
|
+
|
|
74
|
+
<Icon as={Plus} size="md" label="Add item" /> // 16px, aria-label
|
|
75
|
+
<Icon as={Search} size="sm" /> // decorative (aria-hidden)
|
|
76
|
+
<Icon as={Trash} size="lg" /> // 20px
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Sizes: `'xs'` (12px), `'sm'` (14px), `'md'` (16px), `'lg'` (20px), `'xl'` (24px), or a raw number.
|
|
80
|
+
|
|
81
|
+
## ESLint Plugin — enforce canonical components
|
|
82
|
+
|
|
83
|
+
Malix ships an ESLint plugin that catches raw `<button>` and `<input>`
|
|
84
|
+
elements and tells you to use `<Button>` / `<Input>` from the DS.
|
|
85
|
+
|
|
86
|
+
Install the sibling plugin package alongside the main package so that
|
|
87
|
+
classic ESLint config can resolve `@camtomlabs/malix` automatically:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
pnpm add -D @camtomlabs/eslint-plugin-malix
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```js
|
|
94
|
+
// .eslintrc.cjs
|
|
95
|
+
module.exports = {
|
|
96
|
+
plugins: ['@camtomlabs/malix'],
|
|
97
|
+
rules: {
|
|
98
|
+
'@camtomlabs/malix/no-raw-button': 'warn',
|
|
99
|
+
'@camtomlabs/malix/no-raw-input': 'warn',
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Or use the recommended preset:
|
|
105
|
+
|
|
106
|
+
```js
|
|
107
|
+
extends: ['plugin:@camtomlabs/malix/recommended']
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
You can escape the rule with a standard disable comment when needed:
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
// eslint-disable-next-line @camtomlabs/malix/no-raw-button
|
|
114
|
+
<button type="submit" form="external-form-id" />
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The `no-raw-input` rule allows `type="hidden"` and `type="file"` by default.
|
|
118
|
+
|
|
119
|
+
> **Legacy subpath export.** The `@camtomlabs/malix-design-system/eslint-plugin`
|
|
120
|
+
> subpath export still works but is considered legacy — classic ESLint
|
|
121
|
+
> configs can't resolve plugin names from subpath exports. Prefer installing
|
|
122
|
+
> `@camtomlabs/eslint-plugin-malix` directly.
|
|
123
|
+
|
|
46
124
|
## Theme Provider
|
|
47
125
|
|
|
48
126
|
Malix includes a React theme provider for managing dark mode:
|
|
@@ -166,11 +244,46 @@ import { tokenRegistry } from '@camtomlabs/malix-design-system';
|
|
|
166
244
|
### Overlays
|
|
167
245
|
| Component | Description |
|
|
168
246
|
|-----------|-------------|
|
|
247
|
+
| `Dialog` | **Composable modal** with `Dialog.Header` / `Dialog.Body` / `Dialog.Footer` slots. Portal + focus trap + scroll lock + focus restore. Variants: `default \| danger \| warning \| info`. Sizes: `sm \| md \| lg`. **Prefer this for custom modal layouts.** |
|
|
248
|
+
| `ConfirmDialog` | Preset confirm/cancel dialog with title + description + icon. Variants: `default \| danger \| warning \| info`. Use for simple binary confirmations. |
|
|
249
|
+
| `Modal` | Opinionated glass-style modal with fixed header/body/footer preset. Legacy — prefer `Dialog` for new code. |
|
|
169
250
|
| `GlassPopover` | Glassmorphism-styled popover |
|
|
170
|
-
| `Modal` | Full-screen modal dialog |
|
|
171
251
|
| `OnboardingPopover` | Guided onboarding popover |
|
|
172
252
|
| `Overlay` | Backdrop overlay layer |
|
|
173
253
|
|
|
254
|
+
#### Dialog usage
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
import { Dialog, Button } from '@camtomlabs/malix-design-system';
|
|
258
|
+
|
|
259
|
+
function DeleteCatalogDialog({ open, onClose, onDelete }) {
|
|
260
|
+
return (
|
|
261
|
+
<Dialog open={open} onClose={onClose} variant="danger" size="sm" role="alertdialog">
|
|
262
|
+
<Dialog.Header>Delete catalog?</Dialog.Header>
|
|
263
|
+
<Dialog.Body>
|
|
264
|
+
This action cannot be undone. All related glosas and flags will be
|
|
265
|
+
permanently removed.
|
|
266
|
+
</Dialog.Body>
|
|
267
|
+
<Dialog.Footer>
|
|
268
|
+
<Button hierarchy="secondary" onClick={onClose}>Cancel</Button>
|
|
269
|
+
<Button hierarchy="danger" onClick={onDelete}>Delete</Button>
|
|
270
|
+
</Dialog.Footer>
|
|
271
|
+
</Dialog>
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
`Dialog` handles all the modal plumbing for you:
|
|
277
|
+
|
|
278
|
+
- **Portal to `document.body`** — immune to `transform` / `overflow: hidden` ancestors
|
|
279
|
+
- **Focus trap** — Tab cycles within the panel
|
|
280
|
+
- **Escape to close** (disable via `closeOnEsc={false}`)
|
|
281
|
+
- **Backdrop click to close** (disable via `closeOnBackdropClick={false}`)
|
|
282
|
+
- **Body scroll lock** while open
|
|
283
|
+
- **Focus restore** — returns focus to the trigger on close
|
|
284
|
+
- **ARIA wiring** — `aria-labelledby` / `aria-describedby` auto-generated via `useId`
|
|
285
|
+
- **`role="alertdialog"`** opt-in for urgent confirm flows
|
|
286
|
+
|
|
174
287
|
### Interactive / Composite
|
|
175
288
|
| Component | Description |
|
|
176
289
|
|-----------|-------------|
|