jattac.libs.web.zest-button 1.4.0 → 1.5.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.
- package/LICENSE +21 -0
- package/README.md +10 -9
- package/dist/ZestButton.d.ts +4 -0
- package/dist/ZestDropdownMenu.d.ts +4 -0
- package/dist/index.cjs.js +39 -7
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.esm.js +40 -8
- package/dist/index.esm.js.map +1 -1
- package/documentation/api.md +165 -0
- package/documentation/breaking-changes.md +143 -0
- package/documentation/configuration.md +214 -0
- package/documentation/development.md +93 -0
- package/documentation/examples.md +289 -0
- package/documentation/features.md +150 -0
- package/package.json +3 -2
- package/docs/e2e/critical-paths.md +0 -75
- package/docs/features/zest-button-dropdown-options/BRS.md +0 -213
- package/docs/guidelines/AI_ARCHITECTURE.md +0 -455
- package/docs/guidelines/AI_BRS.md +0 -435
- package/docs/guidelines/AI_CODE_REVIEW.md +0 -198
- package/docs/guidelines/AI_E2E_TESTING.md +0 -227
- package/docs/guidelines/AI_GIT_WORKFLOW.md +0 -595
- package/docs/guidelines/AI_KNOWLEDGE.md +0 -213
- package/docs/guidelines/AI_PITFALLS.md +0 -245
- package/docs/guidelines/AI_STYLE_GUIDE.md +0 -162
- package/docs/guidelines/AI_TESTING.md +0 -275
- package/docs/guidelines/AI_TEST_CONFIGURATION.md +0 -529
- package/docs/guidelines/AI_WORKFLOW.md +0 -442
- package/docs/guidelines/AI_WORKFLOW_TRIGGERS.md +0 -222
- package/docs/guidelines/ai-knowledge.md +0 -154
- package/docs/guidelines/decision-log.md +0 -149
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# The Cookbook: From First Button to Design System
|
|
2
|
+
|
|
3
|
+
Welcome to the ZestButton Cookbook! This is the core learning path for mastering `ZestButton`. Each recipe solves a real-world problem and builds on the concepts from the previous one. Start here to go from zero to expert.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Recipe 1: Your First Async Button](#recipe-1-your-first-async-button)
|
|
10
|
+
- [Recipe 2: The Safe "Delete" Button](#recipe-2-the-safe-delete-button)
|
|
11
|
+
- [Recipe 3: Standardizing Your Buttons with a Global Config](#recipe-3-standardizing-your-buttons-with-a-global-config)
|
|
12
|
+
- [Recipe 4: Creating a Custom "Archive" Button](#recipe-4-creating-a-custom-archive-button)
|
|
13
|
+
- [Recipe 5: A Split Button with Overflow Actions](#recipe-5-a-split-button-with-overflow-actions)
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
### Recipe 1: Your First Async Button
|
|
18
|
+
|
|
19
|
+
**Goal:** Create a button that automatically shows a loading spinner during an operation and gives feedback when it's done.
|
|
20
|
+
|
|
21
|
+
**Problem:** You have an API call that takes time. You need to prevent the user from clicking the button multiple times and clearly show when the action is complete.
|
|
22
|
+
|
|
23
|
+
**Solution:** Simply have your `onClick` handler return a `Promise`. `ZestButton` handles the rest. This example also shows success and failure states.
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import React, { useState } from 'react';
|
|
27
|
+
import ZestButton from 'jattac.libs.web.zest-button';
|
|
28
|
+
import { FaSave } from 'react-icons/fa';
|
|
29
|
+
|
|
30
|
+
const SaveButton = () => {
|
|
31
|
+
const [shouldSucceed, setShouldSucceed] = useState(true);
|
|
32
|
+
|
|
33
|
+
const handleSave = async () => {
|
|
34
|
+
console.log('Saving...');
|
|
35
|
+
// Simulate an API call
|
|
36
|
+
await new Promise((resolve, reject) => {
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
shouldSucceed ? resolve('Success!') : reject('Error!');
|
|
39
|
+
}, 1500);
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem', maxWidth: '300px' }}>
|
|
45
|
+
<label>
|
|
46
|
+
<input
|
|
47
|
+
type="checkbox"
|
|
48
|
+
checked={shouldSucceed}
|
|
49
|
+
onChange={() => setShouldSucceed(e => !e)}
|
|
50
|
+
/>
|
|
51
|
+
Simulate Success
|
|
52
|
+
</label>
|
|
53
|
+
<ZestButton
|
|
54
|
+
onClick={handleSave}
|
|
55
|
+
zest={{
|
|
56
|
+
visualOptions: { iconLeft: <FaSave />, stretch: true },
|
|
57
|
+
}}
|
|
58
|
+
>
|
|
59
|
+
Save Settings
|
|
60
|
+
</ZestButton>
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
};
|
|
64
|
+
```
|
|
65
|
+
*For more details on all available options, see the [`BusyOptions`](./api.md#busyoptions) and [`SuccessOptions`](./api.md#successoptions) in our API reference.*
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### Recipe 2: The Safe "Delete" Button
|
|
70
|
+
|
|
71
|
+
**Goal:** Create a button for a destructive action that requires a second click to confirm.
|
|
72
|
+
|
|
73
|
+
**Problem:** Destructive actions like deleting data are dangerous. A user might click the button by accident.
|
|
74
|
+
|
|
75
|
+
**Solution:** Use the `confirmOptions` prop. This forces the user to click once to start a countdown, and a second time to execute the action. Combining this with a `danger` variant provides a clear visual warning.
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import React from 'react';
|
|
79
|
+
import ZestButton from 'jattac.libs.web.zest-button';
|
|
80
|
+
import { FaTrash } from 'react-icons/fa';
|
|
81
|
+
|
|
82
|
+
const DeleteButton = () => {
|
|
83
|
+
const handleDelete = () => {
|
|
84
|
+
alert('Item has been permanently deleted.');
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<ZestButton
|
|
89
|
+
onClick={handleDelete}
|
|
90
|
+
zest={{
|
|
91
|
+
visualOptions: {
|
|
92
|
+
variant: 'danger',
|
|
93
|
+
iconLeft: <FaTrash />,
|
|
94
|
+
},
|
|
95
|
+
confirmOptions: {
|
|
96
|
+
displayLabel: 'Confirm Deletion',
|
|
97
|
+
timeoutSecs: 5,
|
|
98
|
+
},
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
Delete Account
|
|
102
|
+
</ZestButton>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
```
|
|
106
|
+
*For more details, see the [`ConfirmOptions`](./api.md#confirmoptions) in our API reference.*
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
### Recipe 3: Standardizing Your Buttons with a Global Config
|
|
111
|
+
|
|
112
|
+
**Goal:** Define a consistent look and feel for all buttons in your application without repeating props.
|
|
113
|
+
|
|
114
|
+
**Problem:** Your app has dozens of buttons. Specifying `size: 'sm'` or `buttonStyle: 'outline'` on every single one is tedious and error-prone.
|
|
115
|
+
|
|
116
|
+
**Solution:** Wrap your application in the `ZestProvider` and pass a `config` object. Any props in `defaultProps` will be applied to every `ZestButton` within the provider. Local props on a button will always override the global default.
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
// In your main App.tsx
|
|
120
|
+
import React from 'react';
|
|
121
|
+
import { ZestButtonConfigProvider, ZestButton } from 'jattac.libs.web.zest-button';
|
|
122
|
+
|
|
123
|
+
const appZestConfig = {
|
|
124
|
+
defaultProps: {
|
|
125
|
+
visualOptions: {
|
|
126
|
+
size: 'sm', // Make all buttons small by default
|
|
127
|
+
},
|
|
128
|
+
buttonStyle: 'outline', // Make all buttons outline by default
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
const App = () => (
|
|
133
|
+
<ZestButtonConfigProvider config={appZestConfig}>
|
|
134
|
+
<div style={{ display: 'flex', gap: '1rem', alignItems: 'center' }}>
|
|
135
|
+
<ZestButton>I'm a small outline button</ZestButton>
|
|
136
|
+
<ZestButton>So am I</ZestButton>
|
|
137
|
+
<ZestButton zest={{ visualOptions: { size: 'lg' }, buttonStyle: 'solid' }}>
|
|
138
|
+
I'm a large solid button! (Local override)
|
|
139
|
+
</ZestButton>
|
|
140
|
+
</div>
|
|
141
|
+
</ZestButtonConfigProvider>
|
|
142
|
+
);
|
|
143
|
+
```
|
|
144
|
+
*For a full list of provider settings, see the [`ZestGlobalConfig`](./api.md#zestglobalconfig) documentation. To understand the precedence rules, see the [Configuration Guide](./configuration.md).*
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Recipe 4: Creating a Custom "Archive" Button
|
|
149
|
+
|
|
150
|
+
**Goal:** Create a new, reusable button "type" with its own specific icon, style, and behavior that can be used anywhere in the app.
|
|
151
|
+
|
|
152
|
+
**Problem:** You have a common action in your app, like "Archive," that should always look and feel the same. You want to avoid configuring it manually each time and just be able to write `zest={{ semanticType: 'archive' }}`.
|
|
153
|
+
|
|
154
|
+
**Solution:** This is a two-step process that combines **TypeScript Module Augmentation** with the **`ZestButtonConfigProvider`**.
|
|
155
|
+
|
|
156
|
+
**Step 1: Define the new type**
|
|
157
|
+
In your project's type declarations file (e.g., `src/zest.d.ts`), augment the `CustomZestSemanticTypes` interface.
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
// src/zest.d.ts
|
|
161
|
+
import 'jattac.libs.web.zest-button';
|
|
162
|
+
import { FaArchive } from 'react-icons/fa';
|
|
163
|
+
|
|
164
|
+
// 1. Tell ZestButton that 'archive' is a valid semantic type
|
|
165
|
+
declare module 'jattac.libs.web.zest-button' {
|
|
166
|
+
export interface CustomZestSemanticTypes {
|
|
167
|
+
archive: 'archive';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
*(For more on this, see the [Contributor's Guide](./development.md#extending-semantic-types).)*
|
|
172
|
+
|
|
173
|
+
**Step 2: Provide the default configuration**
|
|
174
|
+
In your `App.tsx`, use the `semanticTypeDefaults` property in the `ZestButtonConfigProvider` to define the default props for your new `'archive'` type.
|
|
175
|
+
|
|
176
|
+
```tsx
|
|
177
|
+
// In your main App.tsx
|
|
178
|
+
import React from 'react';
|
|
179
|
+
import { ZestButtonConfigProvider, ZestButton } from 'jattac.libs.web.zest-button';
|
|
180
|
+
import { FaArchive } from 'react-icons/fa';
|
|
181
|
+
|
|
182
|
+
const appZestConfig = {
|
|
183
|
+
semanticTypeDefaults: {
|
|
184
|
+
// 2. Define the default props for the 'archive' type
|
|
185
|
+
archive: {
|
|
186
|
+
buttonStyle: 'outline',
|
|
187
|
+
visualOptions: {
|
|
188
|
+
iconLeft: <FaArchive />,
|
|
189
|
+
variant: 'standard',
|
|
190
|
+
},
|
|
191
|
+
confirmOptions: {
|
|
192
|
+
displayLabel: 'Confirm Archive?',
|
|
193
|
+
timeoutSecs: 10,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
// You can also override built-in types here!
|
|
197
|
+
delete: {
|
|
198
|
+
buttonStyle: 'outline', // Make all delete buttons 'outline'
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const App = () => (
|
|
204
|
+
<ZestButtonConfigProvider config={appZestConfig}>
|
|
205
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
206
|
+
{/* 3. Now just use it! */}
|
|
207
|
+
<ZestButton
|
|
208
|
+
zest={{ semanticType: 'archive' }}
|
|
209
|
+
onClick={() => alert('Archived!')}
|
|
210
|
+
>
|
|
211
|
+
Archive
|
|
212
|
+
</ZestButton>
|
|
213
|
+
|
|
214
|
+
<ZestButton
|
|
215
|
+
zest={{ semanticType: 'delete' }}
|
|
216
|
+
onClick={() => alert('Deleted!')}
|
|
217
|
+
>
|
|
218
|
+
Delete
|
|
219
|
+
</ZestButton>
|
|
220
|
+
</div>
|
|
221
|
+
</ZestButtonConfigProvider>
|
|
222
|
+
);
|
|
223
|
+
```
|
|
224
|
+
This powerful pattern allows you to build a complete, consistent design system for all button actions in your application. For more details on configuration, see the [Configuration Guide](./configuration.md).*
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
### Recipe 5: A Split Button with Overflow Actions
|
|
229
|
+
|
|
230
|
+
**Goal:** Create a button with one obvious default action ("Export as CSV") plus a few situational alternatives ("Export as PDF", "Export as JSON"), without cluttering the UI with three separate buttons.
|
|
231
|
+
|
|
232
|
+
**Problem:** You have a primary action and a handful of related, less-common actions. Placing them all as top-level buttons crowds the UI; hiding all of them behind a menu makes the primary action less discoverable and adds an extra click for the common case.
|
|
233
|
+
|
|
234
|
+
**Solution:** Pass `dropdownOptions` in `zest`. `ZestButton` renders as two visually-fused segments: the main action (left) fires immediately on click, exactly like a normal `ZestButton`, while the chevron (right) opens a menu of the extra options. Each option is independent — it can have its own icon, `busyOptions`, `successOptions`, or `confirmOptions`, running through the same machinery as the main button.
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
import React from 'react';
|
|
238
|
+
import ZestButton from 'jattac.libs.web.zest-button';
|
|
239
|
+
import { FaFileCsv, FaFilePdf, FaFileCode, FaTrash } from 'react-icons/fa6';
|
|
240
|
+
|
|
241
|
+
const ExportButton = () => {
|
|
242
|
+
const exportAs = (format: string) => async () => {
|
|
243
|
+
await new Promise((resolve) => setTimeout(resolve, 800));
|
|
244
|
+
alert(`Exported as ${format}!`);
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
return (
|
|
248
|
+
<ZestButton
|
|
249
|
+
onClick={exportAs('CSV')}
|
|
250
|
+
zest={{
|
|
251
|
+
visualOptions: { iconLeft: <FaFileCsv /> },
|
|
252
|
+
dropdownOptions: [
|
|
253
|
+
{ label: 'Export as PDF', icon: <FaFilePdf />, onClick: exportAs('PDF') },
|
|
254
|
+
{ label: 'Export as JSON', icon: <FaFileCode />, onClick: exportAs('JSON') },
|
|
255
|
+
{
|
|
256
|
+
label: 'Delete export history',
|
|
257
|
+
icon: <FaTrash />,
|
|
258
|
+
onClick: async () => alert('History cleared.'),
|
|
259
|
+
confirmOptions: { displayLabel: 'Confirm Delete', timeoutSecs: 5 },
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
}}
|
|
263
|
+
>
|
|
264
|
+
Export as CSV
|
|
265
|
+
</ZestButton>
|
|
266
|
+
);
|
|
267
|
+
};
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
**Theming and sizing the menu independently:** the dropdown menu panel defaults to a light theme and a minimum width matching the whole split button, regardless of the main button's own `theme`. Both are configurable, either per-button or app-wide via `ZestButtonConfigProvider`'s `defaultProps`:
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
<ZestButton
|
|
274
|
+
zest={{
|
|
275
|
+
theme: 'dark',
|
|
276
|
+
dropdownTheme: 'dark', // pin the menu's theme, instead of following the OS/browser preference
|
|
277
|
+
dropdownWidth: '16rem', // force a specific minimum width instead of matching the button
|
|
278
|
+
dropdownOptions: [{ label: 'Export as PDF', onClick: exportAs('PDF') }],
|
|
279
|
+
}}
|
|
280
|
+
>
|
|
281
|
+
Export as CSV
|
|
282
|
+
</ZestButton>
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
*For the full prop reference, see [`dropdownOptions`](./api.md#zestcustomprops) and [`ZestDropdownOption`](./api.md#zestdropdownoption) in our API reference.*
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
[⬅️ Previous: README](../README.md) | [Next: Features Showcase ➡️](./features.md)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Features: A Guided Tour
|
|
2
|
+
|
|
3
|
+
This document provides a high-level showcase of what's possible with `ZestButton`. For detailed, practical implementation guides, please see our **[Cookbook](./examples.md)**.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
- [Asynchronous Operations & Feedback](#asynchronous-operations--feedback)
|
|
10
|
+
- [Confirmation Flow](#confirmation-flow)
|
|
11
|
+
- [Semantic Types](#semantic-types)
|
|
12
|
+
- [Global Configuration](#global-configuration)
|
|
13
|
+
- [Rich Styling](#rich-styling)
|
|
14
|
+
- [Split Buttons & Overflow Menus](#split-buttons--overflow-menus)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
### Asynchronous Operations & Feedback
|
|
19
|
+
|
|
20
|
+
**What it does:** Automatically handles loading states and provides clear success/failure feedback for any action that returns a Promise.
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
const MyComponent = () => {
|
|
24
|
+
const handleAsyncClick = async () => {
|
|
25
|
+
// Simulate an API call that takes 2 seconds
|
|
26
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<ZestButton onClick={handleAsyncClick}>
|
|
31
|
+
Perform Async Action
|
|
32
|
+
</ZestButton>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
```
|
|
36
|
+
*__Learn more in the [Your First Async Button recipe](./examples.md#recipe-1-your-first-async-button).__*
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### Confirmation Flow
|
|
41
|
+
|
|
42
|
+
**What it does:** Protects users from accidentally performing critical actions by requiring a second click to confirm.
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
const MyComponent = () => {
|
|
46
|
+
const handleDelete = () => alert('The item has been deleted!');
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<ZestButton
|
|
50
|
+
onClick={handleDelete}
|
|
51
|
+
zest={{
|
|
52
|
+
confirmOptions: { displayLabel: 'Confirm?', timeoutSecs: 5 },
|
|
53
|
+
visualOptions: { variant: 'danger' }
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
Delete Item
|
|
57
|
+
</ZestButton>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
*__Learn more in the [Safe "Delete" Button recipe](./examples.md#recipe-2-the-safe-delete-button).__*
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
### Semantic Types
|
|
66
|
+
|
|
67
|
+
**What it does:** Streamlines development by allowing you to declare button intent (e.g., `'save'`, `'delete'`). The button automatically gets appropriate icons, colors, and behaviors.
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
const MyComponent = () => (
|
|
71
|
+
<div style={{ display: 'flex', gap: '1rem' }}>
|
|
72
|
+
<ZestButton zest={{ semanticType: 'save' }}>Save</ZestButton>
|
|
73
|
+
<ZestButton zest={{ semanticType: 'cancel' }}>Cancel</ZestButton>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
```
|
|
77
|
+
*__Learn how to create your own in the [Creating a Custom "Archive" Button recipe](./examples.md#recipe-4-creating-a-custom-archive-button).__*
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
### Global Configuration
|
|
82
|
+
|
|
83
|
+
**What it does:** Allows you to define a consistent style (like size or button style) for all buttons across your entire application.
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
// In your App.tsx
|
|
87
|
+
const appZestConfig = {
|
|
88
|
+
defaultProps: {
|
|
89
|
+
visualOptions: { size: 'sm' },
|
|
90
|
+
buttonStyle: 'outline',
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
const App = () => (
|
|
95
|
+
<ZestButtonConfigProvider config={appZestConfig}>
|
|
96
|
+
{/* All buttons inside will be small and outline by default */}
|
|
97
|
+
</ZestButtonConfigProvider>
|
|
98
|
+
);
|
|
99
|
+
```
|
|
100
|
+
*__Learn more in the [Standardizing Your Buttons recipe](./examples.md#recipe-3-standardizing-your-buttons-with-a-global-config).__*
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
### Rich Styling
|
|
105
|
+
|
|
106
|
+
**What it does:** Provides multiple variants, sizes, and styles (`solid`, `outline`, `text`, `dashed`) to fit any UI context. It also automatically adapts to light and dark themes.
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
const MyComponent = () => (
|
|
110
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
|
111
|
+
<ZestButton zest={{ visualOptions: { variant: 'success', size: 'sm' } }}>
|
|
112
|
+
Small Success
|
|
113
|
+
</ZestButton>
|
|
114
|
+
<ZestButton zest={{ buttonStyle: 'outline', size: 'md' }}>
|
|
115
|
+
Medium Outline
|
|
116
|
+
</ZestButton>
|
|
117
|
+
<ZestButton zest={{ visualOptions: { variant: 'danger', size: 'lg' } }}>
|
|
118
|
+
Large Danger
|
|
119
|
+
</ZestButton>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
```
|
|
123
|
+
*Explore all the recipes in the **[Cookbook](./examples.md)** to see these options in action.*
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Split Buttons & Overflow Menus
|
|
128
|
+
|
|
129
|
+
**What it does:** Attaches a set of secondary actions to a button that already has one obvious default action, via a chevron segment that opens a menu — a discoverable place for "there's more here" without cluttering the UI with extra buttons. Each menu item gets its own independent busy/success/fail/confirm feedback, and the menu can be themed and sized independently of the main button.
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
const MyComponent = () => (
|
|
133
|
+
<ZestButton
|
|
134
|
+
onClick={() => alert('Exported as CSV!')}
|
|
135
|
+
zest={{
|
|
136
|
+
dropdownOptions: [
|
|
137
|
+
{ label: 'Export as PDF', onClick: () => alert('Exported as PDF!') },
|
|
138
|
+
{ label: 'Export as JSON', onClick: () => alert('Exported as JSON!') },
|
|
139
|
+
],
|
|
140
|
+
}}
|
|
141
|
+
>
|
|
142
|
+
Export as CSV
|
|
143
|
+
</ZestButton>
|
|
144
|
+
);
|
|
145
|
+
```
|
|
146
|
+
*__Learn more in the [Split Button with Overflow Actions recipe](./examples.md#recipe-5-a-split-button-with-overflow-actions).__*
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
[⬅️ Previous: The Cookbook (Examples)](./examples.md) | [Next: API Reference ➡️](./api.md)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jattac.libs.web.zest-button",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1",
|
|
4
4
|
"description": "A highly customizable and production-ready React button component featuring robust asynchronous handling, rich visual feedback, and built-in confirmation flows for enhanced user experience",
|
|
5
5
|
"homepage": "https://github.com/nyingimaina/jattac.libs.web.zest-button#readme",
|
|
6
6
|
"repository": {
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"files": [
|
|
17
17
|
"dist",
|
|
18
18
|
"README.md",
|
|
19
|
-
"
|
|
19
|
+
"LICENSE",
|
|
20
|
+
"documentation"
|
|
20
21
|
],
|
|
21
22
|
"scripts": {
|
|
22
23
|
"build": "rollup -c rollup.config.mjs",
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
# Critical Paths
|
|
2
|
-
|
|
3
|
-
This document defines the critical business paths that MUST be covered by e2E tests.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## How to Identify Critical Paths
|
|
8
|
-
|
|
9
|
-
A path is critical if:
|
|
10
|
-
|
|
11
|
-
• It handles money or payments
|
|
12
|
-
|
|
13
|
-
• It manages user authentication or authorization
|
|
14
|
-
|
|
15
|
-
• It writes to the database in ways that affect business data
|
|
16
|
-
|
|
17
|
-
• It integrates with external systems
|
|
18
|
-
|
|
19
|
-
• If broken, it causes immediate user-facing impact
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Paths
|
|
24
|
-
|
|
25
|
-
### Authentication
|
|
26
|
-
|
|
27
|
-
- [ ] Login with valid credentials → 200 + token
|
|
28
|
-
|
|
29
|
-
- [ ] Login with invalid credentials → 401
|
|
30
|
-
|
|
31
|
-
- [ ] Token refresh → 200 + new token
|
|
32
|
-
|
|
33
|
-
- [ ] Logout → 200 + token invalidated
|
|
34
|
-
|
|
35
|
-
### Payment
|
|
36
|
-
|
|
37
|
-
- [ ] Create payment → 201 + payment record
|
|
38
|
-
|
|
39
|
-
- [ ] Confirm payment → 200 + status updated
|
|
40
|
-
|
|
41
|
-
- [ ] Handle payment failure → 200 + status updated
|
|
42
|
-
|
|
43
|
-
- [ ] Process refund → 200 + refund record
|
|
44
|
-
|
|
45
|
-
### Order
|
|
46
|
-
|
|
47
|
-
- [ ] Create order → 201 + order record
|
|
48
|
-
|
|
49
|
-
- [ ] Pay order → 200 + order status updated
|
|
50
|
-
|
|
51
|
-
- [ ] Ship order → 200 + order status updated
|
|
52
|
-
|
|
53
|
-
- [ ] Complete order → 200 + order status updated
|
|
54
|
-
|
|
55
|
-
- [ ] Cancel order → 200 + order status updated
|
|
56
|
-
|
|
57
|
-
### Data
|
|
58
|
-
|
|
59
|
-
- [ ] Import data → 200 + records created
|
|
60
|
-
|
|
61
|
-
- [ ] Export data → 200 + file returned
|
|
62
|
-
|
|
63
|
-
---
|
|
64
|
-
|
|
65
|
-
## Adding New Paths
|
|
66
|
-
|
|
67
|
-
When adding a new critical path:
|
|
68
|
-
|
|
69
|
-
1. Add the path description above
|
|
70
|
-
|
|
71
|
-
2. List each scenario with expected outcome
|
|
72
|
-
|
|
73
|
-
3. Write e2e tests covering each scenario
|
|
74
|
-
|
|
75
|
-
4. Mark scenarios as tested: `- [x]`
|