@umbra.ui/core 0.1.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/dist/components/controls/Dropdown/types.d.ts +5 -0
- package/dist/components/controls/Dropdown/types.d.ts.map +1 -0
- package/dist/components/controls/Dropdown/types.js +1 -0
- package/dist/components/controls/SegmentedControl/types.d.ts +6 -0
- package/dist/components/controls/SegmentedControl/types.d.ts.map +1 -0
- package/dist/components/controls/SegmentedControl/types.js +1 -0
- package/dist/components/dialogs/Alert/types.d.ts +7 -0
- package/dist/components/dialogs/Alert/types.d.ts.map +1 -0
- package/dist/components/dialogs/Alert/types.js +1 -0
- package/dist/components/dialogs/Toast/types.d.ts +34 -0
- package/dist/components/dialogs/Toast/types.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/types.js +10 -0
- package/dist/components/dialogs/Toast/useToast.d.ts +36 -0
- package/dist/components/dialogs/Toast/useToast.d.ts.map +1 -0
- package/dist/components/dialogs/Toast/useToast.js +90 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts +3 -0
- package/dist/components/indicators/Tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/tooltip.js +33 -0
- package/dist/components/indicators/Tooltip/types.d.ts +14 -0
- package/dist/components/indicators/Tooltip/types.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/types.js +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts +18 -0
- package/dist/components/indicators/Tooltip/useTooltip.d.ts.map +1 -0
- package/dist/components/indicators/Tooltip/useTooltip.js +57 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts +14 -0
- package/dist/components/inputs/Tags/tag-bar-styles.d.ts.map +1 -0
- package/dist/components/inputs/Tags/tag-bar-styles.js +313 -0
- package/dist/components/inputs/Tags/types.d.ts +93 -0
- package/dist/components/inputs/Tags/types.d.ts.map +1 -0
- package/dist/components/inputs/Tags/types.js +216 -0
- package/dist/components/inputs/search/types.d.ts +9 -0
- package/dist/components/inputs/search/types.d.ts.map +1 -0
- package/dist/components/inputs/search/types.js +1 -0
- package/dist/components/navigation/adaptive/types.d.ts +16 -0
- package/dist/components/navigation/adaptive/types.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/types.js +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts +27 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useAdaptiveLayout.js +40 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts +6 -0
- package/dist/components/navigation/adaptive/useBreakpoints.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useBreakpoints.js +37 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts +93 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useContainerMonitor.js +145 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts +31 -0
- package/dist/components/navigation/adaptive/useViewAnimation.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewAnimation.js +591 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts +52 -0
- package/dist/components/navigation/adaptive/useViewResize.d.ts.map +1 -0
- package/dist/components/navigation/adaptive/useViewResize.js +146 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts +25 -0
- package/dist/components/navigation/navstack/useNavigationStack.d.ts.map +1 -0
- package/dist/components/navigation/navstack/useNavigationStack.js +133 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts +20 -0
- package/dist/components/navigation/slideover/useSlideoverController.d.ts.map +1 -0
- package/dist/components/navigation/slideover/useSlideoverController.js +267 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts +20 -0
- package/dist/components/navigation/splitview/useSplitViewController.d.ts.map +1 -0
- package/dist/components/navigation/splitview/useSplitViewController.js +325 -0
- package/dist/components/navigation/tabcontroller/types.d.ts +21 -0
- package/dist/components/navigation/tabcontroller/types.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/types.js +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts +5 -0
- package/dist/components/navigation/tabcontroller/useTabController.d.ts.map +1 -0
- package/dist/components/navigation/tabcontroller/useTabController.js +10 -0
- package/dist/components/navigation/types.d.ts +8 -0
- package/dist/components/navigation/types.d.ts.map +1 -0
- package/dist/components/navigation/types.js +1 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts +11 -0
- package/dist/components/pickers/CollectionPicker/types.d.ts.map +1 -0
- package/dist/components/pickers/CollectionPicker/types.js +1 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts +13 -0
- package/dist/components/pickers/ColorPicker/colors.d.ts.map +1 -0
- package/dist/components/pickers/ColorPicker/colors.js +266 -0
- package/dist/components/pickers/FilePicker/types.d.ts +10 -0
- package/dist/components/pickers/FilePicker/types.d.ts.map +1 -0
- package/dist/components/pickers/FilePicker/types.js +1 -0
- package/dist/index.d.ts +91 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +196 -0
- package/dist/theme.d.ts +73 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +279 -0
- package/dist/themes/blank.d.ts +7 -0
- package/dist/themes/blank.d.ts.map +1 -0
- package/dist/themes/blank.js +543 -0
- package/dist/themes/crimson-dark.d.ts +4 -0
- package/dist/themes/crimson-dark.d.ts.map +1 -0
- package/dist/themes/crimson-dark.js +552 -0
- package/dist/themes/cyan-light.d.ts +4 -0
- package/dist/themes/cyan-light.d.ts.map +1 -0
- package/dist/themes/cyan-light.js +552 -0
- package/dist/themes/dark.d.ts +4 -0
- package/dist/themes/dark.d.ts.map +1 -0
- package/dist/themes/dark.js +551 -0
- package/dist/themes/gold-dark.d.ts +4 -0
- package/dist/themes/gold-dark.d.ts.map +1 -0
- package/dist/themes/gold-dark.js +552 -0
- package/dist/themes/grass-dark.d.ts +4 -0
- package/dist/themes/grass-dark.d.ts.map +1 -0
- package/dist/themes/grass-dark.js +552 -0
- package/dist/themes/indigo.d.ts +4 -0
- package/dist/themes/indigo.d.ts.map +1 -0
- package/dist/themes/indigo.js +552 -0
- package/dist/themes/light.d.ts +4 -0
- package/dist/themes/light.d.ts.map +1 -0
- package/dist/themes/light.js +551 -0
- package/dist/themes/orange-dark.d.ts +4 -0
- package/dist/themes/orange-dark.d.ts.map +1 -0
- package/dist/themes/orange-dark.js +551 -0
- package/dist/themes/orange-light.d.ts +4 -0
- package/dist/themes/orange-light.d.ts.map +1 -0
- package/dist/themes/orange-light.js +551 -0
- package/package.json +62 -0
- package/src/components/controls/Button/Button.vue +417 -0
- package/src/components/controls/Button/README.md +348 -0
- package/src/components/controls/Button/theme.css +200 -0
- package/src/components/controls/Checkbox/Checkbox.vue +164 -0
- package/src/components/controls/Checkbox/README.md +441 -0
- package/src/components/controls/Checkbox/theme.css +36 -0
- package/src/components/controls/Dropdown/Dropdown.vue +476 -0
- package/src/components/controls/Dropdown/README.md +370 -0
- package/src/components/controls/Dropdown/theme.css +50 -0
- package/src/components/controls/Dropdown/types.ts +6 -0
- package/src/components/controls/IconButton/IconButton.vue +267 -0
- package/src/components/controls/IconButton/README.md +502 -0
- package/src/components/controls/IconButton/theme.css +89 -0
- package/src/components/controls/Radio/README.md +591 -0
- package/src/components/controls/Radio/Radio.vue +89 -0
- package/src/components/controls/Radio/theme.css +14 -0
- package/src/components/controls/RangeSlider/README.md +608 -0
- package/src/components/controls/RangeSlider/RangeSlider.vue +535 -0
- package/src/components/controls/RangeSlider/theme.css +80 -0
- package/src/components/controls/SegmentedControl/README.md +587 -0
- package/src/components/controls/SegmentedControl/SegmentedControl.vue +284 -0
- package/src/components/controls/SegmentedControl/theme.css +60 -0
- package/src/components/controls/SegmentedControl/types.ts +5 -0
- package/src/components/controls/Slider/README.md +627 -0
- package/src/components/controls/Slider/Slider.vue +260 -0
- package/src/components/controls/Slider/theme.css +74 -0
- package/src/components/controls/Stepper/README.md +601 -0
- package/src/components/controls/Stepper/Stepper.vue +103 -0
- package/src/components/controls/Stepper/theme.css +53 -0
- package/src/components/controls/Switch/README.md +667 -0
- package/src/components/controls/Switch/Switch.vue +127 -0
- package/src/components/controls/Switch/theme.css +42 -0
- package/src/components/dialogs/Alert/Alert.vue +218 -0
- package/src/components/dialogs/Alert/README.md +450 -0
- package/src/components/dialogs/Alert/theme.css +44 -0
- package/src/components/dialogs/Alert/types.ts +11 -0
- package/src/components/dialogs/Toast/README.md +522 -0
- package/src/components/dialogs/Toast/Toast.vue +296 -0
- package/src/components/dialogs/Toast/ToastContainer.vue +330 -0
- package/src/components/dialogs/Toast/theme.css +44 -0
- package/src/components/dialogs/Toast/types.ts +46 -0
- package/src/components/dialogs/Toast/useToast.ts +127 -0
- package/src/components/indicators/ProgressBar/ProgressBar.vue +98 -0
- package/src/components/indicators/ProgressBar/README.md +744 -0
- package/src/components/indicators/ProgressBar/theme.css +36 -0
- package/src/components/indicators/Tooltip/README.md +723 -0
- package/src/components/indicators/Tooltip/TooltipProvider.vue +142 -0
- package/src/components/indicators/Tooltip/theme.css +18 -0
- package/src/components/indicators/Tooltip/tooltip.ts +48 -0
- package/src/components/indicators/Tooltip/types.ts +15 -0
- package/src/components/indicators/Tooltip/useTooltip.ts +71 -0
- package/src/components/inputs/AutogrowTextView/AutogrowTextView.vue +110 -0
- package/src/components/inputs/AutogrowTextView/README.md +643 -0
- package/src/components/inputs/AutogrowTextView/theme.css +28 -0
- package/src/components/inputs/InputCard/InputCard.vue +600 -0
- package/src/components/inputs/InputCard/README.md +636 -0
- package/src/components/inputs/InputEmail/InputEmail.vue +698 -0
- package/src/components/inputs/InputEmail/README.md +764 -0
- package/src/components/inputs/InputNumber/InputNumber.vue +300 -0
- package/src/components/inputs/InputNumber/README.md +749 -0
- package/src/components/inputs/InputPhone/InputPhone.vue +645 -0
- package/src/components/inputs/InputPhone/README.md +636 -0
- package/src/components/inputs/InputSecure/InputSecure.vue +646 -0
- package/src/components/inputs/InputSecure/README.md +771 -0
- package/src/components/inputs/InputText/InputText.vue +225 -0
- package/src/components/inputs/InputText/README.md +844 -0
- package/src/components/inputs/OTP/OTP.vue +349 -0
- package/src/components/inputs/OTP/README.md +736 -0
- package/src/components/inputs/OTP/theme.css +50 -0
- package/src/components/inputs/StringCapture/README.md +718 -0
- package/src/components/inputs/StringCapture/StringCapture.vue +315 -0
- package/src/components/inputs/StringCapture/theme.css +86 -0
- package/src/components/inputs/Tags/README.md +897 -0
- package/src/components/inputs/Tags/TagBar.vue +793 -0
- package/src/components/inputs/Tags/TagCreation.vue +219 -0
- package/src/components/inputs/Tags/TagPicker.vue +380 -0
- package/src/components/inputs/Tags/tag-bar-styles.ts +354 -0
- package/src/components/inputs/Tags/theme.css +121 -0
- package/src/components/inputs/Tags/types.ts +346 -0
- package/src/components/inputs/search/README.md +759 -0
- package/src/components/inputs/search/SearchBar.vue +394 -0
- package/src/components/inputs/search/SearchResults.vue +310 -0
- package/src/components/inputs/search/theme.css +187 -0
- package/src/components/inputs/search/types.ts +8 -0
- package/src/components/inputs/theme.css +102 -0
- package/src/components/menus/ActionMenu/ActionMenu.vue +383 -0
- package/src/components/menus/ActionMenu/README.md +825 -0
- package/src/components/menus/ActionMenu/theme.css +93 -0
- package/src/components/models/Popover/Popover.vue +551 -0
- package/src/components/models/Popover/README.md +885 -0
- package/src/components/models/Popover/theme.css +52 -0
- package/src/components/models/Sheet/README.md +1159 -0
- package/src/components/models/Sheet/Sheet.vue +465 -0
- package/src/components/models/Sheet/theme.css +72 -0
- package/src/components/models/Sidebar/README.md +1228 -0
- package/src/components/models/Sidebar/Sidebar.vue +480 -0
- package/src/components/models/Sidebar/theme.css +90 -0
- package/src/components/navigation/adaptive/AdaptiveLayout.vue +779 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutBreadcrumbs.vue +192 -0
- package/src/components/navigation/adaptive/AdaptiveLayoutMenuButton.vue +149 -0
- package/src/components/navigation/adaptive/README.md +768 -0
- package/src/components/navigation/adaptive/types.ts +19 -0
- package/src/components/navigation/adaptive/useAdaptiveLayout.ts +89 -0
- package/src/components/navigation/adaptive/useBreakpoints.ts +41 -0
- package/src/components/navigation/adaptive/useContainerMonitor.ts +214 -0
- package/src/components/navigation/adaptive/useViewAnimation.ts +721 -0
- package/src/components/navigation/adaptive/useViewResize.ts +211 -0
- package/src/components/navigation/navstack/NavigationStack.vue +180 -0
- package/src/components/navigation/navstack/README.md +994 -0
- package/src/components/navigation/navstack/useNavigationStack.ts +164 -0
- package/src/components/navigation/slideover/README.md +1275 -0
- package/src/components/navigation/slideover/SlideoverController.vue +287 -0
- package/src/components/navigation/slideover/useSlideoverController.ts +320 -0
- package/src/components/navigation/splitview/README.md +1115 -0
- package/src/components/navigation/splitview/SplitViewController.vue +176 -0
- package/src/components/navigation/splitview/useSplitViewController.ts +388 -0
- package/src/components/navigation/tabcontroller/README.md +919 -0
- package/src/components/navigation/tabcontroller/TabController.vue +307 -0
- package/src/components/navigation/tabcontroller/TabItem.vue +57 -0
- package/src/components/navigation/tabcontroller/types.ts +24 -0
- package/src/components/navigation/tabcontroller/useTabController.ts +18 -0
- package/src/components/navigation/theme.css +91 -0
- package/src/components/navigation/types.ts +7 -0
- package/src/components/pickers/CollectionPicker/CollectionPicker.vue +398 -0
- package/src/components/pickers/CollectionPicker/README.md +1115 -0
- package/src/components/pickers/CollectionPicker/theme.css +14 -0
- package/src/components/pickers/CollectionPicker/types.ts +11 -0
- package/src/components/pickers/ColorPicker/ColorPicker.vue +376 -0
- package/src/components/pickers/ColorPicker/README.md +1439 -0
- package/src/components/pickers/ColorPicker/colors.ts +299 -0
- package/src/components/pickers/ColorPicker/theme.css +32 -0
- package/src/components/pickers/DatePicker/DatePicker.vue +660 -0
- package/src/components/pickers/DatePicker/README.md +1195 -0
- package/src/components/pickers/DatePicker/theme.css +22 -0
- package/src/components/pickers/FilePicker/FilePicker.vue +534 -0
- package/src/components/pickers/FilePicker/README.md +1542 -0
- package/src/components/pickers/FilePicker/theme.css +48 -0
- package/src/components/pickers/FilePicker/types.ts +10 -0
- package/src/components/pickers/IconPicker/IconPicker.vue +327 -0
- package/src/components/pickers/IconPicker/README.md +1161 -0
- package/src/components/pickers/IconPicker/theme.css +28 -0
- package/src/components/pickers/theme.css +82 -0
- package/src/components/views/MarkdownViewer/MarkdownViewer.vue +442 -0
- package/src/components/views/MarkdownViewer/README.md +833 -0
- package/src/components/views/MarkdownViewer/theme.css +130 -0
- package/src/index.ts +263 -0
- package/src/theme.ts +378 -0
- package/src/themes/crimson-dark.ts +556 -0
- package/src/themes/cyan-light.ts +556 -0
- package/src/themes/dark.ts +557 -0
- package/src/themes/gold-dark.ts +556 -0
- package/src/themes/grass-dark.ts +556 -0
- package/src/themes/indigo.ts +556 -0
- package/src/themes/light.ts +557 -0
- package/src/themes/orange-dark.ts +557 -0
- package/src/themes/orange-light.ts +557 -0
- package/src/vue.d.ts +45 -0
|
@@ -0,0 +1,1161 @@
|
|
|
1
|
+
# IconPicker
|
|
2
|
+
|
|
3
|
+
A comprehensive icon picker component built with Vue 3 Composition API and TypeScript. The IconPicker provides an intuitive interface for selecting icons from the @umbra-ui/icons library with support for custom icon lists, smart positioning using Floating UI, and smooth animations.
|
|
4
|
+
|
|
5
|
+
## Installation/Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
9
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Dependencies:**
|
|
13
|
+
|
|
14
|
+
- Vue 3.x
|
|
15
|
+
- @floating-ui/vue (for positioning)
|
|
16
|
+
- @umbra-ui/icons (for icon library)
|
|
17
|
+
|
|
18
|
+
## Basic Usage
|
|
19
|
+
|
|
20
|
+
```vue
|
|
21
|
+
<script setup lang="ts">
|
|
22
|
+
import { ref } from "vue";
|
|
23
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
24
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
25
|
+
|
|
26
|
+
const selectedIcon = ref<IconKey>("home");
|
|
27
|
+
|
|
28
|
+
const handleIconChange = (icon: IconKey) => {
|
|
29
|
+
console.log("Selected icon:", icon);
|
|
30
|
+
};
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<div class="app">
|
|
35
|
+
<h2>Choose an Icon</h2>
|
|
36
|
+
|
|
37
|
+
<IconPicker v-model:icon="selectedIcon" @update:icon="handleIconChange" />
|
|
38
|
+
|
|
39
|
+
<div v-if="selectedIcon" class="icon-info">
|
|
40
|
+
<p>
|
|
41
|
+
Selected icon: <strong>{{ selectedIcon }}</strong>
|
|
42
|
+
</p>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<style module>
|
|
48
|
+
.app {
|
|
49
|
+
padding: 24px;
|
|
50
|
+
max-width: 400px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.icon-info {
|
|
54
|
+
margin-top: 20px;
|
|
55
|
+
padding: 16px;
|
|
56
|
+
background: #f8f9fa;
|
|
57
|
+
border-radius: 8px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.icon-info p {
|
|
61
|
+
margin: 0;
|
|
62
|
+
color: #495057;
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Props
|
|
68
|
+
|
|
69
|
+
| Prop Name | Type | Required | Default | Description |
|
|
70
|
+
| --------------- | ----------- | -------- | ----------- | ----------------------------------------- |
|
|
71
|
+
| `icon` | `string` | Yes | `""` | Currently selected icon key |
|
|
72
|
+
| `pickerOffsetX` | `number` | No | `0` | Horizontal offset for picker positioning |
|
|
73
|
+
| `preventPopup` | `boolean` | No | `false` | Whether to prevent the popup from opening |
|
|
74
|
+
| `iconList` | `IconKey[]` | No | `undefined` | Custom list of available icons |
|
|
75
|
+
| `iconSize` | `number` | No | `18` | Size of the displayed icon |
|
|
76
|
+
|
|
77
|
+
## Events
|
|
78
|
+
|
|
79
|
+
| Event Name | Payload Type | Description |
|
|
80
|
+
| ------------- | ------------ | -------------------------------- |
|
|
81
|
+
| `update:icon` | `string` | Emitted when an icon is selected |
|
|
82
|
+
|
|
83
|
+
## Available Icons
|
|
84
|
+
|
|
85
|
+
The IconPicker includes access to the complete @umbra-ui/icons library with over 250 icons across various categories:
|
|
86
|
+
|
|
87
|
+
### Icon Categories
|
|
88
|
+
|
|
89
|
+
- **Navigation**: home, search, menu, back, forward, etc.
|
|
90
|
+
- **Actions**: edit, delete, save, copy, paste, etc.
|
|
91
|
+
- **Communication**: mail, phone, message, notification, etc.
|
|
92
|
+
- **Media**: play, pause, stop, volume, image, video, etc.
|
|
93
|
+
- **Files**: folder, file, document, download, upload, etc.
|
|
94
|
+
- **Interface**: settings, user, lock, unlock, eye, etc.
|
|
95
|
+
- **Arrows**: up, down, left, right, chevron variants, etc.
|
|
96
|
+
- **Shapes**: circle, square, triangle, star, heart, etc.
|
|
97
|
+
|
|
98
|
+
### Accessing Icons
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { icons, type IconKey } from "@umbra-ui/icons";
|
|
102
|
+
|
|
103
|
+
// Get all available icon keys
|
|
104
|
+
const allIcons = Object.keys(icons) as IconKey[];
|
|
105
|
+
|
|
106
|
+
// Filter icons by category
|
|
107
|
+
const navigationIcons = allIcons.filter((key) =>
|
|
108
|
+
["home", "search", "menu", "back", "forward"].includes(key)
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
// Use specific icons
|
|
112
|
+
const homeIcon = icons.home;
|
|
113
|
+
const searchIcon = icons.search;
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## CSS Customization
|
|
117
|
+
|
|
118
|
+
### Layout Variables
|
|
119
|
+
|
|
120
|
+
```css
|
|
121
|
+
.icon-picker {
|
|
122
|
+
--picker-button-bg: #ffffff;
|
|
123
|
+
--picker-button-border: 1px solid #e9ecef;
|
|
124
|
+
--picker-button-hover-bg: #f8f9fa;
|
|
125
|
+
--picker-button-hover-border: 1px solid #dee2e6;
|
|
126
|
+
--picker-button-hover-shadow: rgba(0, 0, 0, 0.1);
|
|
127
|
+
--picker-button-hover-inset-shadow: rgba(255, 255, 255, 0.1);
|
|
128
|
+
--picker-picker-bg: #ffffff;
|
|
129
|
+
--picker-picker-border: 1px solid #e9ecef;
|
|
130
|
+
--picker-picker-shadow: rgba(0, 0, 0, 0.1);
|
|
131
|
+
--picker-picker-inset-shadow: rgba(255, 255, 255, 0.1);
|
|
132
|
+
--picker-selection-bar-bg: #f8f9fa;
|
|
133
|
+
--picker-selection-bar-text: #212529;
|
|
134
|
+
--picker-selection-bar-border: #e9ecef;
|
|
135
|
+
--picker-overlay-bg: rgba(0, 0, 0, 0.1);
|
|
136
|
+
--iconpicker-icon-cell-bg: #f3f4f6;
|
|
137
|
+
--iconpicker-icon-cell-border: #d1d5db;
|
|
138
|
+
--iconpicker-icon-cell-hover-bg: #e5e7eb;
|
|
139
|
+
--iconpicker-icon-cell-selected-bg: #acd8fc;
|
|
140
|
+
--iconpicker-icon-cell-selected-border: #5eb1ef;
|
|
141
|
+
--iconpicker-icon-color: #374151;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Container Styling
|
|
146
|
+
|
|
147
|
+
```css
|
|
148
|
+
.icon-picker {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
max-width: fit-content;
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Button Styling
|
|
157
|
+
|
|
158
|
+
```css
|
|
159
|
+
.icon-picker .button {
|
|
160
|
+
padding: 0.588rem;
|
|
161
|
+
border-radius: 0.353rem;
|
|
162
|
+
cursor: pointer;
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
justify-content: center;
|
|
166
|
+
gap: 0;
|
|
167
|
+
transition: all 0.3s ease;
|
|
168
|
+
background-color: var(--picker-button-bg);
|
|
169
|
+
border: var(--picker-button-border);
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
### Icon Grid Styling
|
|
174
|
+
|
|
175
|
+
```css
|
|
176
|
+
.icon-picker .icon_list {
|
|
177
|
+
display: grid;
|
|
178
|
+
grid-template-columns: repeat(7, 1fr);
|
|
179
|
+
gap: 0.588rem;
|
|
180
|
+
padding: 0.588rem;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.icon-picker .icon_cell {
|
|
184
|
+
width: 2rem;
|
|
185
|
+
height: 2rem;
|
|
186
|
+
border-radius: 0.353rem;
|
|
187
|
+
display: flex;
|
|
188
|
+
align-items: center;
|
|
189
|
+
justify-content: center;
|
|
190
|
+
background-color: var(--iconpicker-icon-cell-bg);
|
|
191
|
+
cursor: pointer;
|
|
192
|
+
transition: border 0.3s ease;
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Examples
|
|
197
|
+
|
|
198
|
+
### Navigation Icon Selector
|
|
199
|
+
|
|
200
|
+
```vue
|
|
201
|
+
<script setup lang="ts">
|
|
202
|
+
import { ref } from "vue";
|
|
203
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
204
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
205
|
+
|
|
206
|
+
const navigationIcons: IconKey[] = [
|
|
207
|
+
"home",
|
|
208
|
+
"search",
|
|
209
|
+
"menu",
|
|
210
|
+
"back",
|
|
211
|
+
"forward",
|
|
212
|
+
"up",
|
|
213
|
+
"down",
|
|
214
|
+
"left",
|
|
215
|
+
"right",
|
|
216
|
+
"chevron-up",
|
|
217
|
+
"chevron-down",
|
|
218
|
+
"chevron-left",
|
|
219
|
+
"chevron-right",
|
|
220
|
+
"arrow-up",
|
|
221
|
+
"arrow-down",
|
|
222
|
+
"arrow-left",
|
|
223
|
+
"arrow-right",
|
|
224
|
+
"external-link",
|
|
225
|
+
"link",
|
|
226
|
+
];
|
|
227
|
+
|
|
228
|
+
const selectedNavIcon = ref<IconKey>("home");
|
|
229
|
+
|
|
230
|
+
const handleNavIconChange = (icon: IconKey) => {
|
|
231
|
+
console.log("Navigation icon changed to:", icon);
|
|
232
|
+
};
|
|
233
|
+
</script>
|
|
234
|
+
|
|
235
|
+
<template>
|
|
236
|
+
<div class="navigation-selector">
|
|
237
|
+
<div class="selector-header">
|
|
238
|
+
<h3>Navigation Icon</h3>
|
|
239
|
+
<p>Choose an icon for your navigation menu</p>
|
|
240
|
+
</div>
|
|
241
|
+
|
|
242
|
+
<IconPicker
|
|
243
|
+
v-model:icon="selectedNavIcon"
|
|
244
|
+
:icon-list="navigationIcons"
|
|
245
|
+
:icon-size="20"
|
|
246
|
+
@update:icon="handleNavIconChange"
|
|
247
|
+
/>
|
|
248
|
+
|
|
249
|
+
<div class="icon-preview">
|
|
250
|
+
<h4>Preview</h4>
|
|
251
|
+
<div class="preview-nav">
|
|
252
|
+
<div class="nav-item">
|
|
253
|
+
<IconPicker
|
|
254
|
+
v-model:icon="selectedNavIcon"
|
|
255
|
+
:icon-list="navigationIcons"
|
|
256
|
+
:icon-size="16"
|
|
257
|
+
:prevent-popup="true"
|
|
258
|
+
/>
|
|
259
|
+
<span>Home</span>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</div>
|
|
263
|
+
</div>
|
|
264
|
+
</template>
|
|
265
|
+
|
|
266
|
+
<style module>
|
|
267
|
+
.navigation-selector {
|
|
268
|
+
padding: 24px;
|
|
269
|
+
max-width: 500px;
|
|
270
|
+
background: #ffffff;
|
|
271
|
+
border-radius: 12px;
|
|
272
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.selector-header {
|
|
276
|
+
margin-bottom: 24px;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
.selector-header h3 {
|
|
280
|
+
font-size: 24px;
|
|
281
|
+
font-weight: 600;
|
|
282
|
+
color: #1a202c;
|
|
283
|
+
margin: 0 0 8px 0;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.selector-header p {
|
|
287
|
+
color: #718096;
|
|
288
|
+
margin: 0;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.icon-preview {
|
|
292
|
+
margin-top: 32px;
|
|
293
|
+
padding-top: 24px;
|
|
294
|
+
border-top: 1px solid #e5e7eb;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
.icon-preview h4 {
|
|
298
|
+
font-size: 18px;
|
|
299
|
+
font-weight: 500;
|
|
300
|
+
color: #2d3748;
|
|
301
|
+
margin: 0 0 16px 0;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.preview-nav {
|
|
305
|
+
padding: 16px;
|
|
306
|
+
background: #f7fafc;
|
|
307
|
+
border-radius: 8px;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
.nav-item {
|
|
311
|
+
display: flex;
|
|
312
|
+
align-items: center;
|
|
313
|
+
gap: 12px;
|
|
314
|
+
padding: 8px 12px;
|
|
315
|
+
background: white;
|
|
316
|
+
border-radius: 6px;
|
|
317
|
+
border: 1px solid #e2e8f0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.nav-item span {
|
|
321
|
+
font-size: 14px;
|
|
322
|
+
font-weight: 500;
|
|
323
|
+
color: #374151;
|
|
324
|
+
}
|
|
325
|
+
</style>
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
### Action Icon Selector
|
|
329
|
+
|
|
330
|
+
```vue
|
|
331
|
+
<script setup lang="ts">
|
|
332
|
+
import { ref } from "vue";
|
|
333
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
334
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
335
|
+
|
|
336
|
+
const actionIcons: IconKey[] = [
|
|
337
|
+
"edit",
|
|
338
|
+
"delete",
|
|
339
|
+
"save",
|
|
340
|
+
"copy",
|
|
341
|
+
"paste",
|
|
342
|
+
"cut",
|
|
343
|
+
"undo",
|
|
344
|
+
"redo",
|
|
345
|
+
"plus",
|
|
346
|
+
"minus",
|
|
347
|
+
"check",
|
|
348
|
+
"x",
|
|
349
|
+
"trash",
|
|
350
|
+
"download",
|
|
351
|
+
"upload",
|
|
352
|
+
"refresh",
|
|
353
|
+
"reload",
|
|
354
|
+
"sync",
|
|
355
|
+
"settings",
|
|
356
|
+
"gear",
|
|
357
|
+
];
|
|
358
|
+
|
|
359
|
+
const selectedActionIcon = ref<IconKey>("edit");
|
|
360
|
+
|
|
361
|
+
const handleActionIconChange = (icon: IconKey) => {
|
|
362
|
+
console.log("Action icon changed to:", icon);
|
|
363
|
+
};
|
|
364
|
+
</script>
|
|
365
|
+
|
|
366
|
+
<template>
|
|
367
|
+
<div class="action-selector">
|
|
368
|
+
<div class="selector-header">
|
|
369
|
+
<h3>Action Icon</h3>
|
|
370
|
+
<p>Choose an icon for your action button</p>
|
|
371
|
+
</div>
|
|
372
|
+
|
|
373
|
+
<IconPicker
|
|
374
|
+
v-model:icon="selectedActionIcon"
|
|
375
|
+
:icon-list="actionIcons"
|
|
376
|
+
:icon-size="18"
|
|
377
|
+
@update:icon="handleActionIconChange"
|
|
378
|
+
/>
|
|
379
|
+
|
|
380
|
+
<div class="action-preview">
|
|
381
|
+
<h4>Button Preview</h4>
|
|
382
|
+
<div class="preview-buttons">
|
|
383
|
+
<button class="action-btn primary">
|
|
384
|
+
<IconPicker
|
|
385
|
+
v-model:icon="selectedActionIcon"
|
|
386
|
+
:icon-list="actionIcons"
|
|
387
|
+
:icon-size="16"
|
|
388
|
+
:prevent-popup="true"
|
|
389
|
+
/>
|
|
390
|
+
Action
|
|
391
|
+
</button>
|
|
392
|
+
<button class="action-btn secondary">
|
|
393
|
+
<IconPicker
|
|
394
|
+
v-model:icon="selectedActionIcon"
|
|
395
|
+
:icon-list="actionIcons"
|
|
396
|
+
:icon-size="16"
|
|
397
|
+
:prevent-popup="true"
|
|
398
|
+
/>
|
|
399
|
+
Secondary
|
|
400
|
+
</button>
|
|
401
|
+
</div>
|
|
402
|
+
</div>
|
|
403
|
+
</div>
|
|
404
|
+
</template>
|
|
405
|
+
|
|
406
|
+
<style module>
|
|
407
|
+
.action-selector {
|
|
408
|
+
padding: 24px;
|
|
409
|
+
max-width: 500px;
|
|
410
|
+
background: #ffffff;
|
|
411
|
+
border-radius: 12px;
|
|
412
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
.selector-header {
|
|
416
|
+
margin-bottom: 24px;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.selector-header h3 {
|
|
420
|
+
font-size: 24px;
|
|
421
|
+
font-weight: 600;
|
|
422
|
+
color: #1a202c;
|
|
423
|
+
margin: 0 0 8px 0;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
.selector-header p {
|
|
427
|
+
color: #718096;
|
|
428
|
+
margin: 0;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.action-preview {
|
|
432
|
+
margin-top: 32px;
|
|
433
|
+
padding-top: 24px;
|
|
434
|
+
border-top: 1px solid #e5e7eb;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
.action-preview h4 {
|
|
438
|
+
font-size: 18px;
|
|
439
|
+
font-weight: 500;
|
|
440
|
+
color: #2d3748;
|
|
441
|
+
margin: 0 0 16px 0;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.preview-buttons {
|
|
445
|
+
display: flex;
|
|
446
|
+
gap: 12px;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.action-btn {
|
|
450
|
+
display: flex;
|
|
451
|
+
align-items: center;
|
|
452
|
+
gap: 8px;
|
|
453
|
+
padding: 8px 16px;
|
|
454
|
+
border: none;
|
|
455
|
+
border-radius: 6px;
|
|
456
|
+
font-size: 14px;
|
|
457
|
+
font-weight: 500;
|
|
458
|
+
cursor: pointer;
|
|
459
|
+
transition: all 0.2s ease;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.action-btn.primary {
|
|
463
|
+
background: #3b82f6;
|
|
464
|
+
color: white;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
.action-btn.primary:hover {
|
|
468
|
+
background: #2563eb;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.action-btn.secondary {
|
|
472
|
+
background: #f3f4f6;
|
|
473
|
+
color: #374151;
|
|
474
|
+
border: 1px solid #d1d5db;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.action-btn.secondary:hover {
|
|
478
|
+
background: #e5e7eb;
|
|
479
|
+
}
|
|
480
|
+
</style>
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
### Media Icon Selector
|
|
484
|
+
|
|
485
|
+
```vue
|
|
486
|
+
<script setup lang="ts">
|
|
487
|
+
import { ref } from "vue";
|
|
488
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
489
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
490
|
+
|
|
491
|
+
const mediaIcons: IconKey[] = [
|
|
492
|
+
"play",
|
|
493
|
+
"pause",
|
|
494
|
+
"stop",
|
|
495
|
+
"skip-back",
|
|
496
|
+
"skip-forward",
|
|
497
|
+
"volume-high",
|
|
498
|
+
"volume-low",
|
|
499
|
+
"volume-mute",
|
|
500
|
+
"image",
|
|
501
|
+
"video",
|
|
502
|
+
"camera",
|
|
503
|
+
"microphone",
|
|
504
|
+
"headphones",
|
|
505
|
+
"speaker",
|
|
506
|
+
"music",
|
|
507
|
+
"film",
|
|
508
|
+
"tv",
|
|
509
|
+
"radio",
|
|
510
|
+
];
|
|
511
|
+
|
|
512
|
+
const selectedMediaIcon = ref<IconKey>("play");
|
|
513
|
+
|
|
514
|
+
const handleMediaIconChange = (icon: IconKey) => {
|
|
515
|
+
console.log("Media icon changed to:", icon);
|
|
516
|
+
};
|
|
517
|
+
</script>
|
|
518
|
+
|
|
519
|
+
<template>
|
|
520
|
+
<div class="media-selector">
|
|
521
|
+
<div class="selector-header">
|
|
522
|
+
<h3>Media Icon</h3>
|
|
523
|
+
<p>Choose an icon for your media controls</p>
|
|
524
|
+
</div>
|
|
525
|
+
|
|
526
|
+
<IconPicker
|
|
527
|
+
v-model:icon="selectedMediaIcon"
|
|
528
|
+
:icon-list="mediaIcons"
|
|
529
|
+
:icon-size="22"
|
|
530
|
+
@update:icon="handleMediaIconChange"
|
|
531
|
+
/>
|
|
532
|
+
|
|
533
|
+
<div class="media-preview">
|
|
534
|
+
<h4>Media Player Preview</h4>
|
|
535
|
+
<div class="preview-player">
|
|
536
|
+
<div class="player-controls">
|
|
537
|
+
<button class="control-btn">
|
|
538
|
+
<IconPicker
|
|
539
|
+
v-model:icon="selectedMediaIcon"
|
|
540
|
+
:icon-list="mediaIcons"
|
|
541
|
+
:icon-size="20"
|
|
542
|
+
:prevent-popup="true"
|
|
543
|
+
/>
|
|
544
|
+
</button>
|
|
545
|
+
<div class="progress-bar">
|
|
546
|
+
<div class="progress-fill"></div>
|
|
547
|
+
</div>
|
|
548
|
+
<div class="time-display">2:34 / 4:12</div>
|
|
549
|
+
</div>
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
</template>
|
|
554
|
+
|
|
555
|
+
<style module>
|
|
556
|
+
.media-selector {
|
|
557
|
+
padding: 24px;
|
|
558
|
+
max-width: 500px;
|
|
559
|
+
background: #ffffff;
|
|
560
|
+
border-radius: 12px;
|
|
561
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.selector-header {
|
|
565
|
+
margin-bottom: 24px;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.selector-header h3 {
|
|
569
|
+
font-size: 24px;
|
|
570
|
+
font-weight: 600;
|
|
571
|
+
color: #1a202c;
|
|
572
|
+
margin: 0 0 8px 0;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.selector-header p {
|
|
576
|
+
color: #718096;
|
|
577
|
+
margin: 0;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.media-preview {
|
|
581
|
+
margin-top: 32px;
|
|
582
|
+
padding-top: 24px;
|
|
583
|
+
border-top: 1px solid #e5e7eb;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.media-preview h4 {
|
|
587
|
+
font-size: 18px;
|
|
588
|
+
font-weight: 500;
|
|
589
|
+
color: #2d3748;
|
|
590
|
+
margin: 0 0 16px 0;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
.preview-player {
|
|
594
|
+
padding: 20px;
|
|
595
|
+
background: #1f2937;
|
|
596
|
+
border-radius: 8px;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.player-controls {
|
|
600
|
+
display: flex;
|
|
601
|
+
align-items: center;
|
|
602
|
+
gap: 16px;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.control-btn {
|
|
606
|
+
width: 40px;
|
|
607
|
+
height: 40px;
|
|
608
|
+
background: #3b82f6;
|
|
609
|
+
color: white;
|
|
610
|
+
border: none;
|
|
611
|
+
border-radius: 50%;
|
|
612
|
+
display: flex;
|
|
613
|
+
align-items: center;
|
|
614
|
+
justify-content: center;
|
|
615
|
+
cursor: pointer;
|
|
616
|
+
transition: background 0.2s ease;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.control-btn:hover {
|
|
620
|
+
background: #2563eb;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.progress-bar {
|
|
624
|
+
flex: 1;
|
|
625
|
+
height: 4px;
|
|
626
|
+
background: #374151;
|
|
627
|
+
border-radius: 2px;
|
|
628
|
+
overflow: hidden;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.progress-fill {
|
|
632
|
+
width: 60%;
|
|
633
|
+
height: 100%;
|
|
634
|
+
background: #3b82f6;
|
|
635
|
+
border-radius: 2px;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
.time-display {
|
|
639
|
+
color: #9ca3af;
|
|
640
|
+
font-size: 12px;
|
|
641
|
+
font-weight: 500;
|
|
642
|
+
min-width: 60px;
|
|
643
|
+
text-align: right;
|
|
644
|
+
}
|
|
645
|
+
</style>
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
### Custom Icon Set
|
|
649
|
+
|
|
650
|
+
```vue
|
|
651
|
+
<script setup lang="ts">
|
|
652
|
+
import { ref } from "vue";
|
|
653
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
654
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
655
|
+
|
|
656
|
+
const customIcons: IconKey[] = [
|
|
657
|
+
"star",
|
|
658
|
+
"heart",
|
|
659
|
+
"thumbs-up",
|
|
660
|
+
"thumbs-down",
|
|
661
|
+
"bookmark",
|
|
662
|
+
"flag",
|
|
663
|
+
"bell",
|
|
664
|
+
"mail",
|
|
665
|
+
"phone",
|
|
666
|
+
"message",
|
|
667
|
+
"chat",
|
|
668
|
+
"comment",
|
|
669
|
+
"user",
|
|
670
|
+
"users",
|
|
671
|
+
"user-plus",
|
|
672
|
+
"user-minus",
|
|
673
|
+
"shield",
|
|
674
|
+
"lock",
|
|
675
|
+
];
|
|
676
|
+
|
|
677
|
+
const selectedCustomIcon = ref<IconKey>("star");
|
|
678
|
+
|
|
679
|
+
const handleCustomIconChange = (icon: IconKey) => {
|
|
680
|
+
console.log("Custom icon changed to:", icon);
|
|
681
|
+
};
|
|
682
|
+
|
|
683
|
+
const addToFavorites = () => {
|
|
684
|
+
console.log("Added to favorites with icon:", selectedCustomIcon.value);
|
|
685
|
+
};
|
|
686
|
+
|
|
687
|
+
const shareContent = () => {
|
|
688
|
+
console.log("Shared content with icon:", selectedCustomIcon.value);
|
|
689
|
+
};
|
|
690
|
+
</script>
|
|
691
|
+
|
|
692
|
+
<template>
|
|
693
|
+
<div class="custom-icon-selector">
|
|
694
|
+
<div class="selector-header">
|
|
695
|
+
<h3>Custom Icon Set</h3>
|
|
696
|
+
<p>Choose from a curated set of social and interaction icons</p>
|
|
697
|
+
</div>
|
|
698
|
+
|
|
699
|
+
<IconPicker
|
|
700
|
+
v-model:icon="selectedCustomIcon"
|
|
701
|
+
:icon-list="customIcons"
|
|
702
|
+
:icon-size="20"
|
|
703
|
+
@update:icon="handleCustomIconChange"
|
|
704
|
+
/>
|
|
705
|
+
|
|
706
|
+
<div class="custom-preview">
|
|
707
|
+
<h4>Interactive Elements</h4>
|
|
708
|
+
<div class="preview-elements">
|
|
709
|
+
<button class="interactive-btn" @click="addToFavorites">
|
|
710
|
+
<IconPicker
|
|
711
|
+
v-model:icon="selectedCustomIcon"
|
|
712
|
+
:icon-list="customIcons"
|
|
713
|
+
:icon-size="16"
|
|
714
|
+
:prevent-popup="true"
|
|
715
|
+
/>
|
|
716
|
+
Add to Favorites
|
|
717
|
+
</button>
|
|
718
|
+
|
|
719
|
+
<button class="interactive-btn" @click="shareContent">
|
|
720
|
+
<IconPicker
|
|
721
|
+
v-model:icon="selectedCustomIcon"
|
|
722
|
+
:icon-list="customIcons"
|
|
723
|
+
:icon-size="16"
|
|
724
|
+
:prevent-popup="true"
|
|
725
|
+
/>
|
|
726
|
+
Share
|
|
727
|
+
</button>
|
|
728
|
+
|
|
729
|
+
<div class="social-stats">
|
|
730
|
+
<div class="stat-item">
|
|
731
|
+
<IconPicker
|
|
732
|
+
v-model:icon="selectedCustomIcon"
|
|
733
|
+
:icon-list="customIcons"
|
|
734
|
+
:icon-size="14"
|
|
735
|
+
:prevent-popup="true"
|
|
736
|
+
/>
|
|
737
|
+
<span>1.2k</span>
|
|
738
|
+
</div>
|
|
739
|
+
</div>
|
|
740
|
+
</div>
|
|
741
|
+
</div>
|
|
742
|
+
</div>
|
|
743
|
+
</template>
|
|
744
|
+
|
|
745
|
+
<style module>
|
|
746
|
+
.custom-icon-selector {
|
|
747
|
+
padding: 24px;
|
|
748
|
+
max-width: 600px;
|
|
749
|
+
background: #ffffff;
|
|
750
|
+
border-radius: 12px;
|
|
751
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.selector-header {
|
|
755
|
+
margin-bottom: 24px;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
.selector-header h3 {
|
|
759
|
+
font-size: 24px;
|
|
760
|
+
font-weight: 600;
|
|
761
|
+
color: #1a202c;
|
|
762
|
+
margin: 0 0 8px 0;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
.selector-header p {
|
|
766
|
+
color: #718096;
|
|
767
|
+
margin: 0;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.custom-preview {
|
|
771
|
+
margin-top: 32px;
|
|
772
|
+
padding-top: 24px;
|
|
773
|
+
border-top: 1px solid #e5e7eb;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
.custom-preview h4 {
|
|
777
|
+
font-size: 18px;
|
|
778
|
+
font-weight: 500;
|
|
779
|
+
color: #2d3748;
|
|
780
|
+
margin: 0 0 16px 0;
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
.preview-elements {
|
|
784
|
+
display: flex;
|
|
785
|
+
flex-direction: column;
|
|
786
|
+
gap: 16px;
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
.interactive-btn {
|
|
790
|
+
display: flex;
|
|
791
|
+
align-items: center;
|
|
792
|
+
gap: 8px;
|
|
793
|
+
padding: 12px 16px;
|
|
794
|
+
background: #f8fafc;
|
|
795
|
+
border: 1px solid #e2e8f0;
|
|
796
|
+
border-radius: 8px;
|
|
797
|
+
font-size: 14px;
|
|
798
|
+
font-weight: 500;
|
|
799
|
+
color: #374151;
|
|
800
|
+
cursor: pointer;
|
|
801
|
+
transition: all 0.2s ease;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.interactive-btn:hover {
|
|
805
|
+
background: #f1f5f9;
|
|
806
|
+
border-color: #cbd5e1;
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
.social-stats {
|
|
810
|
+
display: flex;
|
|
811
|
+
gap: 16px;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
.stat-item {
|
|
815
|
+
display: flex;
|
|
816
|
+
align-items: center;
|
|
817
|
+
gap: 6px;
|
|
818
|
+
padding: 8px 12px;
|
|
819
|
+
background: #fef3c7;
|
|
820
|
+
border-radius: 6px;
|
|
821
|
+
font-size: 12px;
|
|
822
|
+
font-weight: 600;
|
|
823
|
+
color: #92400e;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.stat-item span {
|
|
827
|
+
font-size: 14px;
|
|
828
|
+
}
|
|
829
|
+
</style>
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
### Disabled State Example
|
|
833
|
+
|
|
834
|
+
```vue
|
|
835
|
+
<script setup lang="ts">
|
|
836
|
+
import { ref } from "vue";
|
|
837
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
838
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
839
|
+
|
|
840
|
+
const selectedIcon = ref<IconKey>("home");
|
|
841
|
+
const isDisabled = ref(false);
|
|
842
|
+
|
|
843
|
+
const toggleDisabled = () => {
|
|
844
|
+
isDisabled.value = !isDisabled.value;
|
|
845
|
+
};
|
|
846
|
+
|
|
847
|
+
const handleIconChange = (icon: IconKey) => {
|
|
848
|
+
console.log("Icon changed to:", icon);
|
|
849
|
+
};
|
|
850
|
+
</script>
|
|
851
|
+
|
|
852
|
+
<template>
|
|
853
|
+
<div class="disabled-example">
|
|
854
|
+
<h3>Disabled State</h3>
|
|
855
|
+
|
|
856
|
+
<div class="controls">
|
|
857
|
+
<button @click="toggleDisabled" class="toggle-btn">
|
|
858
|
+
{{ isDisabled ? "Enable" : "Disable" }} Icon Picker
|
|
859
|
+
</button>
|
|
860
|
+
</div>
|
|
861
|
+
|
|
862
|
+
<IconPicker
|
|
863
|
+
v-model:icon="selectedIcon"
|
|
864
|
+
:prevent-popup="isDisabled"
|
|
865
|
+
:icon-size="20"
|
|
866
|
+
@update:icon="handleIconChange"
|
|
867
|
+
/>
|
|
868
|
+
|
|
869
|
+
<div class="status">
|
|
870
|
+
<p>Status: {{ isDisabled ? "Disabled" : "Enabled" }}</p>
|
|
871
|
+
<p>Selected: {{ selectedIcon || "None" }}</p>
|
|
872
|
+
</div>
|
|
873
|
+
</div>
|
|
874
|
+
</template>
|
|
875
|
+
|
|
876
|
+
<style module>
|
|
877
|
+
.disabled-example {
|
|
878
|
+
padding: 24px;
|
|
879
|
+
max-width: 400px;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
.controls {
|
|
883
|
+
margin-bottom: 20px;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
.toggle-btn {
|
|
887
|
+
padding: 8px 16px;
|
|
888
|
+
background: #4299e1;
|
|
889
|
+
color: white;
|
|
890
|
+
border: none;
|
|
891
|
+
border-radius: 6px;
|
|
892
|
+
cursor: pointer;
|
|
893
|
+
font-weight: 500;
|
|
894
|
+
transition: background 0.2s ease;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
.toggle-btn:hover {
|
|
898
|
+
background: #3182ce;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
.status {
|
|
902
|
+
margin-top: 20px;
|
|
903
|
+
padding: 16px;
|
|
904
|
+
background: #f7fafc;
|
|
905
|
+
border-radius: 8px;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
.status p {
|
|
909
|
+
margin: 0 0 8px 0;
|
|
910
|
+
color: #4a5568;
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
.status p:last-child {
|
|
914
|
+
margin-bottom: 0;
|
|
915
|
+
}
|
|
916
|
+
</style>
|
|
917
|
+
```
|
|
918
|
+
|
|
919
|
+
## Advanced Usage
|
|
920
|
+
|
|
921
|
+
### Dynamic Icon Filtering
|
|
922
|
+
|
|
923
|
+
```vue
|
|
924
|
+
<script setup lang="ts">
|
|
925
|
+
import { ref, computed } from "vue";
|
|
926
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
927
|
+
import type { IconKey } from "@umbra-ui/icons";
|
|
928
|
+
import { icons } from "@umbra-ui/icons";
|
|
929
|
+
|
|
930
|
+
const searchQuery = ref("");
|
|
931
|
+
const selectedIcon = ref<IconKey>("home");
|
|
932
|
+
|
|
933
|
+
const allIcons = Object.keys(icons) as IconKey[];
|
|
934
|
+
|
|
935
|
+
const filteredIcons = computed(() => {
|
|
936
|
+
if (!searchQuery.value) return allIcons;
|
|
937
|
+
|
|
938
|
+
return allIcons.filter((iconKey) =>
|
|
939
|
+
iconKey.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
940
|
+
);
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
const handleIconChange = (icon: IconKey) => {
|
|
944
|
+
selectedIcon.value = icon;
|
|
945
|
+
console.log("Selected icon:", icon);
|
|
946
|
+
};
|
|
947
|
+
|
|
948
|
+
const clearSearch = () => {
|
|
949
|
+
searchQuery.value = "";
|
|
950
|
+
};
|
|
951
|
+
</script>
|
|
952
|
+
|
|
953
|
+
<template>
|
|
954
|
+
<div class="dynamic-filtering">
|
|
955
|
+
<h3>Dynamic Icon Filtering</h3>
|
|
956
|
+
|
|
957
|
+
<div class="search-section">
|
|
958
|
+
<div class="search-input">
|
|
959
|
+
<input
|
|
960
|
+
v-model="searchQuery"
|
|
961
|
+
type="text"
|
|
962
|
+
placeholder="Search icons..."
|
|
963
|
+
class="search-field"
|
|
964
|
+
/>
|
|
965
|
+
<button @click="clearSearch" class="clear-btn">×</button>
|
|
966
|
+
</div>
|
|
967
|
+
<p class="search-results">{{ filteredIcons.length }} icons found</p>
|
|
968
|
+
</div>
|
|
969
|
+
|
|
970
|
+
<IconPicker
|
|
971
|
+
v-model:icon="selectedIcon"
|
|
972
|
+
:icon-list="filteredIcons"
|
|
973
|
+
:icon-size="18"
|
|
974
|
+
@update:icon="handleIconChange"
|
|
975
|
+
/>
|
|
976
|
+
|
|
977
|
+
<div class="icon-info">
|
|
978
|
+
<h4>Selected Icon</h4>
|
|
979
|
+
<div class="icon-display">
|
|
980
|
+
<IconPicker
|
|
981
|
+
v-model:icon="selectedIcon"
|
|
982
|
+
:icon-list="filteredIcons"
|
|
983
|
+
:icon-size="32"
|
|
984
|
+
:prevent-popup="true"
|
|
985
|
+
/>
|
|
986
|
+
<div class="icon-details">
|
|
987
|
+
<p class="icon-name">{{ selectedIcon }}</p>
|
|
988
|
+
<p class="icon-category">
|
|
989
|
+
Category: {{ getIconCategory(selectedIcon) }}
|
|
990
|
+
</p>
|
|
991
|
+
</div>
|
|
992
|
+
</div>
|
|
993
|
+
</div>
|
|
994
|
+
</div>
|
|
995
|
+
</template>
|
|
996
|
+
|
|
997
|
+
<style module>
|
|
998
|
+
.dynamic-filtering {
|
|
999
|
+
padding: 24px;
|
|
1000
|
+
max-width: 600px;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.search-section {
|
|
1004
|
+
margin-bottom: 24px;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
.search-input {
|
|
1008
|
+
position: relative;
|
|
1009
|
+
margin-bottom: 8px;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
.search-field {
|
|
1013
|
+
width: 100%;
|
|
1014
|
+
padding: 12px 40px 12px 12px;
|
|
1015
|
+
border: 1px solid #d1d5db;
|
|
1016
|
+
border-radius: 6px;
|
|
1017
|
+
font-size: 14px;
|
|
1018
|
+
transition: border-color 0.2s ease;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
.search-field:focus {
|
|
1022
|
+
outline: none;
|
|
1023
|
+
border-color: #3b82f6;
|
|
1024
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.clear-btn {
|
|
1028
|
+
position: absolute;
|
|
1029
|
+
right: 8px;
|
|
1030
|
+
top: 50%;
|
|
1031
|
+
transform: translateY(-50%);
|
|
1032
|
+
width: 24px;
|
|
1033
|
+
height: 24px;
|
|
1034
|
+
background: #6b7280;
|
|
1035
|
+
color: white;
|
|
1036
|
+
border: none;
|
|
1037
|
+
border-radius: 50%;
|
|
1038
|
+
font-size: 16px;
|
|
1039
|
+
font-weight: bold;
|
|
1040
|
+
cursor: pointer;
|
|
1041
|
+
display: flex;
|
|
1042
|
+
align-items: center;
|
|
1043
|
+
justify-content: center;
|
|
1044
|
+
transition: background 0.2s ease;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.clear-btn:hover {
|
|
1048
|
+
background: #4b5563;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.search-results {
|
|
1052
|
+
color: #6b7280;
|
|
1053
|
+
font-size: 12px;
|
|
1054
|
+
margin: 0;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
.icon-info {
|
|
1058
|
+
margin-top: 32px;
|
|
1059
|
+
padding-top: 24px;
|
|
1060
|
+
border-top: 1px solid #e5e7eb;
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
.icon-info h4 {
|
|
1064
|
+
font-size: 18px;
|
|
1065
|
+
font-weight: 500;
|
|
1066
|
+
color: #2d3748;
|
|
1067
|
+
margin: 0 0 16px 0;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.icon-display {
|
|
1071
|
+
display: flex;
|
|
1072
|
+
align-items: center;
|
|
1073
|
+
gap: 16px;
|
|
1074
|
+
padding: 20px;
|
|
1075
|
+
background: #f9fafb;
|
|
1076
|
+
border-radius: 8px;
|
|
1077
|
+
border: 1px solid #e5e7eb;
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
.icon-details {
|
|
1081
|
+
flex: 1;
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
.icon-name {
|
|
1085
|
+
font-size: 16px;
|
|
1086
|
+
font-weight: 600;
|
|
1087
|
+
color: #374151;
|
|
1088
|
+
margin: 0 0 4px 0;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1091
|
+
.icon-category {
|
|
1092
|
+
font-size: 14px;
|
|
1093
|
+
color: #6b7280;
|
|
1094
|
+
margin: 0;
|
|
1095
|
+
}
|
|
1096
|
+
</style>
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
## Performance Considerations
|
|
1100
|
+
|
|
1101
|
+
- **Floating UI**: Smart positioning with automatic updates and cleanup
|
|
1102
|
+
- **Teleport**: Overlay and picker are teleported to body for proper z-index management
|
|
1103
|
+
- **Event Cleanup**: Proper cleanup of auto-update listeners on unmount
|
|
1104
|
+
- **Icon Filtering**: Efficient filtering of animated icons from the default list
|
|
1105
|
+
- **Computed Properties**: Reactive icon list computation for optimal performance
|
|
1106
|
+
|
|
1107
|
+
## Accessibility
|
|
1108
|
+
|
|
1109
|
+
- **Keyboard Navigation**: Support for keyboard interaction
|
|
1110
|
+
- **Screen Reader Support**: Proper ARIA labels and semantic structure
|
|
1111
|
+
- **Focus Management**: Focus is properly managed during interactions
|
|
1112
|
+
- **Icon Information**: Displays icon names for screen readers
|
|
1113
|
+
- **High Contrast**: Supports high contrast mode with appropriate styling
|
|
1114
|
+
|
|
1115
|
+
## Browser Support
|
|
1116
|
+
|
|
1117
|
+
- **Modern Browsers**: Chrome 88+, Firefox 85+, Safari 14+, Edge 88+
|
|
1118
|
+
- **Mobile Browsers**: iOS Safari 14+, Chrome Mobile 88+
|
|
1119
|
+
- **CSS Features**: Uses CSS Grid and modern layout features
|
|
1120
|
+
- **JavaScript**: Requires ES2020+ support
|
|
1121
|
+
|
|
1122
|
+
## Troubleshooting
|
|
1123
|
+
|
|
1124
|
+
### Common Issues
|
|
1125
|
+
|
|
1126
|
+
1. **Icons not displaying**: Check that @umbra-ui/icons is properly installed
|
|
1127
|
+
2. **Picker not positioning correctly**: Ensure the trigger button has proper positioning context
|
|
1128
|
+
3. **Icon not updating**: Verify the v-model binding is correctly set up
|
|
1129
|
+
4. **Custom icon list not working**: Ensure the iconList prop contains valid IconKey values
|
|
1130
|
+
|
|
1131
|
+
### Debug Mode
|
|
1132
|
+
|
|
1133
|
+
```vue
|
|
1134
|
+
<script setup lang="ts">
|
|
1135
|
+
import { ref, watch } from "vue";
|
|
1136
|
+
import { IconPicker } from "@umbra-ui/core";
|
|
1137
|
+
|
|
1138
|
+
const selectedIcon = ref("");
|
|
1139
|
+
|
|
1140
|
+
// Watch for changes
|
|
1141
|
+
watch(selectedIcon, (newIcon) => {
|
|
1142
|
+
console.log("Selected icon changed:", newIcon);
|
|
1143
|
+
});
|
|
1144
|
+
</script>
|
|
1145
|
+
```
|
|
1146
|
+
|
|
1147
|
+
## Migration Guide
|
|
1148
|
+
|
|
1149
|
+
### From v1 to v2
|
|
1150
|
+
|
|
1151
|
+
- `v-model` prop is now `v-model:icon`
|
|
1152
|
+
- Event names have been updated to use kebab-case
|
|
1153
|
+
- Icon system has been updated to use @umbra-ui/icons
|
|
1154
|
+
- Floating UI integration has been improved
|
|
1155
|
+
|
|
1156
|
+
### Breaking Changes
|
|
1157
|
+
|
|
1158
|
+
- Removed `value` prop in favor of `v-model:icon`
|
|
1159
|
+
- Changed event names from camelCase to kebab-case
|
|
1160
|
+
- Updated icon prop to use string keys instead of components
|
|
1161
|
+
- Modified CSS class naming convention
|