@umbra.ui/core 0.3.0 → 0.4.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.
Files changed (61) hide show
  1. package/dist/components/controls/InlineDropdown/InlineDropdown.vue +290 -0
  2. package/dist/components/controls/InlineDropdown/README.md +35 -0
  3. package/dist/components/controls/InlineDropdown/theme.css +40 -0
  4. package/dist/components/dialogs/Alert/Alert.vue +122 -11
  5. package/dist/components/dialogs/Alert/theme.css +20 -0
  6. package/dist/components/dialogs/Toast/useToast.d.ts +1 -1
  7. package/dist/components/inputs/AutogrowRichTextView/AutogrowRichTextView.vue +128 -0
  8. package/dist/components/inputs/AutogrowRichTextView/README.md +86 -0
  9. package/dist/components/inputs/AutogrowRichTextView/editor.css +211 -0
  10. package/dist/components/inputs/AutogrowRichTextView/theme.css +28 -0
  11. package/dist/components/inputs/InputCryptoAddress/InputCryptoAddress.vue +512 -0
  12. package/dist/components/inputs/InputCryptoAddress/README.md +45 -0
  13. package/dist/components/inputs/InputCryptoAddress/theme.css +80 -0
  14. package/dist/components/inputs/Tags/TagBar.vue +7 -4
  15. package/dist/components/inputs/Tags/theme.css +4 -0
  16. package/dist/components/inputs/search/README.md +64 -736
  17. package/dist/components/inputs/search/SearchOverlay.vue +376 -0
  18. package/dist/components/inputs/search/SearchResultCell.vue +205 -0
  19. package/dist/components/inputs/search/theme.css +66 -21
  20. package/dist/components/inputs/search/types.d.ts +27 -5
  21. package/dist/components/inputs/search/types.d.ts.map +1 -1
  22. package/dist/components/inputs/search/types.ts +33 -5
  23. package/dist/components/menus/ActionMenu/ActionMenu.vue +29 -7
  24. package/dist/components/menus/ActionMenu/theme.css +1 -1
  25. package/dist/components/menus/ActionMenu/types.d.ts +9 -0
  26. package/dist/components/menus/ActionMenu/types.d.ts.map +1 -0
  27. package/dist/components/menus/ActionMenu/types.js +1 -0
  28. package/dist/components/menus/ActionMenu/types.ts +9 -0
  29. package/dist/components/models/Popover/Popover.vue +6 -84
  30. package/dist/css/umbra-ui.css +1 -0
  31. package/dist/index.d.ts +7 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +5 -2
  34. package/package.json +20 -15
  35. package/src/components/controls/InlineDropdown/InlineDropdown.vue +290 -0
  36. package/src/components/controls/InlineDropdown/README.md +35 -0
  37. package/src/components/controls/InlineDropdown/theme.css +40 -0
  38. package/src/components/dialogs/Alert/Alert.vue +122 -11
  39. package/src/components/dialogs/Alert/theme.css +20 -0
  40. package/src/components/inputs/AutogrowRichTextView/AutogrowRichTextView.vue +128 -0
  41. package/src/components/inputs/AutogrowRichTextView/README.md +86 -0
  42. package/src/components/inputs/AutogrowRichTextView/editor.css +211 -0
  43. package/src/components/inputs/AutogrowRichTextView/theme.css +28 -0
  44. package/src/components/inputs/InputCryptoAddress/InputCryptoAddress.vue +512 -0
  45. package/src/components/inputs/InputCryptoAddress/README.md +45 -0
  46. package/src/components/inputs/InputCryptoAddress/theme.css +80 -0
  47. package/src/components/inputs/Tags/TagBar.vue +7 -4
  48. package/src/components/inputs/Tags/theme.css +4 -0
  49. package/src/components/inputs/search/README.md +64 -736
  50. package/src/components/inputs/search/SearchOverlay.vue +376 -0
  51. package/src/components/inputs/search/SearchResultCell.vue +205 -0
  52. package/src/components/inputs/search/theme.css +66 -21
  53. package/src/components/inputs/search/types.ts +33 -5
  54. package/src/components/menus/ActionMenu/ActionMenu.vue +29 -7
  55. package/src/components/menus/ActionMenu/theme.css +1 -1
  56. package/src/components/menus/ActionMenu/types.ts +9 -0
  57. package/src/components/models/Popover/Popover.vue +6 -84
  58. package/src/index.ts +13 -3
  59. package/src/vue.d.ts +7 -26
  60. package/src/components/inputs/search/SearchBar.vue +0 -394
  61. package/src/components/inputs/search/SearchResults.vue +0 -310
