@delightui/components 0.1.105 → 0.1.107
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 +104 -1
- package/dist/cjs/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/cjs/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/cjs/components/molecules/Modal/index.d.ts +2 -0
- package/dist/cjs/components/molecules/index.d.ts +2 -0
- package/dist/cjs/library.css +19 -6
- package/dist/cjs/library.js +3 -3
- package/dist/cjs/library.js.map +1 -1
- package/dist/esm/components/molecules/Modal/DemoModal.d.ts +8 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.d.ts +41 -0
- package/dist/esm/components/molecules/Modal/ModalContext/ModalContext.types.d.ts +87 -0
- package/dist/esm/components/molecules/Modal/ModalContext/index.d.ts +3 -0
- package/dist/esm/components/molecules/Modal/ModalContext/useModal.d.ts +34 -0
- package/dist/esm/components/molecules/Modal/index.d.ts +2 -0
- package/dist/esm/components/molecules/index.d.ts +2 -0
- package/dist/esm/library.css +19 -6
- package/dist/esm/library.js +3 -3
- package/dist/esm/library.js.map +1 -1
- package/dist/index.d.ts +108 -2
- package/docs/README.md +264 -0
- package/docs/components/atoms/ActionImage.md +119 -0
- package/docs/components/atoms/Button.md +197 -0
- package/docs/components/atoms/Checkbox.md +299 -0
- package/docs/components/atoms/CheckboxItem.md +314 -0
- package/docs/components/atoms/Chip.md +380 -0
- package/docs/components/atoms/CustomToggle.md +270 -0
- package/docs/components/atoms/Icon.md +365 -0
- package/docs/components/atoms/IconButton.md +407 -0
- package/docs/components/atoms/Image.md +448 -0
- package/docs/components/atoms/Input.md +430 -0
- package/docs/components/atoms/ListItem.md +502 -0
- package/docs/components/atoms/Password.md +472 -0
- package/docs/components/atoms/RadioButton.md +614 -0
- package/docs/components/atoms/RadioButtonItem.md +588 -0
- package/docs/components/atoms/ResponsiveComponent.md +612 -0
- package/docs/components/atoms/SelectListItem.md +609 -0
- package/docs/components/atoms/Slider.md +605 -0
- package/docs/components/atoms/Spinner.md +605 -0
- package/docs/components/atoms/Text.md +463 -0
- package/docs/components/atoms/TextArea.md +670 -0
- package/docs/components/atoms/ToastNotification.md +668 -0
- package/docs/components/atoms/Toggle.md +737 -0
- package/docs/components/atoms/ToggleButton.md +751 -0
- package/docs/components/atoms/Tooltip.md +391 -0
- package/docs/components/molecules/Accordion.md +440 -0
- package/docs/components/molecules/AccordionGroup.md +547 -0
- package/docs/components/molecules/ActionCard.md +546 -0
- package/docs/components/molecules/Breadcrumb.md +403 -0
- package/docs/components/molecules/Breadcrumbs.md +485 -0
- package/docs/components/molecules/ButtonGroup.md +383 -0
- package/docs/components/molecules/Card.md +298 -0
- package/docs/components/molecules/ChipInput.md +646 -0
- package/docs/components/molecules/ContextMenu.md +768 -0
- package/docs/components/molecules/CustomTimeSelector.md +116 -0
- package/docs/components/molecules/DatePicker.md +516 -0
- package/docs/components/molecules/DateTimeSelector.md +166 -0
- package/docs/components/molecules/FormField.md +312 -0
- package/docs/components/molecules/Grid.md +577 -0
- package/docs/components/molecules/GridItem.md +834 -0
- package/docs/components/molecules/GridList.md +244 -0
- package/docs/components/molecules/List.md +485 -0
- package/docs/components/molecules/Modal.md +470 -0
- package/docs/components/molecules/ModalFooter.md +702 -0
- package/docs/components/molecules/ModalHeader.md +756 -0
- package/docs/components/molecules/ModalProvider.md +205 -0
- package/docs/components/molecules/Nav.md +530 -0
- package/docs/components/molecules/NavItem.md +572 -0
- package/docs/components/molecules/NavLink.md +499 -0
- package/docs/components/molecules/Option.md +521 -0
- package/docs/components/molecules/Pagination.md +592 -0
- package/docs/components/molecules/PaginationNumberField.md +722 -0
- package/docs/components/molecules/Popover.md +516 -0
- package/docs/components/molecules/ProgressBar.md +624 -0
- package/docs/components/molecules/RadioGroup.md +831 -0
- package/docs/components/molecules/RepeaterList.md +185 -0
- package/docs/components/molecules/Select.md +402 -0
- package/docs/components/molecules/SortableTrigger.md +82 -0
- package/docs/components/molecules/useModal.md +379 -0
- package/docs/components/organisms/Dropzone.md +346 -0
- package/docs/components/organisms/DropzoneClear.md +135 -0
- package/docs/components/organisms/DropzoneContent.md +216 -0
- package/docs/components/organisms/DropzoneFilename.md +191 -0
- package/docs/components/organisms/DropzoneSupportedFormats.md +184 -0
- package/docs/components/organisms/DropzoneTrigger.md +209 -0
- package/docs/components/organisms/Form.md +533 -0
- package/docs/components/organisms/SlideOutPanel.md +662 -0
- package/docs/components/organisms/TabContent.md +902 -0
- package/docs/components/organisms/TabItem.md +1091 -0
- package/docs/components/organisms/Table.md +611 -0
- package/docs/components/organisms/TableBody.md +679 -0
- package/docs/components/organisms/TableCell.md +482 -0
- package/docs/components/organisms/TableHeader.md +513 -0
- package/docs/components/organisms/TableHeaderCell.md +661 -0
- package/docs/components/organisms/TableRow.md +715 -0
- package/docs/components/organisms/Tabs.md +1330 -0
- package/docs/components/utils/ConditionalView.md +568 -0
- package/docs/components/utils/RenderStateView.md +726 -0
- package/docs/components/utils/WrapTextNodes.md +614 -0
- package/package.json +3 -2
|
@@ -0,0 +1,831 @@
|
|
|
1
|
+
# RadioGroup
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
A group container component for radio button options that manages selection state and provides coordinated behavior between radio button children. Supports both horizontal and vertical layouts, form integration, controlled and uncontrolled modes, and accessibility features for creating option selectors, preference settings, and choice-based inputs.
|
|
6
|
+
|
|
7
|
+
## Aliases
|
|
8
|
+
|
|
9
|
+
- RadioGroup
|
|
10
|
+
- RadioButtonGroup
|
|
11
|
+
- OptionGroup
|
|
12
|
+
- ChoiceGroup
|
|
13
|
+
- SelectionGroup
|
|
14
|
+
- RadioSet
|
|
15
|
+
|
|
16
|
+
## Props Breakdown
|
|
17
|
+
|
|
18
|
+
**Extends:** ControlledFormComponentProps<string | number>
|
|
19
|
+
|
|
20
|
+
| Prop | Type | Default | Required | Description |
|
|
21
|
+
|------|------|---------|----------|-------------|
|
|
22
|
+
| `children` | `ReactElement<RadioButtonProps> \| ReactElement<RadioButtonProps>[]` | - | Yes | The radio buttons to render in the group |
|
|
23
|
+
| `orientation` | `'horizontal' \| 'vertical'` | `'vertical'` | No | Layout orientation of the radio group |
|
|
24
|
+
| `value` | `string \| number` | - | No | Current selected value (controlled mode) |
|
|
25
|
+
| `onValueChange` | `(value: string \| number) => void` | - | No | Callback when selection changes |
|
|
26
|
+
| `disabled` | `boolean` | `false` | No | Whether the entire group is disabled |
|
|
27
|
+
| `required` | `boolean` | `false` | No | Whether a selection is required |
|
|
28
|
+
| `invalid` | `boolean` | `false` | No | Whether the current selection is invalid |
|
|
29
|
+
| `className` | `string` | - | No | Additional CSS class names |
|
|
30
|
+
|
|
31
|
+
## Examples
|
|
32
|
+
|
|
33
|
+
### Basic Usage
|
|
34
|
+
```tsx
|
|
35
|
+
import { RadioGroup, RadioButton } from '@delightui/components';
|
|
36
|
+
|
|
37
|
+
function BasicExample() {
|
|
38
|
+
const [selectedSize, setSelectedSize] = useState('medium');
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div className="size-selector">
|
|
42
|
+
<Text type="Heading6">Select Size</Text>
|
|
43
|
+
|
|
44
|
+
<RadioGroup
|
|
45
|
+
value={selectedSize}
|
|
46
|
+
onValueChange={setSelectedSize}
|
|
47
|
+
>
|
|
48
|
+
<RadioButton value="small" label="Small" />
|
|
49
|
+
<RadioButton value="medium" label="Medium" />
|
|
50
|
+
<RadioButton value="large" label="Large" />
|
|
51
|
+
<RadioButton value="xlarge" label="Extra Large" />
|
|
52
|
+
</RadioGroup>
|
|
53
|
+
|
|
54
|
+
<Text type="BodySmall">
|
|
55
|
+
Selected: {selectedSize}
|
|
56
|
+
</Text>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Horizontal Layout
|
|
63
|
+
```tsx
|
|
64
|
+
function HorizontalLayoutExample() {
|
|
65
|
+
const [paymentMethod, setPaymentMethod] = useState('credit');
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="payment-options">
|
|
69
|
+
<Text type="Heading6">Payment Method</Text>
|
|
70
|
+
|
|
71
|
+
<RadioGroup
|
|
72
|
+
value={paymentMethod}
|
|
73
|
+
onValueChange={setPaymentMethod}
|
|
74
|
+
orientation="horizontal"
|
|
75
|
+
className="payment-radio-group"
|
|
76
|
+
>
|
|
77
|
+
<RadioButton
|
|
78
|
+
value="credit"
|
|
79
|
+
label="Credit Card"
|
|
80
|
+
/>
|
|
81
|
+
<RadioButton
|
|
82
|
+
value="debit"
|
|
83
|
+
label="Debit Card"
|
|
84
|
+
/>
|
|
85
|
+
<RadioButton
|
|
86
|
+
value="paypal"
|
|
87
|
+
label="PayPal"
|
|
88
|
+
/>
|
|
89
|
+
<RadioButton
|
|
90
|
+
value="bank"
|
|
91
|
+
label="Bank Transfer"
|
|
92
|
+
/>
|
|
93
|
+
</RadioGroup>
|
|
94
|
+
|
|
95
|
+
<div className="payment-info">
|
|
96
|
+
<Text type="BodySmall">
|
|
97
|
+
You selected: {paymentMethod.replace(/^\w/, c => c.toUpperCase())}
|
|
98
|
+
</Text>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Form Integration
|
|
106
|
+
```tsx
|
|
107
|
+
function FormIntegrationExample() {
|
|
108
|
+
const handleSubmit = (values, setError) => {
|
|
109
|
+
if (!values.priority) {
|
|
110
|
+
setError('priority', 'Please select a priority level');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
console.log('Form submitted:', values);
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
return (
|
|
118
|
+
<Form onSubmit={handleSubmit}>
|
|
119
|
+
<FormField
|
|
120
|
+
name="title"
|
|
121
|
+
label="Issue Title"
|
|
122
|
+
required
|
|
123
|
+
>
|
|
124
|
+
<Input placeholder="Describe the issue" />
|
|
125
|
+
</FormField>
|
|
126
|
+
|
|
127
|
+
<FormField
|
|
128
|
+
name="priority"
|
|
129
|
+
label="Priority Level"
|
|
130
|
+
required
|
|
131
|
+
>
|
|
132
|
+
<RadioGroup>
|
|
133
|
+
<RadioButton
|
|
134
|
+
value="low"
|
|
135
|
+
label="Low Priority"
|
|
136
|
+
description="Minor issues, can wait"
|
|
137
|
+
/>
|
|
138
|
+
<RadioButton
|
|
139
|
+
value="medium"
|
|
140
|
+
label="Medium Priority"
|
|
141
|
+
description="Important but not urgent"
|
|
142
|
+
/>
|
|
143
|
+
<RadioButton
|
|
144
|
+
value="high"
|
|
145
|
+
label="High Priority"
|
|
146
|
+
description="Needs immediate attention"
|
|
147
|
+
/>
|
|
148
|
+
<RadioButton
|
|
149
|
+
value="critical"
|
|
150
|
+
label="Critical"
|
|
151
|
+
description="System down or major issue"
|
|
152
|
+
/>
|
|
153
|
+
</RadioGroup>
|
|
154
|
+
</FormField>
|
|
155
|
+
|
|
156
|
+
<FormField name="description" label="Description">
|
|
157
|
+
<TextArea
|
|
158
|
+
placeholder="Additional details..."
|
|
159
|
+
rows={3}
|
|
160
|
+
/>
|
|
161
|
+
</FormField>
|
|
162
|
+
|
|
163
|
+
<Button actionType="submit">
|
|
164
|
+
Submit Issue
|
|
165
|
+
</Button>
|
|
166
|
+
</Form>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Product Selection
|
|
172
|
+
```tsx
|
|
173
|
+
function ProductSelectionExample() {
|
|
174
|
+
const [selectedPlan, setSelectedPlan] = useState('');
|
|
175
|
+
|
|
176
|
+
const plans = [
|
|
177
|
+
{
|
|
178
|
+
id: 'basic',
|
|
179
|
+
name: 'Basic Plan',
|
|
180
|
+
price: '$9.99/month',
|
|
181
|
+
features: ['5 Projects', '10GB Storage', 'Email Support'],
|
|
182
|
+
recommended: false
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: 'pro',
|
|
186
|
+
name: 'Pro Plan',
|
|
187
|
+
price: '$19.99/month',
|
|
188
|
+
features: ['Unlimited Projects', '100GB Storage', 'Priority Support', 'Advanced Analytics'],
|
|
189
|
+
recommended: true
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'enterprise',
|
|
193
|
+
name: 'Enterprise Plan',
|
|
194
|
+
price: '$49.99/month',
|
|
195
|
+
features: ['Everything in Pro', 'Custom Integrations', 'Dedicated Manager', 'SLA Guarantee'],
|
|
196
|
+
recommended: false
|
|
197
|
+
}
|
|
198
|
+
];
|
|
199
|
+
|
|
200
|
+
return (
|
|
201
|
+
<div className="plan-selector">
|
|
202
|
+
<Text type="Heading5">Choose Your Plan</Text>
|
|
203
|
+
|
|
204
|
+
<RadioGroup
|
|
205
|
+
value={selectedPlan}
|
|
206
|
+
onValueChange={setSelectedPlan}
|
|
207
|
+
className="plan-radio-group"
|
|
208
|
+
>
|
|
209
|
+
<List
|
|
210
|
+
data={plans}
|
|
211
|
+
component={({ id, name, price, features, recommended }) => {
|
|
212
|
+
const FeatureComponent = ({ feature }) => (
|
|
213
|
+
<div className="feature-item">
|
|
214
|
+
<Icon icon="Check" className="feature-icon" />
|
|
215
|
+
<Text type="BodySmall">{feature}</Text>
|
|
216
|
+
</div>
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
return (
|
|
220
|
+
<div className="plan-option">
|
|
221
|
+
<div className="plan-header">
|
|
222
|
+
<RadioButton
|
|
223
|
+
value={id}
|
|
224
|
+
label={
|
|
225
|
+
<div className="plan-title">
|
|
226
|
+
<Text type="Heading6">{name}</Text>
|
|
227
|
+
{recommended && (
|
|
228
|
+
<Chip size="Small" style="Primary">
|
|
229
|
+
Recommended
|
|
230
|
+
</Chip>
|
|
231
|
+
)}
|
|
232
|
+
</div>
|
|
233
|
+
}
|
|
234
|
+
/>
|
|
235
|
+
<Text type="Heading6" className="plan-price">
|
|
236
|
+
{price}
|
|
237
|
+
</Text>
|
|
238
|
+
</div>
|
|
239
|
+
|
|
240
|
+
<div className="plan-features">
|
|
241
|
+
<List
|
|
242
|
+
data={features.map(feature => ({ feature }))}
|
|
243
|
+
component={FeatureComponent}
|
|
244
|
+
keyExtractor={(item) => item.feature}
|
|
245
|
+
/>
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
);
|
|
249
|
+
}}
|
|
250
|
+
keyExtractor={(plan) => plan.id}
|
|
251
|
+
/>
|
|
252
|
+
</RadioGroup>
|
|
253
|
+
|
|
254
|
+
<div className="plan-actions">
|
|
255
|
+
<Button
|
|
256
|
+
disabled={!selectedPlan}
|
|
257
|
+
onClick={() => console.log('Selected plan:', selectedPlan)}
|
|
258
|
+
>
|
|
259
|
+
Continue with {plans.find(p => p.id === selectedPlan)?.name || 'Selected Plan'}
|
|
260
|
+
</Button>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
### Settings Configuration
|
|
268
|
+
```tsx
|
|
269
|
+
function SettingsConfigExample() {
|
|
270
|
+
const [settings, setSettings] = useState({
|
|
271
|
+
theme: 'light',
|
|
272
|
+
notifications: 'email',
|
|
273
|
+
privacy: 'friends',
|
|
274
|
+
language: 'en'
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const updateSetting = (key, value) => {
|
|
278
|
+
setSettings(prev => ({ ...prev, [key]: value }));
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
return (
|
|
282
|
+
<div className="settings-panel">
|
|
283
|
+
<Text type="Heading5">Preferences</Text>
|
|
284
|
+
|
|
285
|
+
<div className="settings-section">
|
|
286
|
+
<Text type="Heading6">Theme</Text>
|
|
287
|
+
<RadioGroup
|
|
288
|
+
value={settings.theme}
|
|
289
|
+
onValueChange={(value) => updateSetting('theme', value)}
|
|
290
|
+
orientation="horizontal"
|
|
291
|
+
>
|
|
292
|
+
<RadioButton
|
|
293
|
+
value="light"
|
|
294
|
+
label="Light"
|
|
295
|
+
/>
|
|
296
|
+
<RadioButton
|
|
297
|
+
value="dark"
|
|
298
|
+
label="Dark"
|
|
299
|
+
/>
|
|
300
|
+
<RadioButton
|
|
301
|
+
value="auto"
|
|
302
|
+
label="Auto"
|
|
303
|
+
/>
|
|
304
|
+
</RadioGroup>
|
|
305
|
+
</div>
|
|
306
|
+
|
|
307
|
+
<div className="settings-section">
|
|
308
|
+
<Text type="Heading6">Notifications</Text>
|
|
309
|
+
<RadioGroup
|
|
310
|
+
value={settings.notifications}
|
|
311
|
+
onValueChange={(value) => updateSetting('notifications', value)}
|
|
312
|
+
>
|
|
313
|
+
<RadioButton
|
|
314
|
+
value="all"
|
|
315
|
+
label="All Notifications"
|
|
316
|
+
description="Receive all notifications via email and push"
|
|
317
|
+
/>
|
|
318
|
+
<RadioButton
|
|
319
|
+
value="email"
|
|
320
|
+
label="Email Only"
|
|
321
|
+
description="Only receive email notifications"
|
|
322
|
+
/>
|
|
323
|
+
<RadioButton
|
|
324
|
+
value="push"
|
|
325
|
+
label="Push Only"
|
|
326
|
+
description="Only receive push notifications"
|
|
327
|
+
/>
|
|
328
|
+
<RadioButton
|
|
329
|
+
value="none"
|
|
330
|
+
label="None"
|
|
331
|
+
description="Disable all notifications"
|
|
332
|
+
/>
|
|
333
|
+
</RadioGroup>
|
|
334
|
+
</div>
|
|
335
|
+
|
|
336
|
+
<div className="settings-section">
|
|
337
|
+
<Text type="Heading6">Privacy</Text>
|
|
338
|
+
<RadioGroup
|
|
339
|
+
value={settings.privacy}
|
|
340
|
+
onValueChange={(value) => updateSetting('privacy', value)}
|
|
341
|
+
>
|
|
342
|
+
<RadioButton
|
|
343
|
+
value="public"
|
|
344
|
+
label="Public"
|
|
345
|
+
description="Anyone can see your profile"
|
|
346
|
+
/>
|
|
347
|
+
<RadioButton
|
|
348
|
+
value="friends"
|
|
349
|
+
label="Friends Only"
|
|
350
|
+
description="Only friends can see your profile"
|
|
351
|
+
/>
|
|
352
|
+
<RadioButton
|
|
353
|
+
value="private"
|
|
354
|
+
label="Private"
|
|
355
|
+
description="Only you can see your profile"
|
|
356
|
+
/>
|
|
357
|
+
</RadioGroup>
|
|
358
|
+
</div>
|
|
359
|
+
|
|
360
|
+
<div className="settings-actions">
|
|
361
|
+
<Button type="Outlined">
|
|
362
|
+
Reset to Defaults
|
|
363
|
+
</Button>
|
|
364
|
+
<Button>
|
|
365
|
+
Save Settings
|
|
366
|
+
</Button>
|
|
367
|
+
</div>
|
|
368
|
+
</div>
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Survey Question
|
|
374
|
+
```tsx
|
|
375
|
+
function SurveyQuestionExample() {
|
|
376
|
+
const [answers, setAnswers] = useState({});
|
|
377
|
+
const [currentQuestion, setCurrentQuestion] = useState(0);
|
|
378
|
+
|
|
379
|
+
const questions = [
|
|
380
|
+
{
|
|
381
|
+
id: 'satisfaction',
|
|
382
|
+
question: 'How satisfied are you with our service?',
|
|
383
|
+
options: [
|
|
384
|
+
{ value: 'very-satisfied', label: 'Very Satisfied', emoji: '😍' },
|
|
385
|
+
{ value: 'satisfied', label: 'Satisfied', emoji: '😊' },
|
|
386
|
+
{ value: 'neutral', label: 'Neutral', emoji: '😐' },
|
|
387
|
+
{ value: 'dissatisfied', label: 'Dissatisfied', emoji: '😞' },
|
|
388
|
+
{ value: 'very-dissatisfied', label: 'Very Dissatisfied', emoji: '😤' }
|
|
389
|
+
]
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
id: 'recommend',
|
|
393
|
+
question: 'How likely are you to recommend us to others?',
|
|
394
|
+
options: [
|
|
395
|
+
{ value: '10', label: 'Extremely Likely (10)' },
|
|
396
|
+
{ value: '9', label: 'Very Likely (9)' },
|
|
397
|
+
{ value: '8', label: 'Likely (8)' },
|
|
398
|
+
{ value: '7', label: 'Somewhat Likely (7)' },
|
|
399
|
+
{ value: '6', label: 'Neutral (6)' },
|
|
400
|
+
{ value: '5', label: 'Somewhat Unlikely (5)' },
|
|
401
|
+
{ value: '4', label: 'Unlikely (4)' },
|
|
402
|
+
{ value: '3', label: 'Very Unlikely (3)' },
|
|
403
|
+
{ value: '2', label: 'Extremely Unlikely (2)' },
|
|
404
|
+
{ value: '1', label: 'Not at All Likely (1)' }
|
|
405
|
+
]
|
|
406
|
+
}
|
|
407
|
+
];
|
|
408
|
+
|
|
409
|
+
const currentQ = questions[currentQuestion];
|
|
410
|
+
|
|
411
|
+
const nextQuestion = () => {
|
|
412
|
+
if (currentQuestion < questions.length - 1) {
|
|
413
|
+
setCurrentQuestion(prev => prev + 1);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
|
|
417
|
+
const prevQuestion = () => {
|
|
418
|
+
if (currentQuestion > 0) {
|
|
419
|
+
setCurrentQuestion(prev => prev - 1);
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const updateAnswer = (questionId, value) => {
|
|
424
|
+
setAnswers(prev => ({ ...prev, [questionId]: value }));
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
return (
|
|
428
|
+
<div className="survey-form">
|
|
429
|
+
<div className="survey-header">
|
|
430
|
+
<Text type="Heading5">Customer Feedback Survey</Text>
|
|
431
|
+
<Text type="BodySmall">
|
|
432
|
+
Question {currentQuestion + 1} of {questions.length}
|
|
433
|
+
</Text>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
<ProgressBar
|
|
437
|
+
value={((currentQuestion + 1) / questions.length) * 100}
|
|
438
|
+
showLabel="Text"
|
|
439
|
+
label={`${currentQuestion + 1} of ${questions.length} completed`}
|
|
440
|
+
/>
|
|
441
|
+
|
|
442
|
+
<div className="survey-question">
|
|
443
|
+
<Text type="Heading6">{currentQ.question}</Text>
|
|
444
|
+
|
|
445
|
+
<RadioGroup
|
|
446
|
+
value={answers[currentQ.id] || ''}
|
|
447
|
+
onValueChange={(value) => updateAnswer(currentQ.id, value)}
|
|
448
|
+
className="survey-options"
|
|
449
|
+
>
|
|
450
|
+
{currentQ.options.map(option => (
|
|
451
|
+
<RadioButton
|
|
452
|
+
key={option.value}
|
|
453
|
+
value={option.value}
|
|
454
|
+
label={
|
|
455
|
+
<div className="survey-option">
|
|
456
|
+
{option.emoji && (
|
|
457
|
+
<span className="option-emoji">{option.emoji}</span>
|
|
458
|
+
)}
|
|
459
|
+
<Text>{option.label}</Text>
|
|
460
|
+
</div>
|
|
461
|
+
}
|
|
462
|
+
/>
|
|
463
|
+
))}
|
|
464
|
+
</RadioGroup>
|
|
465
|
+
</div>
|
|
466
|
+
|
|
467
|
+
<div className="survey-navigation">
|
|
468
|
+
<Button
|
|
469
|
+
type="Outlined"
|
|
470
|
+
onClick={prevQuestion}
|
|
471
|
+
disabled={currentQuestion === 0}
|
|
472
|
+
>
|
|
473
|
+
Previous
|
|
474
|
+
</Button>
|
|
475
|
+
|
|
476
|
+
<div className="survey-progress">
|
|
477
|
+
{questions.map((_, index) => (
|
|
478
|
+
<div
|
|
479
|
+
key={index}
|
|
480
|
+
className={`progress-dot ${
|
|
481
|
+
index === currentQuestion ? 'current' :
|
|
482
|
+
answers[questions[index].id] ? 'completed' : 'pending'
|
|
483
|
+
}`}
|
|
484
|
+
/>
|
|
485
|
+
))}
|
|
486
|
+
</div>
|
|
487
|
+
|
|
488
|
+
<Button
|
|
489
|
+
onClick={nextQuestion}
|
|
490
|
+
disabled={!answers[currentQ.id] || currentQuestion === questions.length - 1}
|
|
491
|
+
>
|
|
492
|
+
{currentQuestion === questions.length - 1 ? 'Submit' : 'Next'}
|
|
493
|
+
</Button>
|
|
494
|
+
</div>
|
|
495
|
+
</div>
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
### Shipping Options
|
|
501
|
+
```tsx
|
|
502
|
+
function ShippingOptionsExample() {
|
|
503
|
+
const [selectedShipping, setSelectedShipping] = useState('');
|
|
504
|
+
|
|
505
|
+
const shippingOptions = [
|
|
506
|
+
{
|
|
507
|
+
id: 'standard',
|
|
508
|
+
name: 'Standard Shipping',
|
|
509
|
+
price: 'Free',
|
|
510
|
+
duration: '5-7 business days',
|
|
511
|
+
description: 'Free standard delivery'
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
id: 'express',
|
|
515
|
+
name: 'Express Shipping',
|
|
516
|
+
price: '$9.99',
|
|
517
|
+
duration: '2-3 business days',
|
|
518
|
+
description: 'Faster delivery for urgent orders'
|
|
519
|
+
},
|
|
520
|
+
{
|
|
521
|
+
id: 'overnight',
|
|
522
|
+
name: 'Overnight Delivery',
|
|
523
|
+
price: '$24.99',
|
|
524
|
+
duration: '1 business day',
|
|
525
|
+
description: 'Next business day delivery'
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: 'weekend',
|
|
529
|
+
name: 'Weekend Delivery',
|
|
530
|
+
price: '$19.99',
|
|
531
|
+
duration: 'Saturday delivery',
|
|
532
|
+
description: 'Delivered on Saturday'
|
|
533
|
+
}
|
|
534
|
+
];
|
|
535
|
+
|
|
536
|
+
const selectedOption = shippingOptions.find(opt => opt.id === selectedShipping);
|
|
537
|
+
|
|
538
|
+
return (
|
|
539
|
+
<div className="shipping-selector">
|
|
540
|
+
<Text type="Heading6">Choose Shipping Method</Text>
|
|
541
|
+
|
|
542
|
+
<RadioGroup
|
|
543
|
+
value={selectedShipping}
|
|
544
|
+
onValueChange={setSelectedShipping}
|
|
545
|
+
required
|
|
546
|
+
className="shipping-options"
|
|
547
|
+
>
|
|
548
|
+
{shippingOptions.map(option => (
|
|
549
|
+
<div key={option.id} className="shipping-option">
|
|
550
|
+
<RadioButton
|
|
551
|
+
value={option.id}
|
|
552
|
+
label={
|
|
553
|
+
<div className="shipping-details">
|
|
554
|
+
<div className="shipping-header">
|
|
555
|
+
<Text type="BodyMedium">{option.name}</Text>
|
|
556
|
+
<Text type="BodyMedium" className="shipping-price">
|
|
557
|
+
{option.price}
|
|
558
|
+
</Text>
|
|
559
|
+
</div>
|
|
560
|
+
|
|
561
|
+
<div className="shipping-info">
|
|
562
|
+
<Text type="BodySmall" className="delivery-time">
|
|
563
|
+
<Icon icon="Clock" size="Small" />
|
|
564
|
+
{option.duration}
|
|
565
|
+
</Text>
|
|
566
|
+
<Text type="BodySmall" className="shipping-desc">
|
|
567
|
+
{option.description}
|
|
568
|
+
</Text>
|
|
569
|
+
</div>
|
|
570
|
+
</div>
|
|
571
|
+
}
|
|
572
|
+
/>
|
|
573
|
+
</div>
|
|
574
|
+
))}
|
|
575
|
+
</RadioGroup>
|
|
576
|
+
|
|
577
|
+
{selectedOption && (
|
|
578
|
+
<div className="shipping-summary">
|
|
579
|
+
<Text type="BodySmall">
|
|
580
|
+
Selected: {selectedOption.name} - {selectedOption.price}
|
|
581
|
+
</Text>
|
|
582
|
+
<Text type="BodySmall">
|
|
583
|
+
Estimated delivery: {selectedOption.duration}
|
|
584
|
+
</Text>
|
|
585
|
+
</div>
|
|
586
|
+
)}
|
|
587
|
+
</div>
|
|
588
|
+
);
|
|
589
|
+
}
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Quiz Question
|
|
593
|
+
```tsx
|
|
594
|
+
function QuizQuestionExample() {
|
|
595
|
+
const [selectedAnswer, setSelectedAnswer] = useState('');
|
|
596
|
+
const [showResult, setShowResult] = useState(false);
|
|
597
|
+
|
|
598
|
+
const question = {
|
|
599
|
+
question: 'What is the capital of France?',
|
|
600
|
+
options: [
|
|
601
|
+
{ id: 'a', text: 'London', correct: false },
|
|
602
|
+
{ id: 'b', text: 'Berlin', correct: false },
|
|
603
|
+
{ id: 'c', text: 'Paris', correct: true },
|
|
604
|
+
{ id: 'd', text: 'Madrid', correct: false }
|
|
605
|
+
]
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
const submitAnswer = () => {
|
|
609
|
+
setShowResult(true);
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
const resetQuestion = () => {
|
|
613
|
+
setSelectedAnswer('');
|
|
614
|
+
setShowResult(false);
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
const correctAnswer = question.options.find(opt => opt.correct);
|
|
618
|
+
const selectedOption = question.options.find(opt => opt.id === selectedAnswer);
|
|
619
|
+
const isCorrect = selectedOption?.correct || false;
|
|
620
|
+
|
|
621
|
+
return (
|
|
622
|
+
<div className="quiz-question">
|
|
623
|
+
<Text type="Heading6">Quiz Question</Text>
|
|
624
|
+
|
|
625
|
+
<div className="question-text">
|
|
626
|
+
<Text type="BodyMedium">{question.question}</Text>
|
|
627
|
+
</div>
|
|
628
|
+
|
|
629
|
+
<RadioGroup
|
|
630
|
+
value={selectedAnswer}
|
|
631
|
+
onValueChange={setSelectedAnswer}
|
|
632
|
+
disabled={showResult}
|
|
633
|
+
className="quiz-options"
|
|
634
|
+
>
|
|
635
|
+
{question.options.map(option => (
|
|
636
|
+
<div
|
|
637
|
+
key={option.id}
|
|
638
|
+
className={`quiz-option ${
|
|
639
|
+
showResult ? (
|
|
640
|
+
option.correct ? 'correct' :
|
|
641
|
+
option.id === selectedAnswer && !option.correct ? 'incorrect' :
|
|
642
|
+
'neutral'
|
|
643
|
+
) : ''
|
|
644
|
+
}`}
|
|
645
|
+
>
|
|
646
|
+
<RadioButton
|
|
647
|
+
value={option.id}
|
|
648
|
+
label={
|
|
649
|
+
<div className="option-content">
|
|
650
|
+
<Text>{option.id.toUpperCase()}. {option.text}</Text>
|
|
651
|
+
{showResult && option.correct && (
|
|
652
|
+
<Icon icon="CheckCircle" className="correct-icon" />
|
|
653
|
+
)}
|
|
654
|
+
{showResult && option.id === selectedAnswer && !option.correct && (
|
|
655
|
+
<Icon icon="XCircle" className="incorrect-icon" />
|
|
656
|
+
)}
|
|
657
|
+
</div>
|
|
658
|
+
}
|
|
659
|
+
/>
|
|
660
|
+
</div>
|
|
661
|
+
))}
|
|
662
|
+
</RadioGroup>
|
|
663
|
+
|
|
664
|
+
{!showResult ? (
|
|
665
|
+
<Button
|
|
666
|
+
onClick={submitAnswer}
|
|
667
|
+
disabled={!selectedAnswer}
|
|
668
|
+
>
|
|
669
|
+
Submit Answer
|
|
670
|
+
</Button>
|
|
671
|
+
) : (
|
|
672
|
+
<div className="quiz-result">
|
|
673
|
+
<div className={`result-message ${isCorrect ? 'correct' : 'incorrect'}`}>
|
|
674
|
+
<Icon
|
|
675
|
+
icon={isCorrect ? 'CheckCircle' : 'XCircle'}
|
|
676
|
+
className="result-icon"
|
|
677
|
+
/>
|
|
678
|
+
<Text type="BodyMedium">
|
|
679
|
+
{isCorrect ? 'Correct!' : 'Incorrect'}
|
|
680
|
+
</Text>
|
|
681
|
+
</div>
|
|
682
|
+
|
|
683
|
+
{!isCorrect && (
|
|
684
|
+
<Text type="BodySmall">
|
|
685
|
+
The correct answer is: {correctAnswer.text}
|
|
686
|
+
</Text>
|
|
687
|
+
)}
|
|
688
|
+
|
|
689
|
+
<Button type="Outlined" onClick={resetQuestion}>
|
|
690
|
+
Try Again
|
|
691
|
+
</Button>
|
|
692
|
+
</div>
|
|
693
|
+
)}
|
|
694
|
+
</div>
|
|
695
|
+
);
|
|
696
|
+
}
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### Accessibility Enhanced RadioGroup
|
|
700
|
+
```tsx
|
|
701
|
+
function AccessibilityExample() {
|
|
702
|
+
const [accessibility, setAccessibility] = useState({
|
|
703
|
+
fontSize: 'medium',
|
|
704
|
+
contrast: 'normal',
|
|
705
|
+
motionPreference: 'normal'
|
|
706
|
+
});
|
|
707
|
+
|
|
708
|
+
const updateAccessibility = (key, value) => {
|
|
709
|
+
setAccessibility(prev => ({ ...prev, [key]: value }));
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
return (
|
|
713
|
+
<div className="accessibility-settings">
|
|
714
|
+
<Text type="Heading5">Accessibility Preferences</Text>
|
|
715
|
+
|
|
716
|
+
<div className="accessibility-section">
|
|
717
|
+
<Text type="Heading6">Font Size</Text>
|
|
718
|
+
<Text type="BodySmall">
|
|
719
|
+
Choose a comfortable reading size
|
|
720
|
+
</Text>
|
|
721
|
+
|
|
722
|
+
<RadioGroup
|
|
723
|
+
value={accessibility.fontSize}
|
|
724
|
+
onValueChange={(value) => updateAccessibility('fontSize', value)}
|
|
725
|
+
orientation="horizontal"
|
|
726
|
+
className="font-size-options"
|
|
727
|
+
>
|
|
728
|
+
<RadioButton
|
|
729
|
+
value="small"
|
|
730
|
+
label="Small"
|
|
731
|
+
aria-describedby="font-small-desc"
|
|
732
|
+
/>
|
|
733
|
+
<RadioButton
|
|
734
|
+
value="medium"
|
|
735
|
+
label="Medium"
|
|
736
|
+
aria-describedby="font-medium-desc"
|
|
737
|
+
/>
|
|
738
|
+
<RadioButton
|
|
739
|
+
value="large"
|
|
740
|
+
label="Large"
|
|
741
|
+
aria-describedby="font-large-desc"
|
|
742
|
+
/>
|
|
743
|
+
<RadioButton
|
|
744
|
+
value="xlarge"
|
|
745
|
+
label="Extra Large"
|
|
746
|
+
aria-describedby="font-xlarge-desc"
|
|
747
|
+
/>
|
|
748
|
+
</RadioGroup>
|
|
749
|
+
</div>
|
|
750
|
+
|
|
751
|
+
<div className="accessibility-section">
|
|
752
|
+
<Text type="Heading6">Color Contrast</Text>
|
|
753
|
+
<Text type="BodySmall">
|
|
754
|
+
Adjust contrast for better visibility
|
|
755
|
+
</Text>
|
|
756
|
+
|
|
757
|
+
<RadioGroup
|
|
758
|
+
value={accessibility.contrast}
|
|
759
|
+
onValueChange={(value) => updateAccessibility('contrast', value)}
|
|
760
|
+
>
|
|
761
|
+
<RadioButton
|
|
762
|
+
value="normal"
|
|
763
|
+
label="Normal Contrast"
|
|
764
|
+
description="Standard color scheme"
|
|
765
|
+
/>
|
|
766
|
+
<RadioButton
|
|
767
|
+
value="high"
|
|
768
|
+
label="High Contrast"
|
|
769
|
+
description="Enhanced contrast for better readability"
|
|
770
|
+
/>
|
|
771
|
+
<RadioButton
|
|
772
|
+
value="dark"
|
|
773
|
+
label="Dark Mode"
|
|
774
|
+
description="Dark background with light text"
|
|
775
|
+
/>
|
|
776
|
+
</RadioGroup>
|
|
777
|
+
</div>
|
|
778
|
+
|
|
779
|
+
<div className="accessibility-section">
|
|
780
|
+
<Text type="Heading6">Motion Preference</Text>
|
|
781
|
+
<Text type="BodySmall">
|
|
782
|
+
Control animations and transitions
|
|
783
|
+
</Text>
|
|
784
|
+
|
|
785
|
+
<RadioGroup
|
|
786
|
+
value={accessibility.motionPreference}
|
|
787
|
+
onValueChange={(value) => updateAccessibility('motionPreference', value)}
|
|
788
|
+
>
|
|
789
|
+
<RadioButton
|
|
790
|
+
value="normal"
|
|
791
|
+
label="Normal Motion"
|
|
792
|
+
description="Standard animations and transitions"
|
|
793
|
+
/>
|
|
794
|
+
<RadioButton
|
|
795
|
+
value="reduced"
|
|
796
|
+
label="Reduced Motion"
|
|
797
|
+
description="Minimal animations for sensitivity"
|
|
798
|
+
/>
|
|
799
|
+
<RadioButton
|
|
800
|
+
value="none"
|
|
801
|
+
label="No Motion"
|
|
802
|
+
description="Disable all animations"
|
|
803
|
+
/>
|
|
804
|
+
</RadioGroup>
|
|
805
|
+
</div>
|
|
806
|
+
|
|
807
|
+
<div className="preview-section">
|
|
808
|
+
<Text type="Heading6">Preview</Text>
|
|
809
|
+
<div
|
|
810
|
+
className={`preview-area
|
|
811
|
+
font-${accessibility.fontSize}
|
|
812
|
+
contrast-${accessibility.contrast}
|
|
813
|
+
motion-${accessibility.motionPreference}`}
|
|
814
|
+
>
|
|
815
|
+
<Text>This is how your settings will look.</Text>
|
|
816
|
+
<Button size="Small">Sample Button</Button>
|
|
817
|
+
</div>
|
|
818
|
+
</div>
|
|
819
|
+
|
|
820
|
+
<div className="accessibility-actions">
|
|
821
|
+
<Button type="Outlined">
|
|
822
|
+
Reset Defaults
|
|
823
|
+
</Button>
|
|
824
|
+
<Button>
|
|
825
|
+
Apply Settings
|
|
826
|
+
</Button>
|
|
827
|
+
</div>
|
|
828
|
+
</div>
|
|
829
|
+
);
|
|
830
|
+
}
|
|
831
|
+
```
|