@nationaldesignstudio/react 0.5.4 → 0.5.6
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/component-registry.md +1286 -40
- package/dist/index.d.ts +1572 -133
- package/dist/index.js +2245 -257
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +680 -0
- package/package.json +20 -1
- package/src/components/atoms/blurred-video-backdrop/blurred-video-backdrop.tsx +447 -0
- package/src/components/atoms/button/icon-button.tsx +10 -4
- package/src/components/atoms/select/select.tsx +202 -49
- package/src/components/atoms/video-player/caption-overlay.tsx +107 -0
- package/src/components/atoms/video-player/video-player.tsx +811 -0
- package/src/components/molecules/dialog/dialog.tsx +526 -0
- package/src/components/molecules/video-dialog/video-dialog.tsx +272 -0
- package/src/components/molecules/video-with-backdrop/video-with-backdrop.tsx +383 -0
- package/src/hooks/index.ts +16 -0
- package/src/hooks/use-breakpoint.ts +145 -0
- package/src/hooks/use-captions.ts +247 -0
- package/src/hooks/use-video-keyboard.ts +230 -0
- package/src/lib/utils.ts +8 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Component Registry
|
|
2
2
|
|
|
3
3
|
> Auto-generated component metadata for AI/agent consumption.
|
|
4
|
-
> Generated: 2026-01-
|
|
4
|
+
> Generated: 2026-01-20T19:14:31.863Z
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -346,7 +346,7 @@ className="font-semibold" // Font weight 600
|
|
|
346
346
|
<Button size="md" variant="primary">
|
|
347
347
|
Primary
|
|
348
348
|
</Button>
|
|
349
|
-
<Button size="md" variant="
|
|
349
|
+
<Button size="md" variant="outline">
|
|
350
350
|
Secondary
|
|
351
351
|
</Button>
|
|
352
352
|
</CardActions>
|
|
@@ -374,7 +374,7 @@ className="font-semibold" // Font weight 600
|
|
|
374
374
|
<Button size="md" variant="primary">
|
|
375
375
|
Primary
|
|
376
376
|
</Button>
|
|
377
|
-
<Button size="md" variant="
|
|
377
|
+
<Button size="md" variant="outline">
|
|
378
378
|
Secondary
|
|
379
379
|
</Button>
|
|
380
380
|
</CardActions>
|
|
@@ -404,7 +404,7 @@ className="font-semibold" // Font weight 600
|
|
|
404
404
|
<Button size="sm" variant="primary">
|
|
405
405
|
Primary
|
|
406
406
|
</Button>
|
|
407
|
-
<Button size="sm" variant="
|
|
407
|
+
<Button size="sm" variant="outline">
|
|
408
408
|
Secondary
|
|
409
409
|
</Button>
|
|
410
410
|
</CardActions>
|
|
@@ -538,7 +538,7 @@ className="font-semibold" // Font weight 600
|
|
|
538
538
|
<Button size="md" variant="primary">
|
|
539
539
|
Primary
|
|
540
540
|
</Button>
|
|
541
|
-
<Button size="md" variant="
|
|
541
|
+
<Button size="md" variant="outline">
|
|
542
542
|
Secondary
|
|
543
543
|
</Button>
|
|
544
544
|
</CardActions>
|
|
@@ -1288,6 +1288,248 @@ className="font-semibold" // Font weight 600
|
|
|
1288
1288
|
```
|
|
1289
1289
|
|
|
1290
1290
|
|
|
1291
|
+
### BlurredVideoBackdrop
|
|
1292
|
+
|
|
1293
|
+
**Import:** `import { BlurredVideoBackdrop } from "@nationaldesignstudio/react";`
|
|
1294
|
+
|
|
1295
|
+
**Category:** Other
|
|
1296
|
+
|
|
1297
|
+
**Props:**
|
|
1298
|
+
|
|
1299
|
+
- `videoRef`: React.RefObject<HTMLVideoElement | null> (required)
|
|
1300
|
+
Ref to the primary video element to create backdrop from (required) */
|
|
1301
|
+
- `opacity`: number
|
|
1302
|
+
Opacity of the backdrop (0-1, default: 0.6) */
|
|
1303
|
+
- `extension`: number
|
|
1304
|
+
Extension amount in pixels to cover blur artifacts (default: 120) */
|
|
1305
|
+
- `targetFps`: number
|
|
1306
|
+
Target FPS for canvas rendering (default: 30) */
|
|
1307
|
+
- `scale`: number
|
|
1308
|
+
Canvas scale factor - lower = better performance (default: 0.5) */
|
|
1309
|
+
- `showMetrics`: boolean
|
|
1310
|
+
Whether to show debug metrics */
|
|
1311
|
+
|
|
1312
|
+
**Examples:**
|
|
1313
|
+
|
|
1314
|
+
```tsx
|
|
1315
|
+
<div className="relative w-full h-[600px] bg-black overflow-hidden">
|
|
1316
|
+
<BlurredVideoBackdrop {...args} videoRef={videoRef} />
|
|
1317
|
+
<div className="relative z-10 flex items-center justify-center h-full p-48">
|
|
1318
|
+
<div className="w-full max-w-[800px]">
|
|
1319
|
+
<VideoPlayer
|
|
1320
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1321
|
+
videoRef={videoRef}
|
|
1322
|
+
rounded="lg"
|
|
1323
|
+
/>
|
|
1324
|
+
</div>
|
|
1325
|
+
</div>
|
|
1326
|
+
</div>
|
|
1327
|
+
```
|
|
1328
|
+
|
|
1329
|
+
```tsx
|
|
1330
|
+
<div className="relative w-full h-[500px] bg-black overflow-hidden">
|
|
1331
|
+
<BlurredVideoBackdrop videoRef={videoRef} blur="high" />
|
|
1332
|
+
<div className="relative z-10 flex items-center justify-center h-full p-48">
|
|
1333
|
+
<div className="w-full max-w-[640px]">
|
|
1334
|
+
<VideoPlayer
|
|
1335
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1336
|
+
videoRef={videoRef}
|
|
1337
|
+
rounded="md"
|
|
1338
|
+
/>
|
|
1339
|
+
</div>
|
|
1340
|
+
</div>
|
|
1341
|
+
</div>
|
|
1342
|
+
```
|
|
1343
|
+
|
|
1344
|
+
```tsx
|
|
1345
|
+
<div className="flex flex-col gap-24 p-24">
|
|
1346
|
+
<h2 className="typography-h3-md text-white">Blur Intensity Levels</h2>
|
|
1347
|
+
<div className="grid grid-cols-2 gap-24">
|
|
1348
|
+
{configs.map(({ blur, ref }) => (
|
|
1349
|
+
<div key={blur} className="flex flex-col gap-8">
|
|
1350
|
+
<p className="text-white/80 text-14 capitalize">{blur}</p>
|
|
1351
|
+
<div className="relative h-[200px] bg-black rounded-8 overflow-hidden">
|
|
1352
|
+
<BlurredVideoBackdrop
|
|
1353
|
+
videoRef={ref}
|
|
1354
|
+
blur={blur}
|
|
1355
|
+
opacity={0.8}
|
|
1356
|
+
showMetrics
|
|
1357
|
+
/>
|
|
1358
|
+
<div className="relative z-10 flex items-center justify-center h-full p-8">
|
|
1359
|
+
<div className="w-full max-w-[240px]">
|
|
1360
|
+
<VideoPlayer
|
|
1361
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1362
|
+
videoRef={ref}
|
|
1363
|
+
rounded="sm"
|
|
1364
|
+
/>
|
|
1365
|
+
</div>
|
|
1366
|
+
</div>
|
|
1367
|
+
</div>
|
|
1368
|
+
</div>
|
|
1369
|
+
))}
|
|
1370
|
+
</div>
|
|
1371
|
+
</div>
|
|
1372
|
+
```
|
|
1373
|
+
|
|
1374
|
+
```tsx
|
|
1375
|
+
<div className="flex flex-col gap-24 p-24">
|
|
1376
|
+
<h2 className="typography-h3-md text-white">Gradient Overlays</h2>
|
|
1377
|
+
<div className="grid grid-cols-3 gap-24">
|
|
1378
|
+
{configs.map(({ overlay, ref }) => (
|
|
1379
|
+
<div key={overlay} className="flex flex-col gap-8">
|
|
1380
|
+
<p className="text-white/80 text-14 capitalize">{overlay}</p>
|
|
1381
|
+
<div className="relative h-[200px] bg-black rounded-8 overflow-hidden">
|
|
1382
|
+
<BlurredVideoBackdrop
|
|
1383
|
+
videoRef={ref}
|
|
1384
|
+
blur="high"
|
|
1385
|
+
overlay={overlay}
|
|
1386
|
+
opacity={0.8}
|
|
1387
|
+
/>
|
|
1388
|
+
<div className="relative z-10 flex items-center justify-center h-full p-8">
|
|
1389
|
+
<div className="w-full max-w-[200px]">
|
|
1390
|
+
<VideoPlayer
|
|
1391
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1392
|
+
videoRef={ref}
|
|
1393
|
+
rounded="sm"
|
|
1394
|
+
/>
|
|
1395
|
+
</div>
|
|
1396
|
+
</div>
|
|
1397
|
+
</div>
|
|
1398
|
+
</div>
|
|
1399
|
+
))}
|
|
1400
|
+
</div>
|
|
1401
|
+
</div>
|
|
1402
|
+
```
|
|
1403
|
+
|
|
1404
|
+
```tsx
|
|
1405
|
+
<div className="flex flex-col gap-24 p-24">
|
|
1406
|
+
<div>
|
|
1407
|
+
<h2 className="typography-h3-md text-white mb-8">
|
|
1408
|
+
Scale Factor Impact
|
|
1409
|
+
</h2>
|
|
1410
|
+
<p className="text-gray-400 text-14">
|
|
1411
|
+
Lower scale factors render at reduced resolution for better
|
|
1412
|
+
performance. The blur effect hides most quality loss.
|
|
1413
|
+
</p>
|
|
1414
|
+
</div>
|
|
1415
|
+
<div className="grid grid-cols-2 gap-16">
|
|
1416
|
+
{scales.map(({ scale, ref, label }) => (
|
|
1417
|
+
<div key={scale} className="flex flex-col gap-8">
|
|
1418
|
+
<p className="text-white/80 text-14">{label}</p>
|
|
1419
|
+
<div className="relative h-[250px] bg-black rounded-8 overflow-hidden">
|
|
1420
|
+
<BlurredVideoBackdrop
|
|
1421
|
+
videoRef={ref}
|
|
1422
|
+
blur="high"
|
|
1423
|
+
scale={scale}
|
|
1424
|
+
targetFps={30}
|
|
1425
|
+
showMetrics
|
|
1426
|
+
opacity={0.8}
|
|
1427
|
+
/>
|
|
1428
|
+
<div className="relative z-10 flex items-center justify-center h-full p-16">
|
|
1429
|
+
<div className="w-full max-w-[300px]">
|
|
1430
|
+
<VideoPlayer
|
|
1431
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1432
|
+
videoRef={ref}
|
|
1433
|
+
rounded="sm"
|
|
1434
|
+
/>
|
|
1435
|
+
</div>
|
|
1436
|
+
</div>
|
|
1437
|
+
</div>
|
|
1438
|
+
</div>
|
|
1439
|
+
))}
|
|
1440
|
+
</div>
|
|
1441
|
+
</div>
|
|
1442
|
+
```
|
|
1443
|
+
|
|
1444
|
+
```tsx
|
|
1445
|
+
<div className="flex flex-col gap-16 p-24">
|
|
1446
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
1447
|
+
Click the button to open a video dialog with blurred backdrop. The
|
|
1448
|
+
backdrop renders from the same video element - no sync needed.
|
|
1449
|
+
</p>
|
|
1450
|
+
<Dialog
|
|
1451
|
+
trigger={<Button>Watch Video with Blur Backdrop</Button>}
|
|
1452
|
+
size="full"
|
|
1453
|
+
variant="minimal"
|
|
1454
|
+
showClose={true}
|
|
1455
|
+
open={open}
|
|
1456
|
+
onOpenChange={setOpen}
|
|
1457
|
+
>
|
|
1458
|
+
<div className="relative w-full h-full overflow-hidden">
|
|
1459
|
+
<BlurredVideoBackdrop
|
|
1460
|
+
videoRef={videoRef}
|
|
1461
|
+
blur="high"
|
|
1462
|
+
overlay="vignette"
|
|
1463
|
+
opacity={0.6}
|
|
1464
|
+
/>
|
|
1465
|
+
<div className="relative z-10 flex items-center justify-center h-full p-24">
|
|
1466
|
+
<div className="w-full max-w-[960px]">
|
|
1467
|
+
<VideoPlayer
|
|
1468
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
1469
|
+
videoRef={videoRef}
|
|
1470
|
+
autoPlay={open}
|
|
1471
|
+
rounded="lg"
|
|
1472
|
+
/>
|
|
1473
|
+
</div>
|
|
1474
|
+
</div>
|
|
1475
|
+
</div>
|
|
1476
|
+
</Dialog>
|
|
1477
|
+
<pre className="text-12 bg-gray-100 p-12 rounded-4 overflow-x-auto">
|
|
1478
|
+
{`const videoRef = useRef<HTMLVideoElement>(null);
|
|
1479
|
+
<Dialog size="full" variant="minimal">
|
|
1480
|
+
<div className="relative w-full h-full overflow-hidden">
|
|
1481
|
+
<BlurredVideoBackdrop
|
|
1482
|
+
videoRef={videoRef}
|
|
1483
|
+
blur="high"
|
|
1484
|
+
overlay="vignette"
|
|
1485
|
+
/>
|
|
1486
|
+
<div className="relative z-10 flex items-center justify-center h-full">
|
|
1487
|
+
<VideoPlayer
|
|
1488
|
+
cloudflare={cloudflare}
|
|
1489
|
+
videoRef={videoRef}
|
|
1490
|
+
autoPlay
|
|
1491
|
+
/>
|
|
1492
|
+
</div>
|
|
1493
|
+
</div>
|
|
1494
|
+
</Dialog>`}
|
|
1495
|
+
</pre>
|
|
1496
|
+
</div>
|
|
1497
|
+
```
|
|
1498
|
+
|
|
1499
|
+
```tsx
|
|
1500
|
+
<div className="relative w-full h-[600px] bg-black overflow-hidden">
|
|
1501
|
+
<BlurredVideoBackdrop
|
|
1502
|
+
videoRef={videoRef}
|
|
1503
|
+
blur="extreme"
|
|
1504
|
+
overlay="top-bottom"
|
|
1505
|
+
opacity={0.5}
|
|
1506
|
+
/>
|
|
1507
|
+
{/* Hidden video that drives the backdrop */}
|
|
1508
|
+
<video
|
|
1509
|
+
ref={videoRef}
|
|
1510
|
+
className="hidden"
|
|
1511
|
+
src={`https://customer-${DGA_CLOUDFLARE.customerCode}.cloudflarestream.com/${DGA_CLOUDFLARE.videoId}/manifest/video.m3u8`}
|
|
1512
|
+
autoPlay
|
|
1513
|
+
muted
|
|
1514
|
+
loop
|
|
1515
|
+
playsInline
|
|
1516
|
+
/>
|
|
1517
|
+
<div className="relative z-10 flex flex-col items-center justify-center h-full text-center px-24">
|
|
1518
|
+
<h1 className="typography-h1-lg text-white mb-16">
|
|
1519
|
+
Welcome to the Future
|
|
1520
|
+
</h1>
|
|
1521
|
+
<p className="typography-body-lg-md text-white/80 max-w-xl mb-32">
|
|
1522
|
+
Experience ambient video backgrounds with our BlurredVideoBackdrop
|
|
1523
|
+
component. Perfect for hero sections and video modals.
|
|
1524
|
+
</p>
|
|
1525
|
+
<Button variant="primary" size="lg">
|
|
1526
|
+
Get Started
|
|
1527
|
+
</Button>
|
|
1528
|
+
</div>
|
|
1529
|
+
</div>
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
|
|
1291
1533
|
### CardGrid
|
|
1292
1534
|
|
|
1293
1535
|
**Import:** `import { CardGrid } from "@nationaldesignstudio/react";`
|
|
@@ -1501,6 +1743,360 @@ className="font-semibold" // Font weight 600
|
|
|
1501
1743
|
```
|
|
1502
1744
|
|
|
1503
1745
|
|
|
1746
|
+
### Dialog
|
|
1747
|
+
|
|
1748
|
+
**Import:** `import { Dialog } from "@nationaldesignstudio/react";`
|
|
1749
|
+
|
|
1750
|
+
**Category:** Other
|
|
1751
|
+
|
|
1752
|
+
**Props:**
|
|
1753
|
+
|
|
1754
|
+
- `children`: React.ReactNode (required)
|
|
1755
|
+
The content to show in the dialog */
|
|
1756
|
+
- `trigger`: React.ReactNode
|
|
1757
|
+
The element that triggers the dialog (optional for controlled mode) */
|
|
1758
|
+
- `title`: React.ReactNode
|
|
1759
|
+
Title for the dialog */
|
|
1760
|
+
- `description`: React.ReactNode
|
|
1761
|
+
Description for the dialog */
|
|
1762
|
+
- `size`: "sm" | "md" | "lg" | "xl" | "full"
|
|
1763
|
+
Size of the dialog */
|
|
1764
|
+
Values: `sm`, `md`, `lg`, `xl`, `full`
|
|
1765
|
+
- `variant`: "default" | "minimal"
|
|
1766
|
+
Visual variant: "default" for card style, "minimal" for borderless (video modals) */
|
|
1767
|
+
Values: `default`, `minimal`
|
|
1768
|
+
- `showClose`: boolean
|
|
1769
|
+
Whether to show a close button */
|
|
1770
|
+
- `open`: boolean
|
|
1771
|
+
Controlled open state */
|
|
1772
|
+
- `defaultOpen`: boolean
|
|
1773
|
+
Default open state */
|
|
1774
|
+
- `onOpenChange`: (open: boolean) => void
|
|
1775
|
+
Callback when open state changes */
|
|
1776
|
+
- `className`: string
|
|
1777
|
+
Additional className for the popup */
|
|
1778
|
+
|
|
1779
|
+
**Examples:**
|
|
1780
|
+
|
|
1781
|
+
```tsx
|
|
1782
|
+
<Dialog
|
|
1783
|
+
{...args}
|
|
1784
|
+
trigger={<Button>Open Dialog</Button>}
|
|
1785
|
+
title="Dialog Title"
|
|
1786
|
+
description="This is a description of the dialog content."
|
|
1787
|
+
>
|
|
1788
|
+
<p className="typography-body-md-md mt-16">
|
|
1789
|
+
This is the dialog body content. You can put any content here including
|
|
1790
|
+
text, forms, or other components.
|
|
1791
|
+
</p>
|
|
1792
|
+
</Dialog>
|
|
1793
|
+
```
|
|
1794
|
+
|
|
1795
|
+
```tsx
|
|
1796
|
+
<Dialog
|
|
1797
|
+
trigger={<Button>Open Dialog</Button>}
|
|
1798
|
+
title="Welcome"
|
|
1799
|
+
description="This is a simple dialog."
|
|
1800
|
+
>
|
|
1801
|
+
<p className="typography-body-md-md mt-16">
|
|
1802
|
+
Dialog content goes here. The dialog automatically handles focus
|
|
1803
|
+
trapping, scroll locking, and keyboard navigation.
|
|
1804
|
+
</p>
|
|
1805
|
+
</Dialog>
|
|
1806
|
+
```
|
|
1807
|
+
|
|
1808
|
+
```tsx
|
|
1809
|
+
<Dialog
|
|
1810
|
+
trigger={<Button variant="outline">Small Dialog</Button>}
|
|
1811
|
+
title="Delete Item?"
|
|
1812
|
+
description="This action cannot be undone."
|
|
1813
|
+
size="sm"
|
|
1814
|
+
>
|
|
1815
|
+
<div className="mt-24 flex justify-end gap-12">
|
|
1816
|
+
<Button variant="secondary" size="sm">
|
|
1817
|
+
Cancel
|
|
1818
|
+
</Button>
|
|
1819
|
+
<Button variant="destructive" size="sm">
|
|
1820
|
+
Delete
|
|
1821
|
+
</Button>
|
|
1822
|
+
</div>
|
|
1823
|
+
</Dialog>
|
|
1824
|
+
```
|
|
1825
|
+
|
|
1826
|
+
```tsx
|
|
1827
|
+
<Dialog
|
|
1828
|
+
trigger={<Button variant="outline">Medium Dialog</Button>}
|
|
1829
|
+
title="Edit Profile"
|
|
1830
|
+
description="Make changes to your profile here."
|
|
1831
|
+
size="md"
|
|
1832
|
+
>
|
|
1833
|
+
<div className="mt-24 flex flex-col gap-16">
|
|
1834
|
+
<Input placeholder="Display name" />
|
|
1835
|
+
<Input placeholder="Email address" type="email" />
|
|
1836
|
+
</div>
|
|
1837
|
+
<div className="mt-24 flex justify-end gap-12">
|
|
1838
|
+
<Button variant="secondary">Cancel</Button>
|
|
1839
|
+
<Button>Save Changes</Button>
|
|
1840
|
+
</div>
|
|
1841
|
+
</Dialog>
|
|
1842
|
+
```
|
|
1843
|
+
|
|
1844
|
+
```tsx
|
|
1845
|
+
<Dialog
|
|
1846
|
+
trigger={<Button variant="outline">Large Dialog</Button>}
|
|
1847
|
+
title="Terms of Service"
|
|
1848
|
+
size="lg"
|
|
1849
|
+
>
|
|
1850
|
+
<div className="mt-16 max-h-[400px] overflow-y-auto rounded-surface-ui-small border border-overlay-border bg-bg-section p-16">
|
|
1851
|
+
<p className="typography-body-sm-md text-text-secondary">
|
|
1852
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do
|
|
1853
|
+
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
|
|
1854
|
+
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
|
1855
|
+
aliquip ex ea commodo consequat.
|
|
1856
|
+
</p>
|
|
1857
|
+
<p className="typography-body-sm-md mt-16 text-text-secondary">
|
|
1858
|
+
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
|
|
1859
|
+
dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
|
|
1860
|
+
proident, sunt in culpa qui officia deserunt mollit anim id est
|
|
1861
|
+
laborum.
|
|
1862
|
+
</p>
|
|
1863
|
+
<p className="typography-body-sm-md mt-16 text-text-secondary">
|
|
1864
|
+
Sed ut perspiciatis unde omnis iste natus error sit voluptatem
|
|
1865
|
+
accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae
|
|
1866
|
+
ab illo inventore veritatis et quasi architecto beatae vitae dicta
|
|
1867
|
+
sunt explicabo.
|
|
1868
|
+
</p>
|
|
1869
|
+
</div>
|
|
1870
|
+
<div className="mt-24 flex justify-end gap-12">
|
|
1871
|
+
<Button variant="secondary">Decline</Button>
|
|
1872
|
+
<Button>Accept</Button>
|
|
1873
|
+
</div>
|
|
1874
|
+
</Dialog>
|
|
1875
|
+
```
|
|
1876
|
+
|
|
1877
|
+
```tsx
|
|
1878
|
+
<Dialog
|
|
1879
|
+
trigger={<Button variant="outline">XL Dialog</Button>}
|
|
1880
|
+
title="Dashboard Settings"
|
|
1881
|
+
description="Configure your dashboard preferences."
|
|
1882
|
+
size="xl"
|
|
1883
|
+
>
|
|
1884
|
+
<div className="mt-24 grid grid-cols-2 gap-24">
|
|
1885
|
+
<div className="flex flex-col gap-16">
|
|
1886
|
+
<h3 className="typography-body-md-md font-semibold">
|
|
1887
|
+
Display Settings
|
|
1888
|
+
</h3>
|
|
1889
|
+
<Input placeholder="Dashboard name" />
|
|
1890
|
+
<Input placeholder="Refresh interval (seconds)" type="number" />
|
|
1891
|
+
</div>
|
|
1892
|
+
<div className="flex flex-col gap-16">
|
|
1893
|
+
<h3 className="typography-body-md-md font-semibold">Data Sources</h3>
|
|
1894
|
+
<Input placeholder="API endpoint" />
|
|
1895
|
+
<Input placeholder="API key" type="password" />
|
|
1896
|
+
</div>
|
|
1897
|
+
</div>
|
|
1898
|
+
<div className="mt-24 flex justify-end gap-12">
|
|
1899
|
+
<Button variant="secondary">Cancel</Button>
|
|
1900
|
+
<Button>Save Settings</Button>
|
|
1901
|
+
</div>
|
|
1902
|
+
</Dialog>
|
|
1903
|
+
```
|
|
1904
|
+
|
|
1905
|
+
```tsx
|
|
1906
|
+
<Dialog
|
|
1907
|
+
trigger={<Button variant="outline">Full Dialog</Button>}
|
|
1908
|
+
title="Image Gallery"
|
|
1909
|
+
size="full"
|
|
1910
|
+
>
|
|
1911
|
+
<div className="mt-24 grid flex-1 grid-cols-3 gap-16 overflow-y-auto">
|
|
1912
|
+
{Array.from({ length: 9 }).map((_, i) => (
|
|
1913
|
+
<div
|
|
1914
|
+
key={`image-${i + 1}`}
|
|
1915
|
+
className="aspect-video rounded-surface-card bg-bg-section-secondary"
|
|
1916
|
+
/>
|
|
1917
|
+
))}
|
|
1918
|
+
</div>
|
|
1919
|
+
</Dialog>
|
|
1920
|
+
```
|
|
1921
|
+
|
|
1922
|
+
```tsx
|
|
1923
|
+
<div className="flex flex-wrap items-center gap-12">
|
|
1924
|
+
<Dialog
|
|
1925
|
+
trigger={<Button variant="outline">Small</Button>}
|
|
1926
|
+
title="Small Dialog"
|
|
1927
|
+
size="sm"
|
|
1928
|
+
>
|
|
1929
|
+
<p className="typography-body-md-md mt-16">
|
|
1930
|
+
This is a small dialog for simple confirmations.
|
|
1931
|
+
</p>
|
|
1932
|
+
</Dialog>
|
|
1933
|
+
<Dialog
|
|
1934
|
+
trigger={<Button variant="outline">Medium</Button>}
|
|
1935
|
+
title="Medium Dialog"
|
|
1936
|
+
size="md"
|
|
1937
|
+
>
|
|
1938
|
+
<p className="typography-body-md-md mt-16">
|
|
1939
|
+
This is the default medium size dialog.
|
|
1940
|
+
</p>
|
|
1941
|
+
</Dialog>
|
|
1942
|
+
<Dialog
|
|
1943
|
+
trigger={<Button variant="outline">Large</Button>}
|
|
1944
|
+
title="Large Dialog"
|
|
1945
|
+
size="lg"
|
|
1946
|
+
>
|
|
1947
|
+
<p className="typography-body-md-md mt-16">
|
|
1948
|
+
This is a large dialog for more content.
|
|
1949
|
+
</p>
|
|
1950
|
+
</Dialog>
|
|
1951
|
+
<Dialog
|
|
1952
|
+
trigger={<Button variant="outline">XL</Button>}
|
|
1953
|
+
title="Extra Large Dialog"
|
|
1954
|
+
size="xl"
|
|
1955
|
+
>
|
|
1956
|
+
<p className="typography-body-md-md mt-16">
|
|
1957
|
+
This is an extra large dialog for complex layouts.
|
|
1958
|
+
</p>
|
|
1959
|
+
</Dialog>
|
|
1960
|
+
<Dialog
|
|
1961
|
+
trigger={<Button variant="outline">Full</Button>}
|
|
1962
|
+
title="Full Dialog"
|
|
1963
|
+
size="full"
|
|
1964
|
+
>
|
|
1965
|
+
<p className="typography-body-md-md mt-16">
|
|
1966
|
+
This is a full-size dialog that takes up most of the viewport.
|
|
1967
|
+
</p>
|
|
1968
|
+
</Dialog>
|
|
1969
|
+
</div>
|
|
1970
|
+
```
|
|
1971
|
+
|
|
1972
|
+
```tsx
|
|
1973
|
+
<Dialog
|
|
1974
|
+
trigger={<Button variant="destructive">Delete Account</Button>}
|
|
1975
|
+
title="Are you absolutely sure?"
|
|
1976
|
+
description="This action cannot be undone. This will permanently delete your account and remove your data from our servers."
|
|
1977
|
+
size="sm"
|
|
1978
|
+
>
|
|
1979
|
+
<div className="mt-24 flex justify-end gap-12">
|
|
1980
|
+
<Button variant="secondary">Cancel</Button>
|
|
1981
|
+
<Button variant="destructive">Yes, delete my account</Button>
|
|
1982
|
+
</div>
|
|
1983
|
+
</Dialog>
|
|
1984
|
+
```
|
|
1985
|
+
|
|
1986
|
+
```tsx
|
|
1987
|
+
<Dialog
|
|
1988
|
+
trigger={<Button>Add New User</Button>}
|
|
1989
|
+
title="Create User"
|
|
1990
|
+
description="Add a new user to your organization."
|
|
1991
|
+
>
|
|
1992
|
+
<form className="mt-24 flex flex-col gap-16">
|
|
1993
|
+
<Input placeholder="Full name" />
|
|
1994
|
+
<Input placeholder="Email address" type="email" />
|
|
1995
|
+
<Input placeholder="Role" />
|
|
1996
|
+
<div className="mt-8 flex justify-end gap-12">
|
|
1997
|
+
<Button variant="secondary" type="button">
|
|
1998
|
+
Cancel
|
|
1999
|
+
</Button>
|
|
2000
|
+
<Button type="submit">Create User</Button>
|
|
2001
|
+
</div>
|
|
2002
|
+
</form>
|
|
2003
|
+
</Dialog>
|
|
2004
|
+
```
|
|
2005
|
+
|
|
2006
|
+
```tsx
|
|
2007
|
+
<div className="flex flex-col items-center gap-16">
|
|
2008
|
+
<Dialog
|
|
2009
|
+
trigger={<Button>Controlled Dialog</Button>}
|
|
2010
|
+
title="Controlled"
|
|
2011
|
+
description="This dialog's state is controlled externally."
|
|
2012
|
+
open={open}
|
|
2013
|
+
onOpenChange={setOpen}
|
|
2014
|
+
>
|
|
2015
|
+
<p className="typography-body-md-md mt-16">
|
|
2016
|
+
The dialog is {open ? "open" : "closed"}.
|
|
2017
|
+
</p>
|
|
2018
|
+
</Dialog>
|
|
2019
|
+
<div className="flex gap-12">
|
|
2020
|
+
<Button variant="outline" onClick={() => setOpen(true)}>
|
|
2021
|
+
Open from outside
|
|
2022
|
+
</Button>
|
|
2023
|
+
<Button variant="outline" onClick={() => setOpen(false)}>
|
|
2024
|
+
Close from outside
|
|
2025
|
+
</Button>
|
|
2026
|
+
</div>
|
|
2027
|
+
</div>
|
|
2028
|
+
```
|
|
2029
|
+
|
|
2030
|
+
```tsx
|
|
2031
|
+
<DialogParts>
|
|
2032
|
+
<DialogTrigger>
|
|
2033
|
+
<Button variant="primary">Custom Dialog</Button>
|
|
2034
|
+
</DialogTrigger>
|
|
2035
|
+
<DialogPortal>
|
|
2036
|
+
<DialogBackdrop />
|
|
2037
|
+
<DialogPopup size="md">
|
|
2038
|
+
<DialogClose>
|
|
2039
|
+
<svg
|
|
2040
|
+
width="16"
|
|
2041
|
+
height="16"
|
|
2042
|
+
viewBox="0 0 16 16"
|
|
2043
|
+
fill="none"
|
|
2044
|
+
aria-hidden="true"
|
|
2045
|
+
>
|
|
2046
|
+
<path
|
|
2047
|
+
d="M2 2L14 14M2 14L14 2"
|
|
2048
|
+
stroke="currentColor"
|
|
2049
|
+
strokeWidth="2"
|
|
2050
|
+
strokeLinecap="round"
|
|
2051
|
+
/>
|
|
2052
|
+
</svg>
|
|
2053
|
+
<span className="sr-only">Close</span>
|
|
2054
|
+
</DialogClose>
|
|
2055
|
+
<DialogTitle>Custom Dialog Title</DialogTitle>
|
|
2056
|
+
<DialogDescription>
|
|
2057
|
+
Built with compound components for maximum flexibility.
|
|
2058
|
+
</DialogDescription>
|
|
2059
|
+
<DialogBody>
|
|
2060
|
+
<p className="typography-body-md-md mt-16">
|
|
2061
|
+
This dialog is built using individual compound components, giving
|
|
2062
|
+
you complete control over the structure and styling.
|
|
2063
|
+
</p>
|
|
2064
|
+
</DialogBody>
|
|
2065
|
+
<DialogFooter>
|
|
2066
|
+
<Button variant="secondary">Cancel</Button>
|
|
2067
|
+
<Button>Confirm</Button>
|
|
2068
|
+
</DialogFooter>
|
|
2069
|
+
</DialogPopup>
|
|
2070
|
+
</DialogPortal>
|
|
2071
|
+
</DialogParts>
|
|
2072
|
+
```
|
|
2073
|
+
|
|
2074
|
+
```tsx
|
|
2075
|
+
<Dialog
|
|
2076
|
+
trigger={<Button>Open Parent Dialog</Button>}
|
|
2077
|
+
title="Parent Dialog"
|
|
2078
|
+
description="This dialog contains another dialog."
|
|
2079
|
+
size="lg"
|
|
2080
|
+
>
|
|
2081
|
+
<div className="mt-24 flex flex-col gap-16">
|
|
2082
|
+
<p className="typography-body-md-md">
|
|
2083
|
+
Click the button below to open a nested dialog.
|
|
2084
|
+
</p>
|
|
2085
|
+
<Dialog
|
|
2086
|
+
trigger={<Button variant="secondary">Open Nested Dialog</Button>}
|
|
2087
|
+
title="Nested Dialog"
|
|
2088
|
+
description="This is a nested dialog."
|
|
2089
|
+
size="sm"
|
|
2090
|
+
>
|
|
2091
|
+
<p className="typography-body-md-md mt-16">
|
|
2092
|
+
Nested dialog content. Focus is properly trapped here.
|
|
2093
|
+
</p>
|
|
2094
|
+
</Dialog>
|
|
2095
|
+
</div>
|
|
2096
|
+
</Dialog>
|
|
2097
|
+
```
|
|
2098
|
+
|
|
2099
|
+
|
|
1504
2100
|
### FaqSection
|
|
1505
2101
|
|
|
1506
2102
|
**Import:** `import { FaqSection } from "@nationaldesignstudio/react";`
|
|
@@ -2852,7 +3448,7 @@ className="font-semibold" // Font weight 600
|
|
|
2852
3448
|
```tsx
|
|
2853
3449
|
<div className="flex flex-col gap-16 max-w-[320px]">
|
|
2854
3450
|
<div>
|
|
2855
|
-
<p className="mb-8
|
|
3451
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">Default</p>
|
|
2856
3452
|
<Select>
|
|
2857
3453
|
<SelectTrigger placeholder="Select option..." />
|
|
2858
3454
|
<SelectPopup>
|
|
@@ -2863,7 +3459,7 @@ className="font-semibold" // Font weight 600
|
|
|
2863
3459
|
</Select>
|
|
2864
3460
|
</div>
|
|
2865
3461
|
<div>
|
|
2866
|
-
<p className="mb-8
|
|
3462
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">With Value</p>
|
|
2867
3463
|
<Select defaultValue="option2">
|
|
2868
3464
|
<SelectTrigger placeholder="Select option..." />
|
|
2869
3465
|
<SelectPopup>
|
|
@@ -2874,7 +3470,7 @@ className="font-semibold" // Font weight 600
|
|
|
2874
3470
|
</Select>
|
|
2875
3471
|
</div>
|
|
2876
3472
|
<div>
|
|
2877
|
-
<p className="mb-8
|
|
3473
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">Invalid</p>
|
|
2878
3474
|
<Select>
|
|
2879
3475
|
<SelectTrigger placeholder="Select option..." error />
|
|
2880
3476
|
<SelectPopup>
|
|
@@ -2885,7 +3481,7 @@ className="font-semibold" // Font weight 600
|
|
|
2885
3481
|
</Select>
|
|
2886
3482
|
</div>
|
|
2887
3483
|
<div>
|
|
2888
|
-
<p className="mb-8
|
|
3484
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">Disabled</p>
|
|
2889
3485
|
<Select disabled>
|
|
2890
3486
|
<SelectTrigger placeholder="Select option..." />
|
|
2891
3487
|
<SelectPopup>
|
|
@@ -2940,7 +3536,7 @@ className="font-semibold" // Font weight 600
|
|
|
2940
3536
|
```tsx
|
|
2941
3537
|
<div className="flex flex-col gap-16 max-w-[320px]">
|
|
2942
3538
|
<div>
|
|
2943
|
-
<p className="mb-8
|
|
3539
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">Small (36px)</p>
|
|
2944
3540
|
<Select>
|
|
2945
3541
|
<SelectTrigger size="sm" placeholder="Select option..." />
|
|
2946
3542
|
<SelectPopup>
|
|
@@ -2951,7 +3547,9 @@ className="font-semibold" // Font weight 600
|
|
|
2951
3547
|
</Select>
|
|
2952
3548
|
</div>
|
|
2953
3549
|
<div>
|
|
2954
|
-
<p className="mb-8
|
|
3550
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">
|
|
3551
|
+
Default (48px)
|
|
3552
|
+
</p>
|
|
2955
3553
|
<Select>
|
|
2956
3554
|
<SelectTrigger size="default" placeholder="Select option..." />
|
|
2957
3555
|
<SelectPopup>
|
|
@@ -2962,7 +3560,7 @@ className="font-semibold" // Font weight 600
|
|
|
2962
3560
|
</Select>
|
|
2963
3561
|
</div>
|
|
2964
3562
|
<div>
|
|
2965
|
-
<p className="mb-8
|
|
3563
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">Large (56px)</p>
|
|
2966
3564
|
<Select>
|
|
2967
3565
|
<SelectTrigger size="lg" placeholder="Select option..." />
|
|
2968
3566
|
<SelectPopup>
|
|
@@ -2975,11 +3573,89 @@ className="font-semibold" // Font weight 600
|
|
|
2975
3573
|
</div>
|
|
2976
3574
|
```
|
|
2977
3575
|
|
|
3576
|
+
```tsx
|
|
3577
|
+
<div className="flex flex-col gap-24 max-w-[320px]">
|
|
3578
|
+
<div>
|
|
3579
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">
|
|
3580
|
+
alignItemWithTrigger=true (default)
|
|
3581
|
+
</p>
|
|
3582
|
+
<Select defaultValue="option2">
|
|
3583
|
+
<SelectTrigger placeholder="Select option..." />
|
|
3584
|
+
<SelectPopup alignItemWithTrigger={true}>
|
|
3585
|
+
<SelectOption value="option1">Option 1</SelectOption>
|
|
3586
|
+
<SelectOption value="option2">Option 2</SelectOption>
|
|
3587
|
+
<SelectOption value="option3">Option 3</SelectOption>
|
|
3588
|
+
</SelectPopup>
|
|
3589
|
+
</Select>
|
|
3590
|
+
</div>
|
|
3591
|
+
<div>
|
|
3592
|
+
<p className="mb-8 typography-body-sm-sm text-text-muted">
|
|
3593
|
+
alignItemWithTrigger=false
|
|
3594
|
+
</p>
|
|
3595
|
+
<Select defaultValue="option2">
|
|
3596
|
+
<SelectTrigger placeholder="Select option..." />
|
|
3597
|
+
<SelectPopup alignItemWithTrigger={false}>
|
|
3598
|
+
<SelectOption value="option1">Option 1</SelectOption>
|
|
3599
|
+
<SelectOption value="option2">Option 2</SelectOption>
|
|
3600
|
+
<SelectOption value="option3">Option 3</SelectOption>
|
|
3601
|
+
</SelectPopup>
|
|
3602
|
+
</Select>
|
|
3603
|
+
</div>
|
|
3604
|
+
</div>
|
|
3605
|
+
```
|
|
3606
|
+
|
|
3607
|
+
```tsx
|
|
3608
|
+
<div className="w-[320px]">
|
|
3609
|
+
<Select>
|
|
3610
|
+
<SelectTrigger placeholder="Select a fruit..." />
|
|
3611
|
+
<SelectPopup>
|
|
3612
|
+
<SelectGroup>
|
|
3613
|
+
<SelectGroupLabel>Fruits</SelectGroupLabel>
|
|
3614
|
+
<SelectOption value="apple">Apple</SelectOption>
|
|
3615
|
+
<SelectOption value="banana">Banana</SelectOption>
|
|
3616
|
+
<SelectOption value="orange">Orange</SelectOption>
|
|
3617
|
+
</SelectGroup>
|
|
3618
|
+
<SelectSeparator />
|
|
3619
|
+
<SelectGroup>
|
|
3620
|
+
<SelectGroupLabel>Vegetables</SelectGroupLabel>
|
|
3621
|
+
<SelectOption value="carrot">Carrot</SelectOption>
|
|
3622
|
+
<SelectOption value="broccoli">Broccoli</SelectOption>
|
|
3623
|
+
<SelectOption value="spinach">Spinach</SelectOption>
|
|
3624
|
+
</SelectGroup>
|
|
3625
|
+
<SelectSeparator />
|
|
3626
|
+
<SelectGroup>
|
|
3627
|
+
<SelectGroupLabel>Proteins</SelectGroupLabel>
|
|
3628
|
+
<SelectOption value="chicken">Chicken</SelectOption>
|
|
3629
|
+
<SelectOption value="beef">Beef</SelectOption>
|
|
3630
|
+
<SelectOption value="tofu">Tofu</SelectOption>
|
|
3631
|
+
</SelectGroup>
|
|
3632
|
+
</SelectPopup>
|
|
3633
|
+
</Select>
|
|
3634
|
+
</div>
|
|
3635
|
+
```
|
|
3636
|
+
|
|
3637
|
+
```tsx
|
|
3638
|
+
<div className="w-[320px]">
|
|
3639
|
+
<Select>
|
|
3640
|
+
<SelectTrigger placeholder="Select a state..." />
|
|
3641
|
+
<SelectPopup className="max-h-[200px]">
|
|
3642
|
+
<SelectScrollUpArrow />
|
|
3643
|
+
{allStates.map((state) => (
|
|
3644
|
+
<SelectOption key={state.value} value={state.value}>
|
|
3645
|
+
{state.label}
|
|
3646
|
+
</SelectOption>
|
|
3647
|
+
))}
|
|
3648
|
+
<SelectScrollDownArrow />
|
|
3649
|
+
</SelectPopup>
|
|
3650
|
+
</Select>
|
|
3651
|
+
</div>
|
|
3652
|
+
```
|
|
3653
|
+
|
|
2978
3654
|
```tsx
|
|
2979
3655
|
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
2980
3656
|
<label
|
|
2981
3657
|
htmlFor="state-select"
|
|
2982
|
-
className="
|
|
3658
|
+
className="typography-body-md-md font-medium text-text-primary"
|
|
2983
3659
|
>
|
|
2984
3660
|
State / Territory
|
|
2985
3661
|
</label>
|
|
@@ -2997,10 +3673,10 @@ className="font-semibold" // Font weight 600
|
|
|
2997
3673
|
```
|
|
2998
3674
|
|
|
2999
3675
|
```tsx
|
|
3000
|
-
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
3676
|
+
<div className="flex flex-col gap-8 max-w-[320px]" data-invalid>
|
|
3001
3677
|
<label
|
|
3002
3678
|
htmlFor="state-error"
|
|
3003
|
-
className="
|
|
3679
|
+
className="typography-body-md-md font-medium text-text-primary"
|
|
3004
3680
|
>
|
|
3005
3681
|
State / Territory
|
|
3006
3682
|
</label>
|
|
@@ -3014,7 +3690,9 @@ className="font-semibold" // Font weight 600
|
|
|
3014
3690
|
))}
|
|
3015
3691
|
</SelectPopup>
|
|
3016
3692
|
</Select>
|
|
3017
|
-
<p className="
|
|
3693
|
+
<p className="typography-body-sm-sm text-ui-error-color">
|
|
3694
|
+
Please select a state
|
|
3695
|
+
</p>
|
|
3018
3696
|
</div>
|
|
3019
3697
|
```
|
|
3020
3698
|
|
|
@@ -3022,7 +3700,7 @@ className="font-semibold" // Font weight 600
|
|
|
3022
3700
|
<div className="flex flex-col gap-8 max-w-[320px]">
|
|
3023
3701
|
<label
|
|
3024
3702
|
htmlFor="required-select"
|
|
3025
|
-
className="
|
|
3703
|
+
className="typography-body-md-md font-medium text-text-primary"
|
|
3026
3704
|
>
|
|
3027
3705
|
State / Territory <span className="text-ui-error-color">*</span>
|
|
3028
3706
|
</label>
|
|
@@ -3058,33 +3736,22 @@ className="font-semibold" // Font weight 600
|
|
|
3058
3736
|
</div>
|
|
3059
3737
|
```
|
|
3060
3738
|
|
|
3061
|
-
```tsx
|
|
3062
|
-
<div className="w-[320px]">
|
|
3063
|
-
<Select>
|
|
3064
|
-
<SelectTrigger placeholder="Select a state..." />
|
|
3065
|
-
<SelectPopup>
|
|
3066
|
-
{states.map((state) => (
|
|
3067
|
-
<SelectOption key={state.value} value={state.value}>
|
|
3068
|
-
{state.label}
|
|
3069
|
-
</SelectOption>
|
|
3070
|
-
))}
|
|
3071
|
-
</SelectPopup>
|
|
3072
|
-
</Select>
|
|
3073
|
-
</div>
|
|
3074
|
-
```
|
|
3075
|
-
|
|
3076
3739
|
```tsx
|
|
3077
3740
|
<div className="flex flex-col gap-16 max-w-[500px]">
|
|
3078
|
-
<p className="
|
|
3741
|
+
<p className="typography-body-md-md text-text-muted">
|
|
3079
3742
|
Select and Input share the same base styling for consistent forms
|
|
3080
3743
|
</p>
|
|
3081
3744
|
<div className="flex gap-12">
|
|
3082
3745
|
<div className="flex-1">
|
|
3083
|
-
<p className="block mb-8
|
|
3746
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3747
|
+
Input
|
|
3748
|
+
</p>
|
|
3084
3749
|
<Input placeholder="Enter text..." />
|
|
3085
3750
|
</div>
|
|
3086
3751
|
<div className="flex-1">
|
|
3087
|
-
<p className="block mb-8
|
|
3752
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3753
|
+
Select
|
|
3754
|
+
</p>
|
|
3088
3755
|
<Select>
|
|
3089
3756
|
<SelectTrigger placeholder="Select option..." />
|
|
3090
3757
|
<SelectPopup>
|
|
@@ -3096,11 +3763,15 @@ className="font-semibold" // Font weight 600
|
|
|
3096
3763
|
</div>
|
|
3097
3764
|
<div className="flex gap-12">
|
|
3098
3765
|
<div className="flex-1">
|
|
3099
|
-
<p className="block mb-8
|
|
3766
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3767
|
+
Input (Invalid)
|
|
3768
|
+
</p>
|
|
3100
3769
|
<Input error placeholder="Enter text..." />
|
|
3101
3770
|
</div>
|
|
3102
3771
|
<div className="flex-1">
|
|
3103
|
-
<p className="block mb-8
|
|
3772
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3773
|
+
Select (Invalid)
|
|
3774
|
+
</p>
|
|
3104
3775
|
<Select>
|
|
3105
3776
|
<SelectTrigger error placeholder="Select option..." />
|
|
3106
3777
|
<SelectPopup>
|
|
@@ -3112,11 +3783,13 @@ className="font-semibold" // Font weight 600
|
|
|
3112
3783
|
</div>
|
|
3113
3784
|
<div className="flex gap-12">
|
|
3114
3785
|
<div className="flex-1">
|
|
3115
|
-
<p className="block mb-8
|
|
3786
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3787
|
+
Input (Disabled)
|
|
3788
|
+
</p>
|
|
3116
3789
|
<Input disabled placeholder="Enter text..." />
|
|
3117
3790
|
</div>
|
|
3118
3791
|
<div className="flex-1">
|
|
3119
|
-
<p className="block mb-8
|
|
3792
|
+
<p className="block mb-8 typography-body-sm-sm text-text-muted">
|
|
3120
3793
|
Select (Disabled)
|
|
3121
3794
|
</p>
|
|
3122
3795
|
<Select disabled>
|
|
@@ -3657,6 +4330,579 @@ className="font-semibold" // Font weight 600
|
|
|
3657
4330
|
```
|
|
3658
4331
|
|
|
3659
4332
|
|
|
4333
|
+
### VideoDialog
|
|
4334
|
+
|
|
4335
|
+
**Import:** `import { VideoDialog } from "@nationaldesignstudio/react";`
|
|
4336
|
+
|
|
4337
|
+
**Category:** Other
|
|
4338
|
+
|
|
4339
|
+
**Props:**
|
|
4340
|
+
|
|
4341
|
+
- `trigger`: React.ReactNode (required)
|
|
4342
|
+
Trigger element that opens the dialog */
|
|
4343
|
+
- `blur`: BlurredVideoBackdropProps["blur"]
|
|
4344
|
+
Blur intensity for backdrop (default: high) */
|
|
4345
|
+
- `overlay`: BlurredVideoBackdropProps["overlay"]
|
|
4346
|
+
Gradient overlay for backdrop (default: vignette) */
|
|
4347
|
+
- `backdropOpacity`: number
|
|
4348
|
+
Backdrop opacity (default: 0.6) */
|
|
4349
|
+
- `showClose`: boolean
|
|
4350
|
+
Whether to show close button (default: true) */
|
|
4351
|
+
- `closePosition`: "top-right" | "top-left"
|
|
4352
|
+
Close button position (default: top-right) */
|
|
4353
|
+
Values: `top-right`, `top-left`
|
|
4354
|
+
- `rounded`: VideoPlayerProps["rounded"]
|
|
4355
|
+
Video player rounded corners (default: lg) */
|
|
4356
|
+
- `open`: boolean
|
|
4357
|
+
Controlled open state */
|
|
4358
|
+
- `defaultOpen`: boolean
|
|
4359
|
+
Default open state */
|
|
4360
|
+
- `onOpenChange`: (open: boolean) => void
|
|
4361
|
+
Callback when open state changes */
|
|
4362
|
+
- `className`: string
|
|
4363
|
+
Additional className for the dialog container */
|
|
4364
|
+
|
|
4365
|
+
**Examples:**
|
|
4366
|
+
|
|
4367
|
+
```tsx
|
|
4368
|
+
<VideoDialog {...args} trigger={<Button size="lg">Watch Video</Button>} />
|
|
4369
|
+
```
|
|
4370
|
+
|
|
4371
|
+
```tsx
|
|
4372
|
+
<div className="flex flex-col gap-16 items-center">
|
|
4373
|
+
<p className="text-14 text-gray-600 max-w-md text-center">
|
|
4374
|
+
Click the button to open a fullscreen video modal with the blurred
|
|
4375
|
+
backdrop effect. The blur video stays synchronized with the main video.
|
|
4376
|
+
</p>
|
|
4377
|
+
<VideoDialog
|
|
4378
|
+
trigger={<Button size="lg">Watch Video</Button>}
|
|
4379
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4380
|
+
blur="high"
|
|
4381
|
+
overlay="vignette"
|
|
4382
|
+
/>
|
|
4383
|
+
</div>
|
|
4384
|
+
```
|
|
4385
|
+
|
|
4386
|
+
```tsx
|
|
4387
|
+
<div className="flex flex-wrap gap-12 justify-center">
|
|
4388
|
+
{(["low", "medium", "high", "extreme"] as const).map((blur) => (
|
|
4389
|
+
<VideoDialog
|
|
4390
|
+
key={blur}
|
|
4391
|
+
trigger={
|
|
4392
|
+
<Button variant="secondary" size="md">
|
|
4393
|
+
blur="{blur}"
|
|
4394
|
+
</Button>
|
|
4395
|
+
}
|
|
4396
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4397
|
+
blur={blur}
|
|
4398
|
+
overlay="vignette"
|
|
4399
|
+
/>
|
|
4400
|
+
))}
|
|
4401
|
+
</div>
|
|
4402
|
+
```
|
|
4403
|
+
|
|
4404
|
+
```tsx
|
|
4405
|
+
<div className="flex flex-wrap gap-12 justify-center">
|
|
4406
|
+
{(["none", "vignette", "top-bottom"] as const).map((overlay) => (
|
|
4407
|
+
<VideoDialog
|
|
4408
|
+
key={overlay}
|
|
4409
|
+
trigger={
|
|
4410
|
+
<Button variant="secondary" size="md">
|
|
4411
|
+
overlay="{overlay}"
|
|
4412
|
+
</Button>
|
|
4413
|
+
}
|
|
4414
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4415
|
+
blur="high"
|
|
4416
|
+
overlay={overlay}
|
|
4417
|
+
/>
|
|
4418
|
+
))}
|
|
4419
|
+
</div>
|
|
4420
|
+
```
|
|
4421
|
+
|
|
4422
|
+
```tsx
|
|
4423
|
+
<div className="flex flex-col gap-16 items-center">
|
|
4424
|
+
<p className="text-14 text-gray-600 max-w-md text-center">
|
|
4425
|
+
Controlled state example. The dialog can be opened/closed
|
|
4426
|
+
programmatically.
|
|
4427
|
+
</p>
|
|
4428
|
+
<div className="flex gap-12">
|
|
4429
|
+
<Button onClick={() => setOpen(true)}>Open Dialog</Button>
|
|
4430
|
+
<Button variant="secondary" onClick={() => setOpen(false)}>
|
|
4431
|
+
Close Dialog (No-op when closed)
|
|
4432
|
+
</Button>
|
|
4433
|
+
</div>
|
|
4434
|
+
<VideoDialog
|
|
4435
|
+
trigger={<Button variant="secondary">Using Trigger</Button>}
|
|
4436
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4437
|
+
open={open}
|
|
4438
|
+
onOpenChange={setOpen}
|
|
4439
|
+
/>
|
|
4440
|
+
</div>
|
|
4441
|
+
```
|
|
4442
|
+
|
|
4443
|
+
```tsx
|
|
4444
|
+
<div className="flex gap-12 justify-center">
|
|
4445
|
+
<VideoDialog
|
|
4446
|
+
trigger={
|
|
4447
|
+
<Button variant="secondary" size="md">
|
|
4448
|
+
Close Top-Right
|
|
4449
|
+
</Button>
|
|
4450
|
+
}
|
|
4451
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4452
|
+
closePosition="top-right"
|
|
4453
|
+
/>
|
|
4454
|
+
<VideoDialog
|
|
4455
|
+
trigger={
|
|
4456
|
+
<Button variant="secondary" size="md">
|
|
4457
|
+
Close Top-Left
|
|
4458
|
+
</Button>
|
|
4459
|
+
}
|
|
4460
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4461
|
+
closePosition="top-left"
|
|
4462
|
+
/>
|
|
4463
|
+
</div>
|
|
4464
|
+
```
|
|
4465
|
+
|
|
4466
|
+
```tsx
|
|
4467
|
+
<VideoDialog
|
|
4468
|
+
trigger={<Button size="lg">Watch with Captions</Button>}
|
|
4469
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4470
|
+
captionsSrc="https://customer-29f0fiy60aiz1fqm.cloudflarestream.com/e978a151c0700e12277e66802746e204/captions/en"
|
|
4471
|
+
/>
|
|
4472
|
+
```
|
|
4473
|
+
|
|
4474
|
+
```tsx
|
|
4475
|
+
<div className="flex flex-col gap-16 items-center">
|
|
4476
|
+
<p className="text-14 text-gray-600 max-w-md text-center">
|
|
4477
|
+
Extreme blur creates a very diffused, ambient background that's
|
|
4478
|
+
less distracting while still maintaining visual connection to the video.
|
|
4479
|
+
</p>
|
|
4480
|
+
<VideoDialog
|
|
4481
|
+
trigger={<Button size="lg">Extreme Blur</Button>}
|
|
4482
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4483
|
+
blur="extreme"
|
|
4484
|
+
overlay="vignette"
|
|
4485
|
+
backdropOpacity={0.5}
|
|
4486
|
+
/>
|
|
4487
|
+
</div>
|
|
4488
|
+
```
|
|
4489
|
+
|
|
4490
|
+
```tsx
|
|
4491
|
+
<div className="flex flex-col gap-16 items-center">
|
|
4492
|
+
<p className="text-14 text-gray-600 max-w-md text-center">
|
|
4493
|
+
No visible close button. Use Escape key or click outside to close.
|
|
4494
|
+
</p>
|
|
4495
|
+
<VideoDialog
|
|
4496
|
+
trigger={<Button size="lg">Watch Video</Button>}
|
|
4497
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4498
|
+
showClose={false}
|
|
4499
|
+
/>
|
|
4500
|
+
</div>
|
|
4501
|
+
```
|
|
4502
|
+
|
|
4503
|
+
|
|
4504
|
+
### VideoPlayer
|
|
4505
|
+
|
|
4506
|
+
**Import:** `import { VideoPlayer } from "@nationaldesignstudio/react";`
|
|
4507
|
+
|
|
4508
|
+
**Category:** Other
|
|
4509
|
+
|
|
4510
|
+
**Props:**
|
|
4511
|
+
|
|
4512
|
+
- `src`: string
|
|
4513
|
+
Video source URL (HLS .m3u8 or regular video file) */
|
|
4514
|
+
- `cloudflare`: CloudflareConfig
|
|
4515
|
+
Cloudflare Stream configuration (takes precedence over src) */
|
|
4516
|
+
- `poster`: string
|
|
4517
|
+
Poster image URL */
|
|
4518
|
+
- `captionsSrc`: string
|
|
4519
|
+
VTT captions URL */
|
|
4520
|
+
- `autoPlay`: boolean
|
|
4521
|
+
Whether to autoplay (default: false) */
|
|
4522
|
+
- `loop`: boolean
|
|
4523
|
+
Whether to loop the video (default: false) */
|
|
4524
|
+
- `muted`: boolean
|
|
4525
|
+
Whether to mute initially (default: false) */
|
|
4526
|
+
- `controls`: boolean
|
|
4527
|
+
Whether to show controls (default: true) */
|
|
4528
|
+
- `autoHideControls`: boolean
|
|
4529
|
+
Whether to auto-hide controls when not interacting (default: true) */
|
|
4530
|
+
- `autoHideDelay`: number
|
|
4531
|
+
Control auto-hide delay in ms (default: 3000) */
|
|
4532
|
+
- `captionsEnabled`: boolean
|
|
4533
|
+
Whether captions are enabled by default (default: false) */
|
|
4534
|
+
- `onPlay`: () => void
|
|
4535
|
+
Callback when video starts playing */
|
|
4536
|
+
- `onPause`: () => void
|
|
4537
|
+
Callback when video pauses */
|
|
4538
|
+
- `onEnded`: () => void
|
|
4539
|
+
Callback when video ends */
|
|
4540
|
+
- `onTimeUpdate`: (time: number) => void
|
|
4541
|
+
Callback on time update */
|
|
4542
|
+
- `onError`: (error: Error) => void
|
|
4543
|
+
Callback on error */
|
|
4544
|
+
- `videoRef`: React.RefObject<HTMLVideoElement | null>
|
|
4545
|
+
Ref to the video element */
|
|
4546
|
+
|
|
4547
|
+
**Examples:**
|
|
4548
|
+
|
|
4549
|
+
```tsx
|
|
4550
|
+
<div className="w-640">
|
|
4551
|
+
<VideoPlayer {...args} />
|
|
4552
|
+
</div>
|
|
4553
|
+
```
|
|
4554
|
+
|
|
4555
|
+
```tsx
|
|
4556
|
+
<div className="w-640">
|
|
4557
|
+
<VideoPlayer cloudflare={DGA_CLOUDFLARE} />
|
|
4558
|
+
</div>
|
|
4559
|
+
```
|
|
4560
|
+
|
|
4561
|
+
```tsx
|
|
4562
|
+
<div className="flex flex-col gap-16">
|
|
4563
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4564
|
+
VideoPlayer supports Cloudflare Stream out of the box. Provide your
|
|
4565
|
+
video ID and customer code.
|
|
4566
|
+
</p>
|
|
4567
|
+
<div className="w-640">
|
|
4568
|
+
<VideoPlayer cloudflare={DGA_CLOUDFLARE} rounded="md" />
|
|
4569
|
+
</div>
|
|
4570
|
+
<pre className="text-12 bg-gray-100 p-12 rounded-4 overflow-x-auto">
|
|
4571
|
+
{`<VideoPlayer
|
|
4572
|
+
cloudflare={{
|
|
4573
|
+
videoId: "${DGA_CLOUDFLARE.videoId}",
|
|
4574
|
+
customerCode: "${DGA_CLOUDFLARE.customerCode}"
|
|
4575
|
+
}}
|
|
4576
|
+
rounded="md"
|
|
4577
|
+
/>`}
|
|
4578
|
+
</pre>
|
|
4579
|
+
</div>
|
|
4580
|
+
```
|
|
4581
|
+
|
|
4582
|
+
```tsx
|
|
4583
|
+
<div className="flex flex-col items-center gap-16">
|
|
4584
|
+
<div className="w-640">
|
|
4585
|
+
<VideoPlayer
|
|
4586
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4587
|
+
onPlay={() => addEvent("Video playing")}
|
|
4588
|
+
onPause={() => addEvent("Video paused")}
|
|
4589
|
+
onEnded={() => addEvent("Video ended")}
|
|
4590
|
+
/>
|
|
4591
|
+
</div>
|
|
4592
|
+
<div className="w-256 rounded-4 bg-gray-100 p-16">
|
|
4593
|
+
<p className="mb-8 font-medium text-gray-900">Events:</p>
|
|
4594
|
+
{events.length === 0 ? (
|
|
4595
|
+
<p className="text-gray-500">No events yet</p>
|
|
4596
|
+
) : (
|
|
4597
|
+
<ul className="space-y-4 text-14 text-gray-700">
|
|
4598
|
+
{events.map((event) => (
|
|
4599
|
+
<li key={event}>{event}</li>
|
|
4600
|
+
))}
|
|
4601
|
+
</ul>
|
|
4602
|
+
)}
|
|
4603
|
+
</div>
|
|
4604
|
+
</div>
|
|
4605
|
+
```
|
|
4606
|
+
|
|
4607
|
+
```tsx
|
|
4608
|
+
<div className="flex flex-col gap-16">
|
|
4609
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4610
|
+
Click the button below to open a video player in a dialog. The video
|
|
4611
|
+
will autoplay when the dialog opens.
|
|
4612
|
+
</p>
|
|
4613
|
+
<Dialog
|
|
4614
|
+
trigger={<Button>Watch Video</Button>}
|
|
4615
|
+
size="full"
|
|
4616
|
+
variant="minimal"
|
|
4617
|
+
showClose={false}
|
|
4618
|
+
>
|
|
4619
|
+
<VideoPlayer cloudflare={DGA_CLOUDFLARE} autoPlay rounded="none" />
|
|
4620
|
+
</Dialog>
|
|
4621
|
+
<pre className="text-12 bg-gray-100 p-12 rounded-4 overflow-x-auto">
|
|
4622
|
+
{`import { Dialog } from "@nds/react";
|
|
4623
|
+
import { VideoPlayer } from "@nds/react";
|
|
4624
|
+
<Dialog
|
|
4625
|
+
trigger={<Button>Watch Video</Button>}
|
|
4626
|
+
size="full"
|
|
4627
|
+
variant="minimal"
|
|
4628
|
+
showClose={false}
|
|
4629
|
+
>
|
|
4630
|
+
<VideoPlayer
|
|
4631
|
+
cloudflare={{ videoId: "...", customerCode: "..." }}
|
|
4632
|
+
autoPlay
|
|
4633
|
+
rounded="none"
|
|
4634
|
+
/>
|
|
4635
|
+
</Dialog>`}
|
|
4636
|
+
</pre>
|
|
4637
|
+
</div>
|
|
4638
|
+
```
|
|
4639
|
+
|
|
4640
|
+
```tsx
|
|
4641
|
+
<div className="flex flex-col gap-16">
|
|
4642
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4643
|
+
VideoPlayer supports VTT captions. Click the CC button in the control
|
|
4644
|
+
bar to toggle captions. Captions are displayed as an overlay on the
|
|
4645
|
+
video.
|
|
4646
|
+
</p>
|
|
4647
|
+
<div className="w-640">
|
|
4648
|
+
<VideoPlayer
|
|
4649
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4650
|
+
captionsSrc={DGA_CAPTIONS_URL}
|
|
4651
|
+
captionsEnabled={true}
|
|
4652
|
+
rounded="md"
|
|
4653
|
+
/>
|
|
4654
|
+
</div>
|
|
4655
|
+
<pre className="text-12 bg-gray-100 p-12 rounded-4 overflow-x-auto">
|
|
4656
|
+
{`<VideoPlayer
|
|
4657
|
+
cloudflare={{
|
|
4658
|
+
videoId: "${DGA_CLOUDFLARE.videoId}",
|
|
4659
|
+
customerCode: "${DGA_CLOUDFLARE.customerCode}"
|
|
4660
|
+
}}
|
|
4661
|
+
captionsSrc="https://customer-{customerCode}.cloudflarestream.com/{videoId}/captions/en"
|
|
4662
|
+
captionsEnabled={true}
|
|
4663
|
+
rounded="md"
|
|
4664
|
+
/>`}
|
|
4665
|
+
</pre>
|
|
4666
|
+
</div>
|
|
4667
|
+
```
|
|
4668
|
+
|
|
4669
|
+
```tsx
|
|
4670
|
+
<div className="flex flex-col gap-16">
|
|
4671
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4672
|
+
Captions are available but disabled by default. Users can enable them by
|
|
4673
|
+
clicking the CC button in the control bar.
|
|
4674
|
+
</p>
|
|
4675
|
+
<div className="w-640">
|
|
4676
|
+
<VideoPlayer
|
|
4677
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4678
|
+
captionsSrc={DGA_CAPTIONS_URL}
|
|
4679
|
+
captionsEnabled={false}
|
|
4680
|
+
rounded="md"
|
|
4681
|
+
/>
|
|
4682
|
+
</div>
|
|
4683
|
+
</div>
|
|
4684
|
+
```
|
|
4685
|
+
|
|
4686
|
+
```tsx
|
|
4687
|
+
<div className="flex flex-col gap-16">
|
|
4688
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4689
|
+
VideoPlayer uses media-chrome for accessible, customizable controls. All
|
|
4690
|
+
controls are keyboard accessible.
|
|
4691
|
+
</p>
|
|
4692
|
+
<div className="w-640">
|
|
4693
|
+
<VideoPlayer cloudflare={DGA_CLOUDFLARE} autoHideControls={false} />
|
|
4694
|
+
</div>
|
|
4695
|
+
<div className="text-14 text-gray-600 max-w-md space-y-8">
|
|
4696
|
+
<p>
|
|
4697
|
+
<strong>Controls:</strong>
|
|
4698
|
+
</p>
|
|
4699
|
+
<ul className="list-disc pl-20 space-y-4">
|
|
4700
|
+
<li>Play/Pause button</li>
|
|
4701
|
+
<li>Time range scrubber with preview</li>
|
|
4702
|
+
<li>Mute button</li>
|
|
4703
|
+
<li>Volume slider</li>
|
|
4704
|
+
<li>Current time / duration display</li>
|
|
4705
|
+
<li>Captions toggle (when captionsSrc provided)</li>
|
|
4706
|
+
<li>Fullscreen toggle</li>
|
|
4707
|
+
</ul>
|
|
4708
|
+
</div>
|
|
4709
|
+
</div>
|
|
4710
|
+
```
|
|
4711
|
+
|
|
4712
|
+
|
|
4713
|
+
### VideoWithBackdrop
|
|
4714
|
+
|
|
4715
|
+
**Import:** `import { VideoWithBackdrop } from "@nationaldesignstudio/react";`
|
|
4716
|
+
|
|
4717
|
+
**Category:** Other
|
|
4718
|
+
|
|
4719
|
+
**Props:**
|
|
4720
|
+
|
|
4721
|
+
- `blur`: BlurredVideoBackdropProps["blur"]
|
|
4722
|
+
Blur intensity (default: high) */
|
|
4723
|
+
- `overlay`: BlurredVideoBackdropProps["overlay"]
|
|
4724
|
+
Gradient overlay (default: vignette) */
|
|
4725
|
+
- `backdropOpacity`: number
|
|
4726
|
+
Backdrop opacity (default: 0.6) */
|
|
4727
|
+
- `maxWidth`: string
|
|
4728
|
+
Max width of video player (default: 960px) */
|
|
4729
|
+
- `padding`: "none" | "sm" | "md" | "lg"
|
|
4730
|
+
Content padding (default: md) */
|
|
4731
|
+
Values: `none`, `sm`, `md`, `lg`
|
|
4732
|
+
- `rounded`: VideoPlayerProps["rounded"]
|
|
4733
|
+
Video player rounded corners */
|
|
4734
|
+
- `className`: string
|
|
4735
|
+
Additional className for root container */
|
|
4736
|
+
- `targetFps`: number
|
|
4737
|
+
Target FPS for backdrop canvas (default: 30) */
|
|
4738
|
+
- `scale`: number
|
|
4739
|
+
Canvas scale factor for backdrop (default: 0.5) */
|
|
4740
|
+
|
|
4741
|
+
**Examples:**
|
|
4742
|
+
|
|
4743
|
+
```tsx
|
|
4744
|
+
<div className="h-[600px]">
|
|
4745
|
+
<VideoWithBackdrop {...args} />
|
|
4746
|
+
</div>
|
|
4747
|
+
```
|
|
4748
|
+
|
|
4749
|
+
```tsx
|
|
4750
|
+
<div className="h-[500px]">
|
|
4751
|
+
<VideoWithBackdrop
|
|
4752
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4753
|
+
blur="high"
|
|
4754
|
+
overlay="vignette"
|
|
4755
|
+
/>
|
|
4756
|
+
</div>
|
|
4757
|
+
```
|
|
4758
|
+
|
|
4759
|
+
```tsx
|
|
4760
|
+
<div className="flex flex-col gap-16 p-24">
|
|
4761
|
+
<p className="text-14 text-gray-600 max-w-md">
|
|
4762
|
+
For fullscreen video modals, use the dedicated VideoDialog component.
|
|
4763
|
+
The blur video becomes the modal backdrop itself.
|
|
4764
|
+
</p>
|
|
4765
|
+
<VideoDialog
|
|
4766
|
+
trigger={<Button size="lg">Watch Video</Button>}
|
|
4767
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4768
|
+
blur="high"
|
|
4769
|
+
overlay="vignette"
|
|
4770
|
+
/>
|
|
4771
|
+
<pre className="text-12 bg-gray-100 p-12 rounded-4 overflow-x-auto">
|
|
4772
|
+
{`<VideoDialog
|
|
4773
|
+
trigger={<Button>Watch Video</Button>}
|
|
4774
|
+
cloudflare={{ videoId: "...", customerCode: "..." }}
|
|
4775
|
+
blur="high"
|
|
4776
|
+
overlay="vignette"
|
|
4777
|
+
/>`}
|
|
4778
|
+
</pre>
|
|
4779
|
+
</div>
|
|
4780
|
+
```
|
|
4781
|
+
|
|
4782
|
+
```tsx
|
|
4783
|
+
<div className="h-[600px]">
|
|
4784
|
+
<VideoWithBackdropParts.Root cloudflare={DGA_CLOUDFLARE} fullHeight>
|
|
4785
|
+
<VideoWithBackdropParts.Backdrop
|
|
4786
|
+
blur="extreme"
|
|
4787
|
+
overlay="top-bottom"
|
|
4788
|
+
opacity={0.5}
|
|
4789
|
+
/>
|
|
4790
|
+
<VideoWithBackdropParts.Content fullHeight padding="lg">
|
|
4791
|
+
<VideoWithBackdropParts.Video maxWidth="800px" rounded="md" />
|
|
4792
|
+
</VideoWithBackdropParts.Content>
|
|
4793
|
+
</VideoWithBackdropParts.Root>
|
|
4794
|
+
</div>
|
|
4795
|
+
```
|
|
4796
|
+
|
|
4797
|
+
```tsx
|
|
4798
|
+
<div className="h-[700px]">
|
|
4799
|
+
<VideoWithBackdropParts.Root cloudflare={DGA_CLOUDFLARE} fullHeight>
|
|
4800
|
+
<VideoWithBackdropParts.Backdrop blur="high" overlay="vignette" />
|
|
4801
|
+
<VideoWithBackdropParts.Content fullHeight padding="lg">
|
|
4802
|
+
<div className="flex flex-col items-center gap-24">
|
|
4803
|
+
<div className="text-center">
|
|
4804
|
+
<h2 className="typography-h2-lg text-white mb-8">
|
|
4805
|
+
Featured Video
|
|
4806
|
+
</h2>
|
|
4807
|
+
<p className="typography-body-md-md text-white/70">
|
|
4808
|
+
Watch our latest announcement
|
|
4809
|
+
</p>
|
|
4810
|
+
</div>
|
|
4811
|
+
<VideoWithBackdropParts.Video maxWidth="960px" rounded="lg" />
|
|
4812
|
+
<div className="flex gap-12">
|
|
4813
|
+
<Button variant="secondary" size="sm">
|
|
4814
|
+
Share
|
|
4815
|
+
</Button>
|
|
4816
|
+
<Button variant="secondary" size="sm">
|
|
4817
|
+
Save for Later
|
|
4818
|
+
</Button>
|
|
4819
|
+
</div>
|
|
4820
|
+
</div>
|
|
4821
|
+
</VideoWithBackdropParts.Content>
|
|
4822
|
+
</VideoWithBackdropParts.Root>
|
|
4823
|
+
</div>
|
|
4824
|
+
```
|
|
4825
|
+
|
|
4826
|
+
```tsx
|
|
4827
|
+
<div className="grid grid-cols-2 gap-4 h-screen">
|
|
4828
|
+
{(["low", "medium", "high", "extreme"] as const).map((blur) => (
|
|
4829
|
+
<div key={blur} className="relative">
|
|
4830
|
+
<VideoWithBackdrop
|
|
4831
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4832
|
+
blur={blur}
|
|
4833
|
+
overlay="none"
|
|
4834
|
+
maxWidth="100%"
|
|
4835
|
+
padding="sm"
|
|
4836
|
+
rounded="md"
|
|
4837
|
+
/>
|
|
4838
|
+
<div className="absolute top-16 left-16 z-20 bg-black/60 px-12 py-6 rounded-4">
|
|
4839
|
+
<span className="text-white text-14">blur="{blur}"</span>
|
|
4840
|
+
</div>
|
|
4841
|
+
</div>
|
|
4842
|
+
))}
|
|
4843
|
+
</div>
|
|
4844
|
+
```
|
|
4845
|
+
|
|
4846
|
+
```tsx
|
|
4847
|
+
<div className="grid grid-cols-3 gap-4 h-[400px]">
|
|
4848
|
+
{(["none", "vignette", "top-bottom"] as const).map((overlay) => (
|
|
4849
|
+
<div key={overlay} className="relative h-full">
|
|
4850
|
+
<VideoWithBackdrop
|
|
4851
|
+
cloudflare={DGA_CLOUDFLARE}
|
|
4852
|
+
blur="high"
|
|
4853
|
+
overlay={overlay}
|
|
4854
|
+
maxWidth="100%"
|
|
4855
|
+
padding="sm"
|
|
4856
|
+
rounded="md"
|
|
4857
|
+
/>
|
|
4858
|
+
<div className="absolute top-16 left-16 z-20 bg-black/60 px-12 py-6 rounded-4">
|
|
4859
|
+
<span className="text-white text-14">
|
|
4860
|
+
overlay="{overlay}"
|
|
4861
|
+
</span>
|
|
4862
|
+
</div>
|
|
4863
|
+
</div>
|
|
4864
|
+
))}
|
|
4865
|
+
</div>
|
|
4866
|
+
```
|
|
4867
|
+
|
|
4868
|
+
```tsx
|
|
4869
|
+
<div className="h-[700px]">
|
|
4870
|
+
<VideoWithBackdropParts.Root cloudflare={DGA_CLOUDFLARE} fullHeight>
|
|
4871
|
+
<VideoWithBackdropParts.Backdrop
|
|
4872
|
+
blur="extreme"
|
|
4873
|
+
overlay="top-bottom"
|
|
4874
|
+
opacity={0.4}
|
|
4875
|
+
syncEnabled={false}
|
|
4876
|
+
/>
|
|
4877
|
+
<VideoWithBackdropParts.Content fullHeight padding="lg">
|
|
4878
|
+
<div className="flex flex-col items-center justify-center text-center gap-32 max-w-4xl">
|
|
4879
|
+
<div>
|
|
4880
|
+
<h1 className="typography-h1-lg text-white mb-16">
|
|
4881
|
+
Transform Your Digital Experience
|
|
4882
|
+
</h1>
|
|
4883
|
+
<p className="typography-body-lg-md text-white/80 mb-24">
|
|
4884
|
+
Discover how our platform can help you build stunning,
|
|
4885
|
+
accessible web applications with modern design patterns.
|
|
4886
|
+
</p>
|
|
4887
|
+
<div className="flex gap-16 justify-center">
|
|
4888
|
+
<Button size="lg">Get Started</Button>
|
|
4889
|
+
<Button variant="secondary" size="lg">
|
|
4890
|
+
Learn More
|
|
4891
|
+
</Button>
|
|
4892
|
+
</div>
|
|
4893
|
+
</div>
|
|
4894
|
+
<VideoWithBackdropParts.Video
|
|
4895
|
+
maxWidth="800px"
|
|
4896
|
+
rounded="lg"
|
|
4897
|
+
controls
|
|
4898
|
+
/>
|
|
4899
|
+
</div>
|
|
4900
|
+
</VideoWithBackdropParts.Content>
|
|
4901
|
+
</VideoWithBackdropParts.Root>
|
|
4902
|
+
</div>
|
|
4903
|
+
```
|
|
4904
|
+
|
|
4905
|
+
|
|
3660
4906
|
## Typography
|
|
3661
4907
|
|
|
3662
4908
|
### Prose
|
|
@@ -3763,5 +5009,5 @@ className="font-semibold" // Font weight 600
|
|
|
3763
5009
|
- **Action:** Button
|
|
3764
5010
|
- **Display:** Card, Hero, UsGovBanner
|
|
3765
5011
|
- **Navigation:** Navbar
|
|
3766
|
-
- **Other:** Accordion, Background, Banner, CardGrid, DevToolbar, FaqSection, GridOverlay, Input, NdstudioFooter, PagerControl, Popover, QuoteBlock, River, Select, Tooltip, Tout, TwoColumnSection
|
|
5012
|
+
- **Other:** Accordion, Background, Banner, BlurredVideoBackdrop, CardGrid, DevToolbar, Dialog, FaqSection, GridOverlay, Input, NdstudioFooter, PagerControl, Popover, QuoteBlock, River, Select, Tooltip, Tout, TwoColumnSection, VideoDialog, VideoPlayer, VideoWithBackdrop
|
|
3767
5013
|
- **Typography:** Prose
|