@@ -0,0 +1,290 @@
1
+ <script setup lang="ts">
2
+ import {
3
+ ref,
4
+ onMounted,
5
+ onBeforeUpdate,
6
+ type ComponentPublicInstance,
7
+ } from "vue";
8
+ import { ChevronRightIcon, CheckIcon } from "@umbra.ui/icons";
9
+ import gsap from "gsap";
10
+ import { Flip } from "gsap/Flip";
11
+ import "./theme.css";
12
+ gsap.registerPlugin(Flip);
13
+
14
+ export interface DropdownItem {
15
+ id: string;
16
+ title: string;
17
+ }
18
+
19
+ interface Props {
20
+ items: DropdownItem[];
21
+ placeholder?: string;
22
+ modelValue?: DropdownItem | null;
23
+ }
24
+
25
+ interface Emits {
26
+ (e: "update:modelValue", value: DropdownItem | null): void;
27
+ (e: "itemSelected", value: DropdownItem): void;
28
+ }
29
+
30
+ const props = withDefaults(defineProps<Props>(), {
31
+ placeholder: "Choose an option",
32
+ modelValue: null,
33
+ });
34
+
35
+ const emit = defineEmits<Emits>();
36
+
37
+ const selectedItem = ref<DropdownItem | null>(props.modelValue);
38
+ const selectItem = (item: DropdownItem) => {
39
+ const isSelected = selectedItem.value?.id === item.id;
40
+ if (isSelected) {
41
+ selectedItem.value = null;
42
+ emit("update:modelValue", null);
43
+ toggleItems();
44
+ return;
45
+ }
46
+
47
+ selectedItem.value = item;
48
+ emit("update:modelValue", item);
49
+ emit("itemSelected", item);
50
+ toggleItems();
51
+ };
52
+
53
+ const itemsInDrawer = ref(true);
54
+ const drawerRef = ref<HTMLElement | null>(null);
55
+ const listRef = ref<HTMLElement | null>(null);
56
+ const itemRefs = ref<HTMLElement[]>([]);
57
+
58
+ const setItemRef = (el: Element | ComponentPublicInstance | null) => {
59
+ if (el instanceof HTMLElement) {
60
+ itemRefs.value.push(el);
61
+ }
62
+ };
63
+
64
+ onBeforeUpdate(() => {
65
+ itemRefs.value = [];
66
+ });
67
+
68
+ const toggleItems = () => {
69
+ const drawer = drawerRef.value;
70
+ const itemList = listRef.value;
71
+
72
+ if (!drawer || !itemList) {
73
+ console.error("Identity item drawer or item list not found");
74
+ return;
75
+ }
76
+
77
+ // Collect all item elements
78
+ const targets = itemRefs.value;
79
+
80
+ if (targets.length === 0) return;
81
+
82
+ // Determine current location by checking the parent of the first item
83
+ const isInDrawer = targets[0].parentElement === drawer;
84
+ const destination = isInDrawer ? itemList : drawer;
85
+
86
+ // Capture the INITIAL state BEFORE moving anything (including opacity)
87
+ const state = Flip.getState([...targets, itemList, drawer], {
88
+ props: "opacity",
89
+ });
90
+
91
+ // Move all elements to their destination and set target opacity
92
+ for (const target of targets) {
93
+ destination.appendChild(target);
94
+ // Set opacity on individual targets, not the container
95
+ gsap.set(target, { opacity: isInDrawer ? 1 : 0 });
96
+ }
97
+
98
+ // Update reactive state
99
+ itemsInDrawer.value = !isInDrawer;
100
+
101
+ // Animate from the captured initial state to current positions (including opacity)
102
+ Flip.from(state, {
103
+ duration: 0.3,
104
+ ease: "power1.inOut",
105
+ }).then(() => {
106
+ console.log("Animation complete");
107
+ });
108
+ };
109
+
110
+ onMounted(() => {
111
+ for (const itemElement of itemRefs.value) {
112
+ itemElement.style.opacity = "0";
113
+ }
114
+ });
115
+ </script>
116
+
117
+ <template>
118
+ <div :class="$style.container">
119
+ <div ref="drawerRef" :class="$style.item_drawer">
120
+ <div
121
+ :ref="setItemRef"
122
+ :class="[
123
+ $style.item,
124
+ selectedItem?.title === item.title ? $style.item_selected : '',
125
+ ]"
126
+ v-for="item in items"
127
+ :key="item.title"
128
+ @click="selectItem(item)"
129
+ >
130
+ <p>{{ item.title }}</p>
131
+ <CheckIcon
132
+ v-if="selectedItem?.title === item.title"
133
+ color="white"
134
+ size="16"
135
+ />
136
+ </div>
137
+ </div>
138
+ <div :class="$style.identity_card">
139
+ <div
140
+ :class="[
141
+ $style.button,
142
+ !itemsInDrawer ? $style.button_drawer_open : '',
143
+ selectedItem ? $style.button_selected_value : '',
144
+ ]"
145
+ @click="toggleItems"
146
+ >
147
+ <p class="body">{{ selectedItem?.title ?? placeholder }}</p>
148
+ <div
149
+ :class="$style.icon"
150
+ :style="{
151
+ transform: itemsInDrawer ? 'rotate(0)' : 'rotate(90deg)',
152
+ }"
153
+ >
154
+ <ChevronRightIcon :color="selectedItem ? 'black' : 'white'" />
155
+ </div>
156
+ </div>
157
+ </div>
158
+ <div
159
+ ref="listRef"
160
+ :class="[$style.item_list, itemsInDrawer ? $style.item_list_hidden : '']"
161
+ ></div>
162
+ </div>
163
+ </template>
164
+
165
+ <style module>
166
+ .container {
167
+ display: flex;
168
+ flex-direction: column;
169
+ position: relative;
170
+ }
171
+ .button {
172
+ display: flex;
173
+ align-items: center;
174
+ justify-content: space-between;
175
+ gap: 0.471rem;
176
+ flex-grow: 1;
177
+ background-color: var(--InlineDropdown-button-bg);
178
+ font-weight: 700;
179
+ cursor: default;
180
+ user-select: none;
181
+ transition: 0.3s ease-in-out color, 0.3s ease-in-out background-color,
182
+ 0.3s ease-in-out transform, 0.3s ease-in-out border-radius,
183
+ 0.3s ease-in-out border;
184
+ transform: scale(1);
185
+ will-change: transform;
186
+ padding-left: 0.882rem;
187
+ padding-right: 0.882rem;
188
+ padding-top: 0.588rem;
189
+ padding-bottom: 0.588rem;
190
+ font-size: var(--callout);
191
+ border: 1px solid var(--InlineDropdown-border);
192
+ border-radius: 0.471rem;
193
+ }
194
+ .button > p {
195
+ color: var(--InlineDropdown-button-text-color);
196
+ }
197
+ .button_drawer_open {
198
+ border-bottom-left-radius: 0;
199
+ border-bottom-right-radius: 0;
200
+ }
201
+ .button_selected_value {
202
+ background-color: var(--InlineDropdown-button-selected-bg);
203
+ border: 1px solid var(--InlineDropdown-button-selected-border);
204
+ }
205
+ .button_selected_value > p,
206
+ .button_selected_value > svg {
207
+ color: var(--InlineDropdown-button-selected-text-color);
208
+ }
209
+ .button_selected_value:hover {
210
+ background-color: var(--InlineDropdown-button-selected-hover-bg);
211
+ }
212
+ .item_drawer {
213
+ position: absolute;
214
+ top: 0;
215
+ left: 0;
216
+ right: 0;
217
+ display: grid;
218
+ grid-template-columns: 1fr;
219
+ grid-template-rows: 1fr;
220
+ grid-template-areas: "content";
221
+ }
222
+ .identity_card {
223
+ display: flex;
224
+ align-items: center;
225
+ gap: 0.471rem;
226
+ z-index: 2;
227
+ }
228
+ .identity_card > :first-child {
229
+ width: 100%;
230
+ height: 100%;
231
+ }
232
+
233
+ .icon {
234
+ transform: translateY(-50%);
235
+ display: flex;
236
+ align-items: center;
237
+ justify-content: center;
238
+ pointer-events: none;
239
+ opacity: 0.6;
240
+ transition: transform 0.2s ease;
241
+ }
242
+ .icon > svg {
243
+ width: 1rem;
244
+ height: 1rem;
245
+ }
246
+ .item_list {
247
+ display: flex;
248
+ flex-direction: column;
249
+ transition: padding-top 0.3s ease, border 0.3s ease;
250
+ }
251
+ .item_list > :last-child {
252
+ border-bottom-left-radius: 0.471rem;
253
+ border-bottom-right-radius: 0.471rem;
254
+ }
255
+ .item {
256
+ display: flex;
257
+ align-items: center;
258
+ justify-content: space-between;
259
+ grid-area: content;
260
+ border-bottom: 1px solid var(--InlineDropdown-border);
261
+ border-left: 1px solid var(--InlineDropdown-border);
262
+ border-right: 1px solid var(--InlineDropdown-border);
263
+ padding-left: 0.706rem;
264
+ padding-right: 0.706rem;
265
+ padding-top: 0.471rem;
266
+ padding-bottom: 0.471rem;
267
+ cursor: pointer;
268
+ transition: background-color 0.15s ease;
269
+ user-select: none;
270
+ width: 100%;
271
+ background-color: var(--InlineDropdown-item-bg);
272
+ }
273
+ .item:hover {
274
+ background-color: var(--InlineDropdown-item-hover-bg);
275
+ }
276
+ .item_selected {
277
+ background-color: var(--InlineDropdown-item-selected-bg);
278
+ border-top: 1px solid var(--InlineDropdown-item-selected-border);
279
+ border-bottom: 1px solid var(--InlineDropdown-item-selected-border);
280
+ }
281
+ /* targets the item immediately before the selected one and removes its bottom border */
282
+ .item:has(+ .item_selected) {
283
+ border-bottom: none;
284
+ }
285
+ .item > svg {
286
+ width: 1rem;
287
+ height: 1rem;
288
+ opacity: 0.7;
289
+ }
290
+ </style>
@@ -0,0 +1,35 @@
1
+ ## InlineDropdown
2
+
3
+ Compact dropdown with inline list animation for quick selection.
4
+
5
+ ### Usage
6
+
7
+ ```vue
8
+ <script setup lang="ts">
9
+ import { ref } from "vue";
10
+ import { InlineDropdown } from "@umbra.ui/core";
11
+
12
+ const items = [
13
+ { id: "a", title: "Alpha" },
14
+ { id: "b", title: "Beta" },
15
+ { id: "c", title: "Gamma" },
16
+ ];
17
+
18
+ const selected = ref(items[0]);
19
+ </script>
20
+
21
+ <template>
22
+ <InlineDropdown v-model="selected" :items="items" />
23
+ </template>
24
+ ```
25
+
26
+ ### Props
27
+
28
+ - `items`: list of `{ id, title }` items.
29
+ - `modelValue`: selected item (for `v-model`).
30
+ - `placeholder`: text when no selection is set.
31
+
32
+ ### Events
33
+
34
+ - `update:modelValue`: emitted on selection changes.
35
+ - `itemSelected`: emitted with the selected item.
@@ -0,0 +1,40 @@
1
+ /* Light theme - InlineDropdown */
2
+ :root {
3
+ --InlineDropdown-button-bg: #ffffff;
4
+ --InlineDropdown-border: rgba(0, 0, 0, 0.12);
5
+ --InlineDropdown-button-border: var(--InlineDropdown-border);
6
+ --InlineDropdown-button-text-color: #1a1d23;
7
+ --InlineDropdown-button-selected-bg: #e8e8e8;
8
+ --InlineDropdown-button-selected-border: rgba(0, 0, 0, 0.12);
9
+ --InlineDropdown-button-selected-text-color: #1a1d23;
10
+ --InlineDropdown-button-selected-hover-bg: #e0e0e0;
11
+
12
+ --InlineDropdown-item-list-border: var(--InlineDropdown-border);
13
+ --InlineDropdown-item-list-hidden-border: transparent;
14
+ --InlineDropdown-item-border: var(--InlineDropdown-border);
15
+ --InlineDropdown-item-bg: #ffffff;
16
+ --InlineDropdown-item-hover-bg: #f0f2f4;
17
+ --InlineDropdown-item-selected-bg: #f0f2f4;
18
+ --InlineDropdown-item-selected-border: rgba(0, 0, 0, 0.12);
19
+ }
20
+
21
+ /* Dark theme */
22
+ .dark,
23
+ .dark-theme {
24
+ --InlineDropdown-border: rgba(255, 255, 255, 0.12);
25
+ --InlineDropdown-button-bg: #484848;
26
+ --InlineDropdown-button-border: var(--InlineDropdown-border);
27
+ --InlineDropdown-button-text-color: #b4b4b4;
28
+ --InlineDropdown-button-selected-bg: #b4b4b4;
29
+ --InlineDropdown-button-selected-border: #eeeeee;
30
+ --InlineDropdown-button-selected-text-color: #111111;
31
+ --InlineDropdown-button-selected-hover-bg: #c9c9c9;
32
+
33
+ --InlineDropdown-item-list-border: var(--InlineDropdown-border);
34
+ --InlineDropdown-item-list-hidden-border: transparent;
35
+ --InlineDropdown-item-border: var(--InlineDropdown-border);
36
+ --InlineDropdown-item-bg: #484848;
37
+ --InlineDropdown-item-hover-bg: rgb(88, 88, 88);
38
+ --InlineDropdown-item-selected-bg: #606060;
39
+ --InlineDropdown-item-selected-border: #7b7b7b;
40
+ }
@@ -4,9 +4,30 @@
4
4
  <script setup lang="ts">
