aural-ui 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +456 -0
- package/dist/components/aspect-ratio/AspectRatio.stories.tsx +1327 -0
- package/dist/components/aspect-ratio/index.tsx +10 -0
- package/dist/components/aspect-ratio/meta.ts +8 -0
- package/dist/components/avatar/Avatar.stories.tsx +645 -0
- package/dist/components/avatar/index.tsx +50 -0
- package/dist/components/avatar/meta.ts +8 -0
- package/dist/components/badge/Badge.stories.tsx +169 -0
- package/dist/components/badge/index.tsx +28 -0
- package/dist/components/badge/meta.ts +6 -0
- package/dist/components/banner/Banner.stories.tsx +475 -0
- package/dist/components/banner/index.tsx +256 -0
- package/dist/components/banner/meta.ts +36 -0
- package/dist/components/button/Button.stories.tsx +74 -0
- package/dist/components/button/index.tsx +158 -0
- package/dist/components/button/meta.ts +33 -0
- package/dist/components/card/Card.stories.tsx +377 -0
- package/dist/components/card/index.tsx +85 -0
- package/dist/components/card/meta.ts +14 -0
- package/dist/components/char-count/CharCount.stories.tsx +334 -0
- package/dist/components/char-count/index.tsx +51 -0
- package/dist/components/char-count/meta.ts +13 -0
- package/dist/components/checkbox/Checkbox.stories.tsx +209 -0
- package/dist/components/checkbox/index.tsx +34 -0
- package/dist/components/checkbox/meta.ts +19 -0
- package/dist/components/chip/Chip.stories.tsx +207 -0
- package/dist/components/chip/index.tsx +92 -0
- package/dist/components/chip/meta.ts +17 -0
- package/dist/components/circular-loader/CircularLoader.stories.tsx +741 -0
- package/dist/components/circular-loader/index.tsx +138 -0
- package/dist/components/circular-loader/meta.ts +11 -0
- package/dist/components/collapsible/Collapsible.stories.tsx +319 -0
- package/dist/components/collapsible/index.tsx +158 -0
- package/dist/components/collapsible/meta.ts +22 -0
- package/dist/components/command/Command.stories.tsx +996 -0
- package/dist/components/command/index.tsx +324 -0
- package/dist/components/command/meta.ts +18 -0
- package/dist/components/dialog/Dialog.stories.tsx +963 -0
- package/dist/components/dialog/index.tsx +250 -0
- package/dist/components/dialog/meta.ts +28 -0
- package/dist/components/divider/Divider.stories.tsx +633 -0
- package/dist/components/divider/index.tsx +181 -0
- package/dist/components/divider/meta.ts +12 -0
- package/dist/components/dot-loader/DotLoader.stories.tsx +352 -0
- package/dist/components/dot-loader/index.tsx +78 -0
- package/dist/components/dot-loader/meta.ts +14 -0
- package/dist/components/dropdown/Dropdown.stories.tsx +1210 -0
- package/dist/components/dropdown/index.tsx +479 -0
- package/dist/components/dropdown/meta.ts +21 -0
- package/dist/components/form/Form.stories.tsx +320 -0
- package/dist/components/form/index.tsx +183 -0
- package/dist/components/form/meta.ts +11 -0
- package/dist/components/helper-text/HelperText.stories.tsx +254 -0
- package/dist/components/helper-text/index.tsx +102 -0
- package/dist/components/helper-text/meta.ts +18 -0
- package/dist/components/hover-card/HoverCard.stories.tsx +1328 -0
- package/dist/components/hover-card/index.tsx +42 -0
- package/dist/components/hover-card/meta.ts +12 -0
- package/dist/components/icon-button/IconButton.stories.tsx +252 -0
- package/dist/components/icon-button/index.tsx +130 -0
- package/dist/components/icon-button/meta.ts +20 -0
- package/dist/components/if-else/if-else.stories.tsx +100 -0
- package/dist/components/if-else/index.tsx +56 -0
- package/dist/components/if-else/meta.ts +6 -0
- package/dist/components/index.ts +70 -0
- package/dist/components/input/Input.stories.tsx +431 -0
- package/dist/components/input/index.tsx +487 -0
- package/dist/components/input/meta.ts +28 -0
- package/dist/components/label/Label.stories.tsx +200 -0
- package/dist/components/label/index.tsx +43 -0
- package/dist/components/label/meta.ts +14 -0
- package/dist/components/list/List.stories.tsx +963 -0
- package/dist/components/list/index.tsx +567 -0
- package/dist/components/list/meta.ts +24 -0
- package/dist/components/marquee/Marquee.stories.tsx +819 -0
- package/dist/components/marquee/index.tsx +107 -0
- package/dist/components/marquee/meta.ts +6 -0
- package/dist/components/overlay/Overlay.stories.tsx +954 -0
- package/dist/components/overlay/index.tsx +58 -0
- package/dist/components/overlay/meta.ts +10 -0
- package/dist/components/pagination/Pagination.stories.tsx +354 -0
- package/dist/components/pagination/index.tsx +455 -0
- package/dist/components/pagination/meta.ts +29 -0
- package/dist/components/popover/Popover.stories.tsx +1037 -0
- package/dist/components/popover/index.tsx +67 -0
- package/dist/components/popover/meta.ts +12 -0
- package/dist/components/radio/Radio.stories.tsx +146 -0
- package/dist/components/radio/index.tsx +41 -0
- package/dist/components/radio/meta.ts +19 -0
- package/dist/components/resizable/Resizable.stories.tsx +866 -0
- package/dist/components/resizable/index.tsx +55 -0
- package/dist/components/resizable/meta.ts +12 -0
- package/dist/components/scroll-area/ScrollArea.stories.tsx +1104 -0
- package/dist/components/scroll-area/index.tsx +55 -0
- package/dist/components/scroll-area/meta.ts +8 -0
- package/dist/components/search/Search.stories.tsx +678 -0
- package/dist/components/search/index.tsx +141 -0
- package/dist/components/search/meta.ts +6 -0
- package/dist/components/select/Select.stories.tsx +962 -0
- package/dist/components/select/index.tsx +512 -0
- package/dist/components/select/meta.ts +40 -0
- package/dist/components/sheet/Sheet.stories.tsx +1060 -0
- package/dist/components/sheet/index.tsx +440 -0
- package/dist/components/sheet/meta.ts +38 -0
- package/dist/components/skelton/Skelton.stories.tsx +859 -0
- package/dist/components/skelton/index.tsx +17 -0
- package/dist/components/skelton/meta.ts +6 -0
- package/dist/components/slider/Slider.stories.tsx +876 -0
- package/dist/components/slider/index.tsx +156 -0
- package/dist/components/slider/meta.ts +29 -0
- package/dist/components/stepper/Stepper.stories.tsx +639 -0
- package/dist/components/stepper/index.tsx +650 -0
- package/dist/components/stepper/meta.ts +19 -0
- package/dist/components/switch/Switch.stories.tsx +85 -0
- package/dist/components/switch/index.tsx +37 -0
- package/dist/components/switch/meta.ts +24 -0
- package/dist/components/switch-case/SwitchCase.stories.tsx +209 -0
- package/dist/components/switch-case/index.tsx +89 -0
- package/dist/components/switch-case/meta.ts +6 -0
- package/dist/components/table/Table.stories.tsx +1095 -0
- package/dist/components/table/index.tsx +113 -0
- package/dist/components/table/meta.ts +20 -0
- package/dist/components/tabs/Tabs.stories.tsx +1379 -0
- package/dist/components/tabs/index.tsx +186 -0
- package/dist/components/tabs/meta.ts +25 -0
- package/dist/components/tag/Tag.stories.tsx +625 -0
- package/dist/components/tag/index.tsx +320 -0
- package/dist/components/tag/meta.ts +52 -0
- package/dist/components/textarea/TextArea.stories.tsx +723 -0
- package/dist/components/textarea/index.tsx +480 -0
- package/dist/components/textarea/meta.ts +23 -0
- package/dist/components/toast/Toast.stories.tsx +1427 -0
- package/dist/components/toast/index.tsx +26 -0
- package/dist/components/toast/meta.ts +19 -0
- package/dist/components/toggle/Toggle.stories.tsx +1093 -0
- package/dist/components/toggle/index.tsx +44 -0
- package/dist/components/toggle/meta.ts +19 -0
- package/dist/components/tooltip/Tooltip.stories.tsx +1548 -0
- package/dist/components/tooltip/index.tsx +304 -0
- package/dist/components/tooltip/meta.ts +21 -0
- package/dist/components/typography/Typography.stories.tsx +197 -0
- package/dist/components/typography/index.tsx +184 -0
- package/dist/components/typography/meta.ts +38 -0
- package/dist/fonts/LabGrotesque-Regular.ttf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Bold.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Light.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Medium.otf +0 -0
- package/dist/fonts/LabGrotesqueTRIAL-Regular.otf +0 -0
- package/dist/fonts/PPSupplySans-Regular (1).otf +0 -0
- package/dist/fonts/PPSupplySans-Regular.otf +0 -0
- package/dist/fonts/PPSupplySans-Ultralight.otf +0 -0
- package/dist/hooks/index.ts +3 -0
- package/dist/hooks/use-previous/UsePrevious.stories.tsx +997 -0
- package/dist/hooks/use-previous/index.ts +15 -0
- package/dist/hooks/use-previous/meta.ts +6 -0
- package/dist/hooks/use-standalone-pagination/UseStandalonePagination.stories.tsx +983 -0
- package/dist/hooks/use-standalone-pagination/index.ts +146 -0
- package/dist/hooks/use-standalone-pagination/meta.ts +6 -0
- package/dist/icons/Icons.stories.tsx +29 -0
- package/dist/icons/alert-icon/AlertIcon.stories.tsx +991 -0
- package/dist/icons/alert-icon/index.tsx +48 -0
- package/dist/icons/alert-icon/meta.ts +8 -0
- package/dist/icons/all-icons.tsx +738 -0
- package/dist/icons/angle-down-icon/AngleDownIcon.stories.tsx +1031 -0
- package/dist/icons/angle-down-icon/index.tsx +25 -0
- package/dist/icons/angle-down-icon/meta.ts +8 -0
- package/dist/icons/arrow-box-left-icon/ArrowBoxLeftIcon.stories.tsx +1080 -0
- package/dist/icons/arrow-box-left-icon/index.tsx +24 -0
- package/dist/icons/arrow-box-left-icon/meta.ts +8 -0
- package/dist/icons/arrow-right-icon/ArrowRightIcon.stories.tsx +1151 -0
- package/dist/icons/arrow-right-icon/index.tsx +26 -0
- package/dist/icons/arrow-right-icon/meta.ts +8 -0
- package/dist/icons/arrow-right-up-icon/ArrowRightUpIcon.stories.tsx +1273 -0
- package/dist/icons/arrow-right-up-icon/index.tsx +24 -0
- package/dist/icons/arrow-right-up-icon/meta.ts +8 -0
- package/dist/icons/art-board-icon/ArtBoardIcon.stories.tsx +670 -0
- package/dist/icons/art-board-icon/index.tsx +24 -0
- package/dist/icons/art-board-icon/meta.ts +7 -0
- package/dist/icons/audio-bar-icon/AudioBarIcon.stories.tsx +1244 -0
- package/dist/icons/audio-bar-icon/index.tsx +19 -0
- package/dist/icons/audio-bar-icon/meta.ts +8 -0
- package/dist/icons/bubble-check-icon/BubbleCheckIcon.stories.tsx +1239 -0
- package/dist/icons/bubble-check-icon/index.tsx +24 -0
- package/dist/icons/bubble-check-icon/meta.ts +8 -0
- package/dist/icons/bubble-crossed-icon/BubbleCrossedIcon.stories.tsx +1228 -0
- package/dist/icons/bubble-crossed-icon/index.tsx +24 -0
- package/dist/icons/bubble-crossed-icon/meta.ts +8 -0
- package/dist/icons/bubble-sparkle-icon/BubbleSparkleIcon.stories.tsx +912 -0
- package/dist/icons/bubble-sparkle-icon/index.tsx +26 -0
- package/dist/icons/bubble-sparkle-icon/meta.ts +8 -0
- package/dist/icons/chevron-double-left-icon/ChevronDoubleLeftIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-double-left-icon/index.tsx +34 -0
- package/dist/icons/chevron-double-left-icon/meta.ts +8 -0
- package/dist/icons/chevron-double-right-icon/ChevronDoubleRightIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-double-right-icon/index.tsx +34 -0
- package/dist/icons/chevron-double-right-icon/meta.ts +8 -0
- package/dist/icons/chevron-down-icon/ChevronDownIcon.stories.tsx +1001 -0
- package/dist/icons/chevron-down-icon/index.tsx +27 -0
- package/dist/icons/chevron-down-icon/meta.ts +8 -0
- package/dist/icons/chevron-left-icon/ChevronLeftIcon.stories.tsx +1029 -0
- package/dist/icons/chevron-left-icon/index.tsx +27 -0
- package/dist/icons/chevron-left-icon/meta.ts +8 -0
- package/dist/icons/chevron-right-icon/ChevronRightIcon.stories.tsx +1021 -0
- package/dist/icons/chevron-right-icon/index.tsx +27 -0
- package/dist/icons/chevron-right-icon/meta.ts +8 -0
- package/dist/icons/chevron-up-icon/ChevronUpIcon.stories.tsx +1036 -0
- package/dist/icons/chevron-up-icon/index.tsx +27 -0
- package/dist/icons/chevron-up-icon/meta.ts +8 -0
- package/dist/icons/command-icon/CommandIcon.stories.tsx +1098 -0
- package/dist/icons/command-icon/index.tsx +24 -0
- package/dist/icons/command-icon/meta.ts +8 -0
- package/dist/icons/cross-circle-icon/CrossCircleIcon.stories.tsx +1061 -0
- package/dist/icons/cross-circle-icon/index.tsx +23 -0
- package/dist/icons/cross-circle-icon/meta.ts +8 -0
- package/dist/icons/cross-icon/CrossIcon.stories.tsx +1027 -0
- package/dist/icons/cross-icon/index.tsx +24 -0
- package/dist/icons/cross-icon/meta.ts +8 -0
- package/dist/icons/edit-big-icon/EditBigIcon.stories.tsx +1092 -0
- package/dist/icons/edit-big-icon/index.tsx +22 -0
- package/dist/icons/edit-big-icon/meta.ts +8 -0
- package/dist/icons/eye-close-icon/EyeCloseIcon.stories.tsx +1090 -0
- package/dist/icons/eye-close-icon/index.tsx +26 -0
- package/dist/icons/eye-close-icon/meta.ts +8 -0
- package/dist/icons/eye-open-icon/EyeOpenIcon.stories.tsx +1098 -0
- package/dist/icons/eye-open-icon/index.tsx +24 -0
- package/dist/icons/eye-open-icon/meta.ts +8 -0
- package/dist/icons/feature-shine-icon/FeatureShineIcon.stories.tsx +1071 -0
- package/dist/icons/feature-shine-icon/index.tsx +29 -0
- package/dist/icons/feature-shine-icon/meta.ts +8 -0
- package/dist/icons/file-chart-icon/FileChartIcon.stories.tsx +1115 -0
- package/dist/icons/file-chart-icon/index.tsx +24 -0
- package/dist/icons/file-chart-icon/meta.ts +8 -0
- package/dist/icons/file-text-icon/FileTextIcon.stories.tsx +668 -0
- package/dist/icons/file-text-icon/index.tsx +24 -0
- package/dist/icons/file-text-icon/meta.ts +8 -0
- package/dist/icons/grip-vertical-icon/GripVerticalIcon.stories.tsx +1239 -0
- package/dist/icons/grip-vertical-icon/index.tsx +28 -0
- package/dist/icons/grip-vertical-icon/meta.ts +8 -0
- package/dist/icons/image-icon/ImageIcon.stories.tsx +1181 -0
- package/dist/icons/image-icon/index.tsx +24 -0
- package/dist/icons/image-icon/meta.ts +8 -0
- package/dist/icons/import-folder-icon/ImportFolderIcon.stories.tsx +1248 -0
- package/dist/icons/import-folder-icon/index.tsx +22 -0
- package/dist/icons/import-folder-icon/meta.ts +8 -0
- package/dist/icons/index.ts +46 -0
- package/dist/icons/light-bulb-simple-icon/LightBulbSimpleIcon.stories.tsx +1272 -0
- package/dist/icons/light-bulb-simple-icon/index.tsx +24 -0
- package/dist/icons/light-bulb-simple-icon/meta.ts +8 -0
- package/dist/icons/magic-book-icon/MagicBookIcon.stories.tsx +1245 -0
- package/dist/icons/magic-book-icon/index.tsx +32 -0
- package/dist/icons/magic-book-icon/meta.ts +8 -0
- package/dist/icons/maintenance-icon/MaintenanceIcon.stories.tsx +1251 -0
- package/dist/icons/maintenance-icon/index.tsx +23 -0
- package/dist/icons/maintenance-icon/meta.ts +8 -0
- package/dist/icons/message-icon/MessageIcon.stories.tsx +595 -0
- package/dist/icons/message-icon/index.tsx +30 -0
- package/dist/icons/message-icon/meta.ts +8 -0
- package/dist/icons/move-horizontal-icon/MoveHorizontalIcon.stories.tsx +1245 -0
- package/dist/icons/move-horizontal-icon/index.tsx +23 -0
- package/dist/icons/move-horizontal-icon/meta.ts +8 -0
- package/dist/icons/move-vertical-icon/MoveVerticalIcon.stories.tsx +1196 -0
- package/dist/icons/move-vertical-icon/index.tsx +23 -0
- package/dist/icons/move-vertical-icon/meta.ts +8 -0
- package/dist/icons/page-search-icon/PageSearchIcon.stories.tsx +1167 -0
- package/dist/icons/page-search-icon/index.tsx +21 -0
- package/dist/icons/page-search-icon/meta.ts +8 -0
- package/dist/icons/pencil-icon/PencilIcon.stories.tsx +1131 -0
- package/dist/icons/pencil-icon/index.tsx +21 -0
- package/dist/icons/pencil-icon/meta.ts +8 -0
- package/dist/icons/plus-icon/PlusIcon.stories.tsx +1151 -0
- package/dist/icons/plus-icon/index.tsx +24 -0
- package/dist/icons/plus-icon/meta.ts +8 -0
- package/dist/icons/search-icon/SearchIcon.stories.tsx +1181 -0
- package/dist/icons/search-icon/index.tsx +24 -0
- package/dist/icons/search-icon/meta.ts +8 -0
- package/dist/icons/site-logo-icon/SiteLogoIcon.stories.tsx +1167 -0
- package/dist/icons/site-logo-icon/index.tsx +79 -0
- package/dist/icons/site-logo-icon/meta.ts +8 -0
- package/dist/icons/spinner-gradient-icon/SpinnerGradientIcon.stories.tsx +637 -0
- package/dist/icons/spinner-gradient-icon/index.tsx +53 -0
- package/dist/icons/spinner-gradient-icon/meta.ts +8 -0
- package/dist/icons/spinner-solid-icon/SpinnerSolidIcon.stories.tsx +644 -0
- package/dist/icons/spinner-solid-icon/index.tsx +59 -0
- package/dist/icons/spinner-solid-icon/meta.ts +8 -0
- package/dist/icons/spinner-solid-neutral-icon/SpinnerSolidINeutralcon.stories.tsx +736 -0
- package/dist/icons/spinner-solid-neutral-icon/index.tsx +53 -0
- package/dist/icons/spinner-solid-neutral-icon/meta.ts +8 -0
- package/dist/icons/tick-circle-icon/TickCircleIcon.stories.tsx +1204 -0
- package/dist/icons/tick-circle-icon/index.tsx +23 -0
- package/dist/icons/tick-circle-icon/meta.ts +8 -0
- package/dist/icons/tick-icon/TickIcon.stories.tsx +1340 -0
- package/dist/icons/tick-icon/index.tsx +24 -0
- package/dist/icons/tick-icon/meta.ts +8 -0
- package/dist/icons/trash-icon/TrashIcon.stories.tsx +996 -0
- package/dist/icons/trash-icon/index.tsx +24 -0
- package/dist/icons/trash-icon/meta.ts +8 -0
- package/dist/icons/upload-icon/UploadIcon.stories.tsx +947 -0
- package/dist/icons/upload-icon/index.tsx +24 -0
- package/dist/icons/upload-icon/meta.ts +8 -0
- package/dist/icons/vertical-menu-icon/VerticalMenuIcon.stories.tsx +1045 -0
- package/dist/icons/vertical-menu-icon/index.tsx +27 -0
- package/dist/icons/vertical-menu-icon/meta.ts +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +206 -0
- package/dist/lib/utils.ts +6 -0
- package/dist/styles/aural-theme.css +1008 -0
- package/package.json +142 -0
|
@@ -0,0 +1,738 @@
|
|
|
1
|
+
import React, { useMemo, useState } from "react"
|
|
2
|
+
import { Button } from "@components/button"
|
|
3
|
+
import {
|
|
4
|
+
Dialog,
|
|
5
|
+
DialogContent,
|
|
6
|
+
DialogHeader,
|
|
7
|
+
DialogTitle,
|
|
8
|
+
} from "@components/dialog"
|
|
9
|
+
import * as IconSet from "@icons/index"
|
|
10
|
+
|
|
11
|
+
// Icon Usage Modal
|
|
12
|
+
const IconUsageModal: React.FC<{
|
|
13
|
+
isOpen: boolean
|
|
14
|
+
onClose: () => void
|
|
15
|
+
iconName: string
|
|
16
|
+
IconComponent: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
17
|
+
}> = ({ isOpen, onClose, iconName, IconComponent }) => {
|
|
18
|
+
const [copiedIndex, setCopiedIndex] = useState<number | null>(null)
|
|
19
|
+
|
|
20
|
+
const usageExamples = [
|
|
21
|
+
{
|
|
22
|
+
title: "Basic Usage",
|
|
23
|
+
code: `import { ${iconName} } from "@icons/index"
|
|
24
|
+
|
|
25
|
+
function MyComponent() {
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex items-center gap-2">
|
|
28
|
+
<${iconName} className="h-5 w-5 text-white" />
|
|
29
|
+
<span>Icon with text</span>
|
|
30
|
+
</div>
|
|
31
|
+
)
|
|
32
|
+
}`,
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
title: "Custom Size & Color",
|
|
36
|
+
code: `import { ${iconName} } from "@icons/index"
|
|
37
|
+
|
|
38
|
+
function CustomIcon() {
|
|
39
|
+
return (
|
|
40
|
+
<${iconName}
|
|
41
|
+
width={32}
|
|
42
|
+
height={32}
|
|
43
|
+
className="text-blue-500"
|
|
44
|
+
/>
|
|
45
|
+
)
|
|
46
|
+
}`,
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
title: "In Button",
|
|
50
|
+
code: `import { ${iconName} } from "@icons/index"
|
|
51
|
+
import { Button } from "@components/button"
|
|
52
|
+
|
|
53
|
+
function IconButton() {
|
|
54
|
+
return (
|
|
55
|
+
<Button className="flex items-center gap-2">
|
|
56
|
+
<${iconName} className="h-4 w-4" />
|
|
57
|
+
Click me
|
|
58
|
+
</Button>
|
|
59
|
+
)
|
|
60
|
+
}`,
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
title: "Interactive States",
|
|
64
|
+
code: `import { ${iconName} } from "@icons/index"
|
|
65
|
+
|
|
66
|
+
function InteractiveIcon() {
|
|
67
|
+
return (
|
|
68
|
+
<${iconName} className="h-6 w-6 text-gray-400 transition-colors hover:text-white" />
|
|
69
|
+
)
|
|
70
|
+
}`,
|
|
71
|
+
},
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
const copyToClipboard = async (text: string, index: number) => {
|
|
75
|
+
try {
|
|
76
|
+
await navigator.clipboard.writeText(text)
|
|
77
|
+
setCopiedIndex(index)
|
|
78
|
+
setTimeout(() => setCopiedIndex(null), 2000)
|
|
79
|
+
} catch (err) {
|
|
80
|
+
console.error("Failed to copy text: ", err)
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<Dialog open={isOpen} onOpenChange={onClose}>
|
|
86
|
+
<DialogContent
|
|
87
|
+
classes={{
|
|
88
|
+
content: "max-w-4xl",
|
|
89
|
+
root: "bg-gray-900 text-white",
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<DialogHeader className="border-b border-white/10 pb-4">
|
|
93
|
+
<div className="flex items-center gap-4">
|
|
94
|
+
<div className="rounded-lg bg-white/5 p-3">
|
|
95
|
+
<IconComponent className="h-8 w-8 text-white" />
|
|
96
|
+
</div>
|
|
97
|
+
<div>
|
|
98
|
+
<DialogTitle className="text-xl font-semibold text-white">
|
|
99
|
+
{iconName}
|
|
100
|
+
</DialogTitle>
|
|
101
|
+
<p className="text-sm text-white/60">
|
|
102
|
+
Usage examples and implementation
|
|
103
|
+
</p>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</DialogHeader>
|
|
107
|
+
|
|
108
|
+
<div className="max-h-[calc(90vh-200px)] space-y-6 overflow-y-auto">
|
|
109
|
+
{/* Usage Examples */}
|
|
110
|
+
{usageExamples.map((example, index) => (
|
|
111
|
+
<div key={index} className="space-y-3">
|
|
112
|
+
<h3 className="text-lg font-medium text-white">
|
|
113
|
+
{example.title}
|
|
114
|
+
</h3>
|
|
115
|
+
<div className="relative">
|
|
116
|
+
<pre className="overflow-x-auto rounded-lg border border-white/10 bg-black/40 p-4 text-sm text-gray-300">
|
|
117
|
+
<code>{example.code}</code>
|
|
118
|
+
</pre>
|
|
119
|
+
<Button
|
|
120
|
+
onClick={() => copyToClipboard(example.code, index)}
|
|
121
|
+
className="absolute top-2 right-2"
|
|
122
|
+
size="sm"
|
|
123
|
+
variant="outline"
|
|
124
|
+
>
|
|
125
|
+
{copiedIndex === index ? "Copied!" : "Copy"}
|
|
126
|
+
</Button>
|
|
127
|
+
</div>
|
|
128
|
+
</div>
|
|
129
|
+
))}
|
|
130
|
+
|
|
131
|
+
{/* Live Preview */}
|
|
132
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-6">
|
|
133
|
+
<h3 className="mb-4 text-lg font-medium text-white">
|
|
134
|
+
Live Preview
|
|
135
|
+
</h3>
|
|
136
|
+
<div className="flex flex-wrap items-center gap-6">
|
|
137
|
+
<div className="text-center">
|
|
138
|
+
<IconComponent className="mb-2 h-6 w-6 text-white" />
|
|
139
|
+
<span className="text-xs text-white/60">Default</span>
|
|
140
|
+
</div>
|
|
141
|
+
<div className="text-center">
|
|
142
|
+
<IconComponent className="mb-2 h-8 w-8 text-blue-400" />
|
|
143
|
+
<span className="text-xs text-white/60">Large Blue</span>
|
|
144
|
+
</div>
|
|
145
|
+
<div className="text-center">
|
|
146
|
+
<IconComponent className="mb-2 h-4 w-4 text-green-400" />
|
|
147
|
+
<span className="text-xs text-white/60">Small Green</span>
|
|
148
|
+
</div>
|
|
149
|
+
<div className="text-center">
|
|
150
|
+
<IconComponent className="mb-2 h-6 w-6 text-red-400" />
|
|
151
|
+
<span className="text-xs text-white/60">Red</span>
|
|
152
|
+
</div>
|
|
153
|
+
<div className="text-center">
|
|
154
|
+
<IconComponent className="mb-2 h-6 w-6 text-yellow-400" />
|
|
155
|
+
<span className="text-xs text-white/60">Yellow</span>
|
|
156
|
+
</div>
|
|
157
|
+
</div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
{/* Icon Properties */}
|
|
161
|
+
<div className="rounded-lg border border-white/10 bg-white/5 p-6">
|
|
162
|
+
<h3 className="mb-4 text-lg font-medium text-white">
|
|
163
|
+
Icon Properties
|
|
164
|
+
</h3>
|
|
165
|
+
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
|
166
|
+
<div className="space-y-2">
|
|
167
|
+
<h4 className="text-sm font-medium text-white/80">
|
|
168
|
+
Common Props
|
|
169
|
+
</h4>
|
|
170
|
+
<ul className="space-y-1 text-sm text-white/60">
|
|
171
|
+
<li>
|
|
172
|
+
<code className="rounded bg-black/20 px-1">className</code>{" "}
|
|
173
|
+
- CSS classes
|
|
174
|
+
</li>
|
|
175
|
+
<li>
|
|
176
|
+
<code className="rounded bg-black/20 px-1">width</code> -
|
|
177
|
+
Icon width
|
|
178
|
+
</li>
|
|
179
|
+
<li>
|
|
180
|
+
<code className="rounded bg-black/20 px-1">height</code> -
|
|
181
|
+
Icon height
|
|
182
|
+
</li>
|
|
183
|
+
</ul>
|
|
184
|
+
</div>
|
|
185
|
+
<div className="space-y-2">
|
|
186
|
+
<h4 className="text-sm font-medium text-white/80">SVG Props</h4>
|
|
187
|
+
<ul className="space-y-1 text-sm text-white/60">
|
|
188
|
+
<li>
|
|
189
|
+
<code className="rounded bg-black/20 px-1">stroke</code> -
|
|
190
|
+
Stroke color
|
|
191
|
+
</li>
|
|
192
|
+
<li>
|
|
193
|
+
<code className="rounded bg-black/20 px-1">
|
|
194
|
+
strokeWidth
|
|
195
|
+
</code>{" "}
|
|
196
|
+
- Stroke width
|
|
197
|
+
</li>
|
|
198
|
+
<li>
|
|
199
|
+
<code className="rounded bg-black/20 px-1">fill</code> -
|
|
200
|
+
Fill color
|
|
201
|
+
</li>
|
|
202
|
+
</ul>
|
|
203
|
+
</div>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</DialogContent>
|
|
208
|
+
</Dialog>
|
|
209
|
+
)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
interface IconCategoryProps {
|
|
213
|
+
category: string
|
|
214
|
+
children: React.ReactNode
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const IconCategory: React.FC<IconCategoryProps> = ({ category, children }) => {
|
|
218
|
+
return (
|
|
219
|
+
<div className="space-y-8">
|
|
220
|
+
<div className="flex items-center gap-4">
|
|
221
|
+
<div className="h-px flex-1 bg-gradient-to-r from-purple-500/50 to-transparent" />
|
|
222
|
+
<h2 className="rounded-full border border-purple-500/20 bg-purple-500/10 px-4 py-2 text-lg font-semibold text-purple-300">
|
|
223
|
+
{category}
|
|
224
|
+
</h2>
|
|
225
|
+
<div className="h-px flex-1 bg-gradient-to-l from-purple-500/50 to-transparent" />
|
|
226
|
+
</div>
|
|
227
|
+
<div className="space-y-12">{children}</div>
|
|
228
|
+
</div>
|
|
229
|
+
)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
interface IconGridProps {
|
|
233
|
+
title: string
|
|
234
|
+
description?: string
|
|
235
|
+
icons: {
|
|
236
|
+
name: string
|
|
237
|
+
component: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
238
|
+
category?: string
|
|
239
|
+
description?: string
|
|
240
|
+
}[]
|
|
241
|
+
onIconClick?: (
|
|
242
|
+
name: string,
|
|
243
|
+
component: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
244
|
+
) => void
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const IconGrid: React.FC<IconGridProps> = ({
|
|
248
|
+
title,
|
|
249
|
+
description,
|
|
250
|
+
icons,
|
|
251
|
+
onIconClick,
|
|
252
|
+
}) => {
|
|
253
|
+
return (
|
|
254
|
+
<div className="space-y-6">
|
|
255
|
+
<div className="space-y-2">
|
|
256
|
+
<h3 className="text-2xl font-bold text-white">{title}</h3>
|
|
257
|
+
{description && (
|
|
258
|
+
<p className="text-sm leading-relaxed text-white/70">{description}</p>
|
|
259
|
+
)}
|
|
260
|
+
</div>
|
|
261
|
+
<div className="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8">
|
|
262
|
+
{icons.map(({ name, component: IconComponent, category }) => (
|
|
263
|
+
<div
|
|
264
|
+
key={name}
|
|
265
|
+
onClick={() => onIconClick?.(name, IconComponent)}
|
|
266
|
+
className="group relative cursor-pointer overflow-hidden rounded-lg border border-white/10 bg-white/5 transition-all duration-200 hover:scale-105 hover:border-white/20 hover:bg-white/10"
|
|
267
|
+
>
|
|
268
|
+
{/* Icon Display */}
|
|
269
|
+
<div className="flex h-24 items-center justify-center bg-gradient-to-br from-white/5 to-white/10 transition-all duration-200 group-hover:from-white/10 group-hover:to-white/15">
|
|
270
|
+
<IconComponent className="h-8 w-8 text-white transition-all duration-200 group-hover:scale-110 group-hover:text-blue-400" />
|
|
271
|
+
</div>
|
|
272
|
+
|
|
273
|
+
{/* Icon Info */}
|
|
274
|
+
<div className="space-y-2 p-3">
|
|
275
|
+
<h4 className="truncate text-xs font-medium text-white">
|
|
276
|
+
{name}
|
|
277
|
+
</h4>
|
|
278
|
+
{category && (
|
|
279
|
+
<span className="inline-block rounded-full bg-purple-500/20 px-2 py-1 text-xs text-purple-300">
|
|
280
|
+
{category}
|
|
281
|
+
</span>
|
|
282
|
+
)}
|
|
283
|
+
</div>
|
|
284
|
+
|
|
285
|
+
{/* Hover overlay */}
|
|
286
|
+
<div className="absolute inset-0 flex flex-col items-center justify-center bg-black/80 opacity-0 backdrop-blur-sm transition-opacity duration-200 group-hover:opacity-100">
|
|
287
|
+
<IconComponent className="mb-2 h-8 w-8 text-white" />
|
|
288
|
+
<p className="px-2 text-center text-xs font-medium text-white">
|
|
289
|
+
{name}
|
|
290
|
+
</p>
|
|
291
|
+
<p className="mt-1 text-xs text-blue-300">Click for usage</p>
|
|
292
|
+
</div>
|
|
293
|
+
</div>
|
|
294
|
+
))}
|
|
295
|
+
</div>
|
|
296
|
+
</div>
|
|
297
|
+
)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export const Icons: React.FC = () => {
|
|
301
|
+
const [searchTerm, setSearchTerm] = useState("")
|
|
302
|
+
const [selectedCategory, setSelectedCategory] = useState("all")
|
|
303
|
+
const [selectedIcon, setSelectedIcon] = useState<{
|
|
304
|
+
name: string
|
|
305
|
+
component: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
306
|
+
} | null>(null)
|
|
307
|
+
|
|
308
|
+
const categories = [
|
|
309
|
+
"all",
|
|
310
|
+
"navigation",
|
|
311
|
+
"actions",
|
|
312
|
+
"interface",
|
|
313
|
+
"content",
|
|
314
|
+
"status",
|
|
315
|
+
"social",
|
|
316
|
+
]
|
|
317
|
+
|
|
318
|
+
// Get all icon components and categorize them
|
|
319
|
+
const allIcons = useMemo(() => {
|
|
320
|
+
return Object.entries(IconSet)
|
|
321
|
+
.filter(([name]) => name.endsWith("Icon"))
|
|
322
|
+
.map(([name, component]) => ({
|
|
323
|
+
name,
|
|
324
|
+
component: component as React.ComponentType<
|
|
325
|
+
React.SVGProps<SVGSVGElement>
|
|
326
|
+
>,
|
|
327
|
+
category: categorizeIcon(name),
|
|
328
|
+
description: getIconDescription(name),
|
|
329
|
+
}))
|
|
330
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
331
|
+
}, [])
|
|
332
|
+
|
|
333
|
+
// Categorize icons based on their names
|
|
334
|
+
function categorizeIcon(iconName: string): string {
|
|
335
|
+
const name = iconName.toLowerCase()
|
|
336
|
+
|
|
337
|
+
if (name.includes("chevron") || name.includes("arrow")) {
|
|
338
|
+
return "navigation"
|
|
339
|
+
}
|
|
340
|
+
if (
|
|
341
|
+
name.includes("cross") ||
|
|
342
|
+
name.includes("tick") ||
|
|
343
|
+
name.includes("plus") ||
|
|
344
|
+
name.includes("edit") ||
|
|
345
|
+
name.includes("trash")
|
|
346
|
+
) {
|
|
347
|
+
return "actions"
|
|
348
|
+
}
|
|
349
|
+
if (
|
|
350
|
+
name.includes("eye") ||
|
|
351
|
+
name.includes("search") ||
|
|
352
|
+
name.includes("command") ||
|
|
353
|
+
name.includes("menu")
|
|
354
|
+
) {
|
|
355
|
+
return "interface"
|
|
356
|
+
}
|
|
357
|
+
if (
|
|
358
|
+
name.includes("file") ||
|
|
359
|
+
name.includes("image") ||
|
|
360
|
+
name.includes("bubble") ||
|
|
361
|
+
name.includes("import")
|
|
362
|
+
) {
|
|
363
|
+
return "content"
|
|
364
|
+
}
|
|
365
|
+
if (
|
|
366
|
+
name.includes("alert") ||
|
|
367
|
+
name.includes("maintenance") ||
|
|
368
|
+
name.includes("bulb")
|
|
369
|
+
) {
|
|
370
|
+
return "status"
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
return "interface"
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
// Get icon description based on name
|
|
377
|
+
function getIconDescription(iconName: string): string {
|
|
378
|
+
const descriptions: Record<string, string> = {
|
|
379
|
+
ChevronRightIcon: "Navigate forward or expand",
|
|
380
|
+
ChevronLeftIcon: "Navigate back or collapse",
|
|
381
|
+
CrossIcon: "Close or cancel action",
|
|
382
|
+
TickIcon: "Confirm or success state",
|
|
383
|
+
SearchIcon: "Search functionality",
|
|
384
|
+
EyeOpenIcon: "Show or visible state",
|
|
385
|
+
EyeCloseIcon: "Hide or invisible state",
|
|
386
|
+
AlertIcon: "Warning or attention",
|
|
387
|
+
PlusIcon: "Add or create new",
|
|
388
|
+
EditIcon: "Edit or modify",
|
|
389
|
+
TrashIcon: "Delete or remove",
|
|
390
|
+
ImageIcon: "Image content",
|
|
391
|
+
FileChartIcon: "Chart or analytics",
|
|
392
|
+
CommandIcon: "Keyboard shortcut",
|
|
393
|
+
VerticalMenuIcon: "More options menu",
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return descriptions[iconName] || "UI icon component"
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Filter icons based on search term and category
|
|
400
|
+
const filteredIcons = useMemo(() => {
|
|
401
|
+
let filtered = allIcons
|
|
402
|
+
|
|
403
|
+
// Filter by category
|
|
404
|
+
if (selectedCategory !== "all") {
|
|
405
|
+
filtered = filtered.filter((icon) => icon.category === selectedCategory)
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Filter by search term
|
|
409
|
+
if (searchTerm) {
|
|
410
|
+
filtered = filtered.filter(
|
|
411
|
+
(icon) =>
|
|
412
|
+
icon.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
413
|
+
icon.description?.toLowerCase().includes(searchTerm.toLowerCase())
|
|
414
|
+
)
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
return filtered
|
|
418
|
+
}, [allIcons, selectedCategory, searchTerm])
|
|
419
|
+
|
|
420
|
+
// Group icons by category for display
|
|
421
|
+
const iconsByCategory = useMemo(() => {
|
|
422
|
+
const grouped: Record<string, typeof filteredIcons> = {}
|
|
423
|
+
|
|
424
|
+
filteredIcons.forEach((icon) => {
|
|
425
|
+
if (!grouped[icon.category]) {
|
|
426
|
+
grouped[icon.category] = []
|
|
427
|
+
}
|
|
428
|
+
grouped[icon.category].push(icon)
|
|
429
|
+
})
|
|
430
|
+
|
|
431
|
+
return grouped
|
|
432
|
+
}, [filteredIcons])
|
|
433
|
+
|
|
434
|
+
const handleIconClick = (
|
|
435
|
+
name: string,
|
|
436
|
+
component: React.ComponentType<React.SVGProps<SVGSVGElement>>
|
|
437
|
+
) => {
|
|
438
|
+
setSelectedIcon({ name, component })
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// Calculate stats
|
|
442
|
+
const totalIcons = allIcons.length
|
|
443
|
+
const categoryCount = Object.keys(iconsByCategory).length
|
|
444
|
+
|
|
445
|
+
return (
|
|
446
|
+
<div className="min-h-screen bg-gradient-to-br from-gray-900 via-purple-900/20 to-gray-900">
|
|
447
|
+
{/* Header */}
|
|
448
|
+
<div className="relative overflow-hidden border-b border-white/10 bg-black/20 backdrop-blur-xl">
|
|
449
|
+
<div className="absolute inset-0 bg-gradient-to-r from-purple-500/10 via-transparent to-blue-500/10" />
|
|
450
|
+
<div className="relative mx-auto max-w-7xl px-6 py-16">
|
|
451
|
+
<div className="space-y-6 text-center">
|
|
452
|
+
<h1 className="bg-gradient-to-r from-white via-purple-200 to-white bg-clip-text text-5xl font-bold text-transparent">
|
|
453
|
+
Icon Library
|
|
454
|
+
</h1>
|
|
455
|
+
<p className="mx-auto max-w-3xl text-xl leading-relaxed text-white/70">
|
|
456
|
+
A comprehensive collection of carefully crafted icons built with
|
|
457
|
+
accessibility in mind. Each icon is optimized for clarity and
|
|
458
|
+
consistency across your interface.
|
|
459
|
+
</p>
|
|
460
|
+
|
|
461
|
+
{/* Stats */}
|
|
462
|
+
<div className="flex items-center justify-center gap-8 pt-8">
|
|
463
|
+
<div className="text-center">
|
|
464
|
+
<div className="text-3xl font-bold text-purple-300">
|
|
465
|
+
{totalIcons}+
|
|
466
|
+
</div>
|
|
467
|
+
<div className="text-sm text-white/60">Total icons</div>
|
|
468
|
+
</div>
|
|
469
|
+
<div className="h-8 w-px bg-white/20" />
|
|
470
|
+
<div className="text-center">
|
|
471
|
+
<div className="text-3xl font-bold text-blue-300">
|
|
472
|
+
{categoryCount}
|
|
473
|
+
</div>
|
|
474
|
+
<div className="text-sm text-white/60">Categories</div>
|
|
475
|
+
</div>
|
|
476
|
+
<div className="h-8 w-px bg-white/20" />
|
|
477
|
+
<div className="text-center">
|
|
478
|
+
<div className="text-3xl font-bold text-green-300">
|
|
479
|
+
Accessible
|
|
480
|
+
</div>
|
|
481
|
+
<div className="text-sm text-white/60">Radix UI</div>
|
|
482
|
+
</div>
|
|
483
|
+
</div>
|
|
484
|
+
</div>
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
|
|
488
|
+
{/* Controls */}
|
|
489
|
+
<div className="sticky top-0 z-40 border-b border-white/10 bg-black/80 backdrop-blur-xl">
|
|
490
|
+
<div className="mx-auto max-w-7xl px-6 py-4">
|
|
491
|
+
<div className="flex flex-col items-center justify-between gap-4 sm:flex-row">
|
|
492
|
+
<div className="flex flex-wrap gap-2">
|
|
493
|
+
{categories.map((category) => (
|
|
494
|
+
<button
|
|
495
|
+
key={category}
|
|
496
|
+
onClick={() => setSelectedCategory(category)}
|
|
497
|
+
className={`rounded-full px-4 py-2 text-sm font-medium transition-all duration-200 ${
|
|
498
|
+
selectedCategory === category
|
|
499
|
+
? "bg-purple-500 text-white shadow-lg shadow-purple-500/25"
|
|
500
|
+
: "bg-white/5 text-white/70 hover:bg-white/10 hover:text-white"
|
|
501
|
+
}`}
|
|
502
|
+
>
|
|
503
|
+
{category.charAt(0).toUpperCase() + category.slice(1)}
|
|
504
|
+
</button>
|
|
505
|
+
))}
|
|
506
|
+
</div>
|
|
507
|
+
|
|
508
|
+
<div className="relative">
|
|
509
|
+
<input
|
|
510
|
+
type="text"
|
|
511
|
+
placeholder="Search icons..."
|
|
512
|
+
value={searchTerm}
|
|
513
|
+
onChange={(e) => setSearchTerm(e.target.value)}
|
|
514
|
+
className="w-64 rounded-lg border border-white/10 bg-white/5 py-2 pr-10 pl-4 text-white placeholder-white/50 focus:border-purple-500/50 focus:ring-2 focus:ring-purple-500/50 focus:outline-none"
|
|
515
|
+
/>
|
|
516
|
+
<div className="absolute top-1/2 right-3 -translate-y-1/2 text-white/50">
|
|
517
|
+
{searchTerm ? (
|
|
518
|
+
<button
|
|
519
|
+
onClick={() => setSearchTerm("")}
|
|
520
|
+
className="hover:text-white"
|
|
521
|
+
>
|
|
522
|
+
<svg
|
|
523
|
+
className="h-4 w-4"
|
|
524
|
+
fill="none"
|
|
525
|
+
stroke="currentColor"
|
|
526
|
+
viewBox="0 0 24 24"
|
|
527
|
+
>
|
|
528
|
+
<path
|
|
529
|
+
strokeLinecap="round"
|
|
530
|
+
strokeLinejoin="round"
|
|
531
|
+
strokeWidth={2}
|
|
532
|
+
d="M6 18L18 6M6 6l12 12"
|
|
533
|
+
/>
|
|
534
|
+
</svg>
|
|
535
|
+
</button>
|
|
536
|
+
) : (
|
|
537
|
+
<svg
|
|
538
|
+
className="h-4 w-4"
|
|
539
|
+
fill="none"
|
|
540
|
+
stroke="currentColor"
|
|
541
|
+
viewBox="0 0 24 24"
|
|
542
|
+
>
|
|
543
|
+
<path
|
|
544
|
+
strokeLinecap="round"
|
|
545
|
+
strokeLinejoin="round"
|
|
546
|
+
strokeWidth={2}
|
|
547
|
+
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
|
|
548
|
+
/>
|
|
549
|
+
</svg>
|
|
550
|
+
)}
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
</div>
|
|
554
|
+
|
|
555
|
+
{/* Search Results Indicator */}
|
|
556
|
+
{searchTerm && (
|
|
557
|
+
<div className="mt-4 text-center">
|
|
558
|
+
<p className="text-sm text-white/70">
|
|
559
|
+
{filteredIcons.length > 0 ? (
|
|
560
|
+
<>
|
|
561
|
+
Found{" "}
|
|
562
|
+
<span className="font-medium text-purple-300">
|
|
563
|
+
{filteredIcons.length}
|
|
564
|
+
</span>{" "}
|
|
565
|
+
icons matching "{searchTerm}"
|
|
566
|
+
</>
|
|
567
|
+
) : (
|
|
568
|
+
<>
|
|
569
|
+
No icons found matching "
|
|
570
|
+
<span className="font-medium text-red-300">
|
|
571
|
+
{searchTerm}
|
|
572
|
+
</span>
|
|
573
|
+
"
|
|
574
|
+
</>
|
|
575
|
+
)}
|
|
576
|
+
</p>
|
|
577
|
+
</div>
|
|
578
|
+
)}
|
|
579
|
+
</div>
|
|
580
|
+
</div>
|
|
581
|
+
|
|
582
|
+
{/* Content */}
|
|
583
|
+
<div className="mx-auto max-w-7xl space-y-16 px-6 py-12">
|
|
584
|
+
{/* No Results Message */}
|
|
585
|
+
{searchTerm && filteredIcons.length === 0 && (
|
|
586
|
+
<div className="py-16 text-center">
|
|
587
|
+
<div className="mx-auto max-w-md space-y-4">
|
|
588
|
+
<div className="text-6xl">🔍</div>
|
|
589
|
+
<h3 className="text-xl font-medium text-white">No icons found</h3>
|
|
590
|
+
<p className="text-white/60">
|
|
591
|
+
Try searching for a different term or clear your search to see
|
|
592
|
+
all icons.
|
|
593
|
+
</p>
|
|
594
|
+
<button
|
|
595
|
+
onClick={() => setSearchTerm("")}
|
|
596
|
+
className="mt-4 rounded-full bg-purple-500 px-6 py-2 text-sm font-medium text-white transition-colors hover:bg-purple-600"
|
|
597
|
+
>
|
|
598
|
+
Clear Search
|
|
599
|
+
</button>
|
|
600
|
+
</div>
|
|
601
|
+
</div>
|
|
602
|
+
)}
|
|
603
|
+
|
|
604
|
+
{/* Show all icons when no category filter is applied and no search */}
|
|
605
|
+
{selectedCategory === "all" && !searchTerm && (
|
|
606
|
+
<IconCategory category="All Icons">
|
|
607
|
+
<IconGrid
|
|
608
|
+
title="Complete Icon Collection"
|
|
609
|
+
description={`Browse all ${totalIcons} icons in our library. Click any icon to see usage examples and copy code.`}
|
|
610
|
+
icons={allIcons}
|
|
611
|
+
onIconClick={handleIconClick}
|
|
612
|
+
/>
|
|
613
|
+
</IconCategory>
|
|
614
|
+
)}
|
|
615
|
+
|
|
616
|
+
{/* Show icons by category */}
|
|
617
|
+
{Object.entries(iconsByCategory).map(([category, icons]) => {
|
|
618
|
+
if (icons.length === 0) return null
|
|
619
|
+
|
|
620
|
+
const categoryDisplayName =
|
|
621
|
+
category.charAt(0).toUpperCase() + category.slice(1)
|
|
622
|
+
const categoryDescriptions: Record<string, string> = {
|
|
623
|
+
navigation:
|
|
624
|
+
"Icons for navigation, directional movement, and flow control.",
|
|
625
|
+
actions:
|
|
626
|
+
"Icons for user actions like adding, editing, deleting, and confirming.",
|
|
627
|
+
interface:
|
|
628
|
+
"Icons for interface elements like menus, search, and controls.",
|
|
629
|
+
content: "Icons for content types like files, images, and media.",
|
|
630
|
+
status: "Icons for states, alerts, and status indicators.",
|
|
631
|
+
social: "Icons for social features and sharing functionality.",
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
return (
|
|
635
|
+
<IconCategory
|
|
636
|
+
key={category}
|
|
637
|
+
category={`${categoryDisplayName} Icons`}
|
|
638
|
+
>
|
|
639
|
+
<IconGrid
|
|
640
|
+
title={`${categoryDisplayName} (${icons.length})`}
|
|
641
|
+
description={categoryDescriptions[category]}
|
|
642
|
+
icons={icons}
|
|
643
|
+
onIconClick={handleIconClick}
|
|
644
|
+
/>
|
|
645
|
+
</IconCategory>
|
|
646
|
+
)
|
|
647
|
+
})}
|
|
648
|
+
|
|
649
|
+
{/* Featured Icons Section - only show when no filters applied */}
|
|
650
|
+
{selectedCategory === "all" && !searchTerm && (
|
|
651
|
+
<IconCategory category="Featured Icons">
|
|
652
|
+
<div className="grid grid-cols-1 gap-8 lg:grid-cols-2">
|
|
653
|
+
{/* Most Used Icons */}
|
|
654
|
+
<div className="space-y-6">
|
|
655
|
+
<h3 className="text-xl font-bold text-white">Most Used</h3>
|
|
656
|
+
<div className="grid grid-cols-4 gap-4">
|
|
657
|
+
{allIcons
|
|
658
|
+
.filter((icon) =>
|
|
659
|
+
[
|
|
660
|
+
"ChevronRightIcon",
|
|
661
|
+
"ChevronLeftIcon",
|
|
662
|
+
"CrossIcon",
|
|
663
|
+
"TickIcon",
|
|
664
|
+
"SearchIcon",
|
|
665
|
+
"PlusIcon",
|
|
666
|
+
"EditIcon",
|
|
667
|
+
"TrashIcon",
|
|
668
|
+
].includes(icon.name)
|
|
669
|
+
)
|
|
670
|
+
.map(({ name, component: IconComponent }) => (
|
|
671
|
+
<div
|
|
672
|
+
key={name}
|
|
673
|
+
onClick={() => handleIconClick(name, IconComponent)}
|
|
674
|
+
className="group cursor-pointer rounded-lg border border-white/10 bg-white/5 p-4 text-center transition-all hover:scale-105 hover:bg-white/10"
|
|
675
|
+
>
|
|
676
|
+
<IconComponent className="mx-auto mb-2 h-8 w-8 text-white transition-colors group-hover:text-blue-400" />
|
|
677
|
+
<p className="text-xs text-white/70">
|
|
678
|
+
{name.replace("Icon", "")}
|
|
679
|
+
</p>
|
|
680
|
+
</div>
|
|
681
|
+
))}
|
|
682
|
+
</div>
|
|
683
|
+
</div>
|
|
684
|
+
|
|
685
|
+
{/* Recently Added */}
|
|
686
|
+
<div className="space-y-6">
|
|
687
|
+
<h3 className="text-xl font-bold text-white">Recently Added</h3>
|
|
688
|
+
<div className="grid grid-cols-4 gap-4">
|
|
689
|
+
{allIcons
|
|
690
|
+
.slice(-8)
|
|
691
|
+
.map(({ name, component: IconComponent }) => (
|
|
692
|
+
<div
|
|
693
|
+
key={name}
|
|
694
|
+
onClick={() => handleIconClick(name, IconComponent)}
|
|
695
|
+
className="group cursor-pointer rounded-lg border border-white/10 bg-white/5 p-4 text-center transition-all hover:scale-105 hover:bg-white/10"
|
|
696
|
+
>
|
|
697
|
+
<IconComponent className="mx-auto mb-2 h-8 w-8 text-white transition-colors group-hover:text-blue-400" />
|
|
698
|
+
<p className="text-xs text-white/70">
|
|
699
|
+
{name.replace("Icon", "")}
|
|
700
|
+
</p>
|
|
701
|
+
</div>
|
|
702
|
+
))}
|
|
703
|
+
</div>
|
|
704
|
+
</div>
|
|
705
|
+
</div>
|
|
706
|
+
</IconCategory>
|
|
707
|
+
)}
|
|
708
|
+
</div>
|
|
709
|
+
|
|
710
|
+
{/* Footer */}
|
|
711
|
+
<div className="border-t border-white/10 bg-black/20 backdrop-blur-xl">
|
|
712
|
+
<div className="mx-auto max-w-7xl px-6 py-8">
|
|
713
|
+
<div className="space-y-4 text-center">
|
|
714
|
+
<p className="text-white/60">
|
|
715
|
+
All icons are built with Radix UI's AccessibleIcon for screen
|
|
716
|
+
reader compatibility.
|
|
717
|
+
</p>
|
|
718
|
+
<p className="text-sm text-white/40">
|
|
719
|
+
Click any icon to see usage examples and copy implementation code.
|
|
720
|
+
</p>
|
|
721
|
+
</div>
|
|
722
|
+
</div>
|
|
723
|
+
</div>
|
|
724
|
+
|
|
725
|
+
{/* Usage Modal */}
|
|
726
|
+
{selectedIcon && (
|
|
727
|
+
<IconUsageModal
|
|
728
|
+
isOpen={!!selectedIcon}
|
|
729
|
+
onClose={() => setSelectedIcon(null)}
|
|
730
|
+
iconName={selectedIcon.name}
|
|
731
|
+
IconComponent={selectedIcon.component}
|
|
732
|
+
/>
|
|
733
|
+
)}
|
|
734
|
+
</div>
|
|
735
|
+
)
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
export default Icons
|