5
5
  import { watch, ref } from "vue";
6
6
  import Button from "../../controls/Button/Button.vue";
7
- import type { AlertAction, AlertActionType } from "./types";
8
7
  import "./theme.css";
9
8
 
9
+ export type AlertActionType =
10
+ | "Primary"
11
+ | "Secondary"
12
+ | "Tertiary"
13
+ | "Quaternary"
14
+ | "Destructive"
15
+ | "Cancel";
16
+
17
+ export interface AlertAction {
18
+ title: string;
19
+ action: (inputValue?: string) => void | string | Promise<void | string>;
20
+ type: AlertActionType;
21
+ }
22
+
23
+ export interface AlertTextFieldConfig {
24
+ label?: string;
25
+ placeholder?: string;
26
+ type?: "text" | "password";
27
+ defaultValue?: string;
28
+ required?: boolean;
29
+ }
30
+
10
31
  // Props for customization
11
32
  const props = defineProps({
12
33
  show: {
@@ -26,6 +47,11 @@ const props = defineProps({
26
47
  required: false,
27
48
  default: () => [{ title: "Ok", action: () => {}, type: "Cancel" }],
28
49
  },
50
+ textFieldConfig: {
51
+ type: Object as () => AlertTextFieldConfig,
52
+ required: false,
53
+ default: undefined,
54
+ },
29
55
  });
30
56
 
31
57
  const emit = defineEmits(["update:show"]);
@@ -44,9 +70,13 @@ watch(
44
70
  const overlayOpacity = ref<number>(0);
45
71
  const popupOpacity = ref<number>(0);
46
72
  const popoverScale = ref<number>(1.1);
73
+ const textFieldValue = ref<string>("");
74
+ const errorMessage = ref<string>("");
47
75
 
48
76
  // Method to show the popup
49
77
  const showPopup = () => {
78
+ textFieldValue.value = props.textFieldConfig?.defaultValue || "";
79
+ errorMessage.value = "";
50
80
  setTimeout(() => {
51
81
  overlayOpacity.value = 1;
52
82
  popupOpacity.value = 1;
@@ -69,10 +99,14 @@ const buttonColor = (
69
99
  type: AlertActionType
70
100
  ): "primary" | "secondary" | "tertiary" | "quaternary" | "danger" => {
71
101
  switch (type) {
72
- case "Default":
102
+ case "Primary":
73
103
  return "primary";
74
104
  case "Secondary":
75
105
  return "secondary";
106
+ case "Tertiary":
107
+ return "tertiary";
108
+ case "Quaternary":
109
+ return "quaternary";
76
110
  case "Cancel":
77
111
  return "tertiary";
78
112
  case "Destructive":
@@ -87,7 +121,7 @@ const buttonOrder = (type: AlertActionType, index: number) => {
87
121
  return props.actions.length;
88
122
  }
89
123
  return -1;
90
- } else if (type === "Default") {
124
+ } else if (type === "Primary") {
91
125
  if (props.actions.length > 2) {
92
126
  return -1;
93
127
  }
@@ -95,9 +129,27 @@ const buttonOrder = (type: AlertActionType, index: number) => {
95
129
  }
96
130
  return index;
97
131
  };
98
- const onClick = (action: AlertAction) => {
132
+ const clearError = () => {
133
+ errorMessage.value = "";
134
+ };
135
+
136
+ const onClick = async (action: AlertAction) => {
137
+ errorMessage.value = "";
138
+
139
+ // Pass input value if textFieldConfig exists
140
+ const inputValue = props.textFieldConfig ? textFieldValue.value : undefined;
141
+
142
+ // Call the action and get the result
143
+ const result = await action.action(inputValue);
144
+
145
+ // If result is a string, show error and keep alert open
146
+ if (typeof result === "string") {
147
+ errorMessage.value = result;
148
+ return;
149
+ }
150
+
151
+ // Otherwise, dismiss the alert
99
152
  hidePopup();
100
- action.action();
101
153
  };
102
154
  </script>
103
155
  <!-- ================================================================================================ -->
@@ -126,6 +178,21 @@ const onClick = (action: AlertAction) => {
126
178
  <!-- Description -->
127
179
  <p :class="[$style.description, 'body']">{{ description }}</p>
128
180
 
181
+ <!-- Text Field (optional) -->
182
+ <div v-if="textFieldConfig" :class="$style.text_field_container">
183
+ <input
184
+ v-model="textFieldValue"
185
+ :type="textFieldConfig.type || 'text'"
186
+ :placeholder="textFieldConfig.placeholder || ''"
187
+ :class="$style.text_field"
188
+ class="body"
189
+ @input="clearError"
190
+ />
191
+ <p v-if="errorMessage" :class="[$style.error_message, 'footnote']">
192
+ {{ errorMessage }}
193
+ </p>
194
+ </div>
195
+
129
196
  <!-- Actions -->
130
197
  <div
131
198
  :class="[
@@ -138,8 +205,10 @@ const onClick = (action: AlertAction) => {
138
205
  v-for="(action, index) in actions"
139
206
  :key="`action-${index}`"
140
207
  :style="{ order: buttonOrder(action.type, index) }"
208
+ :class="$style.action_item"
141
209
  >
142
210
  <Button
211
+ :class="$style.button"
143
212
  :title="action.title"
144
213
  :button-style="buttonColor(action.type)"
145
214
  @click="onClick(action)"
@@ -164,7 +233,7 @@ const onClick = (action: AlertAction) => {
164
233
  display: flex;
165
234
  justify-content: center;
166
235
  align-items: center;
167
- z-index: 1000;
236
+ z-index: 10000;
168
237
  transition: 0.2s ease-in-out opacity, 0.2s ease-in-out scale;
169
238
  }
170
239
 
@@ -175,8 +244,10 @@ const onClick = (action: AlertAction) => {
175
244
  bottom: 0;
176
245
  right: 0;
177
246
  background: var(--alert-overlay-bg);
247
+ backdrop-filter: blur(10px);
248
+ -webkit-backdrop-filter: blur(10px);
178
249
  transition: 0.2s ease-in-out opacity;
179
- z-index: 999;
250
+ z-index: 9999;
180
251
  }
181
252
 
182
253
  .content {
@@ -185,8 +256,8 @@ const onClick = (action: AlertAction) => {
185
256
  padding: 1.176rem;
186
257
  border-radius: 0.471rem;
187
258
  box-shadow: 0 2px 10px var(--alert-content-shadow);
188
- z-index: 1001;
189
- max-width: 20.588rem;
259
+ z-index: 10001;
260
+ width: 21rem;
190
261
  display: flex;
191
262
  flex-direction: column;
192
263
  gap: 0.706rem;
@@ -201,18 +272,58 @@ const onClick = (action: AlertAction) => {
201
272
  opacity: var(--alert-description-opacity);
202
273
  }
203
274
 
275
+ .text_field_container {
276
+ display: flex;
277
+ flex-direction: column;
278
+ gap: 0.471rem;
279
+ margin-bottom: 0.5rem;
280
+ }
281
+
282
+ .text_field {
283
+ min-height: 2.353rem;
284
+ background-color: var(--alert-text-field-bg);
285
+ border: 1px solid var(--alert-text-field-border);
286
+ outline: none;
287
+ padding: 0.588rem 0.882rem;
288
+ border-radius: 0.471rem;
289
+ color: var(--alert-text-field-color);
290
+ transition: background-color 0.3s ease, border-color 0.3s ease;
291
+ text-align: center;
292
+ }
293
+
294
+ .text_field:focus {
295
+ background-color: var(--alert-text-field-focus-bg);
296
+ border-color: var(--alert-text-field-border-focused);
297
+ }
298
+
299
+ .error_message {
300
+ color: var(--alert-error-color);
301
+ margin-top: 0.235rem;
302
+ }
303
+
204
304
  .single_action {
205
305
  display: flex;
206
- justify-content: end;
306
+ width: 100%;
207
307
  }
208
308
  .binary_action {
209
309
  display: flex;
210
310
  align-items: center;
211
- gap: 0.706rem;
311
+ gap: 1.176rem;
312
+ width: 100%;
212
313
  }
213
314
  .multiple_actions {
214
315
  display: flex;
215
316
  flex-direction: column;
216
317
  gap: 0.706rem;
318
+ width: 100%;
319
+ }
320
+ .action_item {
321
+ flex: 1;
322
+ display: flex;
323
+ }
324
+ .button {
325
+ flex-grow: 1;
326
+ width: 100%;
327
+ min-width: 0;
217
328
  }
218
329
  </style>
@@ -21,6 +21,16 @@
21
21
  /* Alert description colors */
22
22
  --alert-description-opacity: 0.7; /* slightly more visible in light mode */
23
23
 
24
+ /* Alert text field colors */
25
+ --alert-text-field-bg: #f3f4f6;
26
+ --alert-text-field-border: rgba(0, 0, 0, 0.1);
27
+ --alert-text-field-color: #1a1d23;
28
+ --alert-text-field-focus-bg: #ffffff;
29
+ --alert-text-field-border-focused: #0090ff;
30
+
31
+ /* Alert error color */
32
+ --alert-error-color: #e5484d;
33
+
24
34
  /* Alert destructive button color */
25
35
  --alert-destructive-color: #e5484d; /* red9 - destructive action color */
26
36
  }
@@ -39,6 +49,16 @@
39
49
  /* Alert description colors */
40
50
  --alert-description-opacity: 0.5; /* Original dark mode value */
41
51
 
52
+ /* Alert text field colors */
53
+ --alert-text-field-bg: #2a2a2a;
54
+ --alert-text-field-border: #3a3a3a;
55
+ --alert-text-field-color: #eeeeee;
56
+ --alert-text-field-focus-bg: #3a3a3a;
57
+ --alert-text-field-border-focused: #0090ff;
58
+
59
+ /* Alert error color */
60
+ --alert-error-color: #e5484d;
61
+
42
62
  /* Alert destructive button color */
43
63
  --alert-destructive-color: #e5484d; /* red9 - destructive action color */
44
64
  }
@@ -23,7 +23,7 @@ export declare const useToast: () => {
23
23
  duration: number;
24
24
  dismissible: boolean;
25
25
  }[]>;
26
- toastStyle: import("vue").ComputedRef<"bar" | "full" | "notification">;
26
+ toastStyle: import("vue").ComputedRef<"notification" | "bar" | "full">;
27
27
  addToast: (options: ToastOptions) => Promise<string>;
28
28
  removeToast: (id: string) => void;
29
29
  removeAllToasts: () => void;