@necrolab/dashboard 0.5.14 → 0.5.16

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 (120) hide show
  1. package/backend/api.js +2 -3
  2. package/eslint.config.js +46 -0
  3. package/index.html +2 -1
  4. package/package.json +5 -2
  5. package/src/App.vue +140 -170
  6. package/src/assets/css/base/mixins.scss +72 -0
  7. package/src/assets/css/base/reset.scss +0 -2
  8. package/src/assets/css/base/scroll.scss +43 -36
  9. package/src/assets/css/base/typography.scss +9 -10
  10. package/src/assets/css/base/variables.scss +43 -0
  11. package/src/assets/css/components/accessibility.scss +37 -0
  12. package/src/assets/css/components/buttons.scss +58 -15
  13. package/src/assets/css/components/forms.scss +31 -32
  14. package/src/assets/css/components/headers.scss +119 -0
  15. package/src/assets/css/components/modals.scss +2 -2
  16. package/src/assets/css/components/search-groups.scss +28 -19
  17. package/src/assets/css/components/tables.scss +5 -7
  18. package/src/assets/css/components/toasts.scss +7 -7
  19. package/src/assets/css/components/utilities.scss +220 -0
  20. package/src/assets/css/main.scss +72 -75
  21. package/src/components/Auth/LoginForm.vue +5 -84
  22. package/src/components/Editors/Account/Account.vue +8 -10
  23. package/src/components/Editors/Account/AccountCreator.vue +28 -59
  24. package/src/components/Editors/Account/AccountView.vue +38 -86
  25. package/src/components/Editors/Account/CreateAccount.vue +8 -50
  26. package/src/components/Editors/Profile/CreateProfile.vue +74 -131
  27. package/src/components/Editors/Profile/Profile.vue +15 -17
  28. package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
  29. package/src/components/Editors/Profile/ProfileView.vue +46 -96
  30. package/src/components/Editors/TagLabel.vue +16 -55
  31. package/src/components/Editors/TagToggle.vue +20 -8
  32. package/src/components/Filter/Filter.vue +62 -75
  33. package/src/components/Filter/FilterPreview.vue +161 -135
  34. package/src/components/Filter/PriceSortToggle.vue +36 -43
  35. package/src/components/Table/Header.vue +1 -1
  36. package/src/components/Table/Table.vue +61 -12
  37. package/src/components/Tasks/CheckStock.vue +7 -16
  38. package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
  39. package/src/components/Tasks/Controls/MobileControls.vue +5 -20
  40. package/src/components/Tasks/CreateTaskAXS.vue +20 -118
  41. package/src/components/Tasks/CreateTaskTM.vue +33 -189
  42. package/src/components/Tasks/EventDetailRow.vue +21 -0
  43. package/src/components/Tasks/MassEdit.vue +6 -16
  44. package/src/components/Tasks/QuickSettings.vue +140 -216
  45. package/src/components/Tasks/ScrapeVenue.vue +4 -13
  46. package/src/components/Tasks/Stats.vue +19 -38
  47. package/src/components/Tasks/Task.vue +65 -268
  48. package/src/components/Tasks/TaskLabel.vue +9 -3
  49. package/src/components/Tasks/TaskView.vue +43 -63
  50. package/src/components/Tasks/Utilities.vue +10 -42
  51. package/src/components/Tasks/ViewTask.vue +23 -107
  52. package/src/components/icons/Close.vue +2 -8
  53. package/src/components/icons/Gear.vue +8 -8
  54. package/src/components/icons/Hash.vue +5 -0
  55. package/src/components/icons/Key.vue +2 -8
  56. package/src/components/icons/Pencil.vue +2 -8
  57. package/src/components/icons/Profile.vue +2 -8
  58. package/src/components/icons/Sell.vue +2 -8
  59. package/src/components/icons/Spinner.vue +4 -7
  60. package/src/components/icons/SquareCheck.vue +2 -8
  61. package/src/components/icons/SquareUncheck.vue +2 -8
  62. package/src/components/icons/Wildcard.vue +2 -8
  63. package/src/components/icons/index.js +3 -1
  64. package/src/components/ui/ActionButtonGroup.vue +113 -52
  65. package/src/components/ui/BalanceIndicator.vue +60 -0
  66. package/src/components/ui/EmptyState.vue +24 -0
  67. package/src/components/ui/EnableDisableToggle.vue +23 -0
  68. package/src/components/ui/FormField.vue +48 -48
  69. package/src/components/ui/IconLabel.vue +23 -0
  70. package/src/components/ui/InfoRow.vue +21 -54
  71. package/src/components/ui/Modal.vue +78 -37
  72. package/src/components/ui/Navbar.vue +60 -41
  73. package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
  74. package/src/components/ui/ReconnectIndicator.vue +111 -124
  75. package/src/components/ui/SectionCard.vue +6 -14
  76. package/src/components/ui/Splash.vue +2 -10
  77. package/src/components/ui/StatusBadge.vue +26 -28
  78. package/src/components/ui/TaskToggle.vue +54 -0
  79. package/src/components/ui/controls/CountryChooser.vue +27 -64
  80. package/src/components/ui/controls/EyeToggle.vue +1 -1
  81. package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
  82. package/src/components/ui/controls/atomic/Dropdown.vue +102 -95
  83. package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -94
  84. package/src/components/ui/controls/atomic/Switch.vue +21 -84
  85. package/src/composables/useColorMapping.js +15 -0
  86. package/src/composables/useCopyToClipboard.js +1 -1
  87. package/src/composables/useDateFormatting.js +21 -0
  88. package/src/composables/useDeviceDetection.js +14 -0
  89. package/src/composables/useDropdownPosition.js +5 -6
  90. package/src/composables/useDynamicTableHeight.js +31 -0
  91. package/src/composables/useRowSelection.js +0 -3
  92. package/src/composables/useTicketPricing.js +16 -0
  93. package/src/composables/useWindowDimensions.js +21 -0
  94. package/src/libs/Filter.js +14 -20
  95. package/src/libs/panzoom.js +1 -5
  96. package/src/libs/utils/array.js +60 -0
  97. package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
  98. package/src/libs/utils/eventUrl.js +40 -0
  99. package/src/libs/utils/string.js +28 -0
  100. package/src/libs/utils/time.js +20 -0
  101. package/src/libs/utils/validation.js +88 -0
  102. package/src/main.js +0 -2
  103. package/src/stores/connection.js +1 -4
  104. package/src/stores/logger.js +6 -12
  105. package/src/stores/sampleData.js +1 -2
  106. package/src/stores/ui.js +59 -36
  107. package/src/views/Accounts.vue +17 -31
  108. package/src/views/Console.vue +76 -176
  109. package/src/views/Editor.vue +217 -383
  110. package/src/views/FilterBuilder.vue +190 -373
  111. package/src/views/Login.vue +3 -28
  112. package/src/views/Profiles.vue +12 -22
  113. package/src/views/Tasks.vue +51 -38
  114. package/tailwind.config.js +82 -71
  115. package/workbox-config.cjs +47 -5
  116. package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2416
  117. package/exit +0 -209
  118. package/run +0 -177
  119. package/switch-branch.sh +0 -41
  120. /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div>
3
3
  <div
4
- class="dropdown input-default p-4 w-16 bg-dark-550 small-dropdown"
4
+ class="dropdown input-default !rounded-full !p-0 !w-[3em] !h-[3em] flex justify-center items-center !bg-clip-border bg-dark-550"
5
5
  ref="dropdownRef"
6
6
  @click="toggleOpen"
7
7
  >
@@ -17,42 +17,42 @@
17
17
  <transition name="fade">
18
18
  <div
19
19
  v-if="open"
20
- class="dropdown-content-portal special-dropdown"
20
+ class="bg-dark-400 border border-dark-650 rounded-lg shadow-2xl z-50 p-2 !max-h-52 !overflow-y-auto custom-scrollbar-y min-w-20 w-25"
21
21
  :style="menuStyle"
22
22
  @click.stop
23
23
  @wheel.stop
24
24
  @touchmove.stop
25
25
  >
26
- <div class="header-item">TM</div>
26
+ <div class="country-header-item">TM</div>
27
27
  <div
28
28
  v-bind:key="country.id"
29
29
  v-for="country in countries.TM"
30
30
  class="country-item"
31
31
  @click="selectCountry(country, 'TM')"
32
32
  >
33
- <div class="flex items-center justify-center gap-2">
34
- <span class="text-xs font-medium">{{
33
+ <div class="flex items-center justify-center gap-1.5 w-full flex-nowrap">
34
+ <span class="text-xs font-medium whitespace-nowrap flex-shrink-0 text-center">{{
35
35
  country.siteId.split("_")[1]
36
36
  }}</span>
37
37
  <img
38
- class="w-5 h-4"
38
+ class="w-4.5 h-3.5 flex-shrink-0"
39
39
  :src="`/flags/${country.siteId.split('_')[1].toLowerCase()}.svg`"
40
40
  />
41
41
  </div>
42
42
  </div>
43
- <div class="header-item">AXS</div>
43
+ <div class="country-header-item">AXS</div>
44
44
  <div
45
45
  v-bind:key="country.id"
46
46
  v-for="country in countries.AXS"
47
47
  class="country-item"
48
48
  @click="selectCountry(country, 'AXS')"
49
49
  >
50
- <div class="flex items-center justify-center gap-2">
51
- <span class="text-xs font-medium">{{
50
+ <div class="flex items-center justify-center gap-1.5 w-full flex-nowrap">
51
+ <span class="text-xs font-medium whitespace-nowrap flex-shrink-0 text-center">{{
52
52
  country.siteId.split("_")[1]
53
53
  }}</span>
54
54
  <img
55
- class="w-5 h-4"
55
+ class="w-4.5 h-3.5 flex-shrink-0"
56
56
  :src="`/flags/${country.siteId.split('_')[1].toLowerCase()}.svg`"
57
57
  />
58
58
  </div>
@@ -108,74 +108,37 @@ const selectCountry = (country, module) => {
108
108
  </script>
109
109
 
110
110
  <style scoped>
111
- .special-dropdown {
112
- @apply min-w-20;
113
- }
114
-
115
- .small-dropdown {
116
- @apply bg-clip-border rounded-full w-12 h-12 flex justify-center items-center;
117
- padding: 0;
118
- }
119
-
120
- .dropdown-content-portal {
121
- @apply bg-dark-400 border border-dark-650 rounded-lg shadow-2xl z-50;
122
- @apply max-h-52 overflow-y-auto touch-pan-y;
123
- padding: 0.5rem;
124
- overscroll-behavior: contain;
125
- -webkit-overflow-scrolling: touch;
126
- scrollbar-width: none;
127
- -ms-overflow-style: none;
128
- min-width: 100px;
129
- width: 100px;
130
- }
131
-
132
- .dropdown-content-portal::-webkit-scrollbar {
133
- display: none;
134
- }
135
-
136
- .header-item {
111
+ .country-header-item {
137
112
  @apply text-center text-xs font-bold text-white;
138
- @apply py-2 px-1 mx-0.5 my-1 rounded-md;
113
+ @apply py-2 px-1 my-1 mx-0.5;
114
+ @apply cursor-default pointer-events-none;
115
+ @apply border rounded-md tracking-wider;
139
116
  @apply flex items-center justify-center;
140
- @apply pointer-events-none cursor-default;
141
117
  @apply relative;
142
- background: linear-gradient(
143
- 135deg,
144
- rgba(255, 255, 255, 0.08) 0%,
145
- rgba(255, 255, 255, 0.04) 100%
146
- );
147
- border: 1px solid rgba(255, 255, 255, 0.1);
148
- letter-spacing: 0.5px;
118
+ border-color: rgba(255, 255, 255, 0.1);
119
+ background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.04) 100%);
149
120
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);
150
121
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
151
122
  }
152
123
 
153
- .header-item:first-child {
124
+ .country-header-item:first-of-type {
154
125
  @apply mt-0.5;
155
126
  }
156
127
 
157
- .header-item::before {
158
- content: "";
159
- position: absolute;
160
- top: 0;
161
- left: 0;
162
- right: 0;
163
- height: 1px;
164
- background: linear-gradient(
165
- 90deg,
166
- transparent 0%,
167
- rgba(255, 255, 255, 0.2) 50%,
168
- transparent 100%
169
- );
170
- border-radius: 6px 6px 0 0;
128
+ .country-header-item::before {
129
+ content: '';
130
+ @apply absolute top-0 left-0 right-0 h-px rounded-t-md;
131
+ background: linear-gradient(90deg, transparent 0%, rgba(255, 255, 255, 0.2) 50%, transparent 100%);
171
132
  }
172
133
 
173
134
  .country-item {
174
- @apply py-2 px-1 mx-0.5 my-px text-sm text-white;
175
- @apply cursor-pointer rounded-md min-h-8;
135
+ @apply py-2 px-1 my-px mx-0.5 min-h-8;
136
+ @apply text-sm text-white cursor-pointer rounded-md;
176
137
  @apply flex items-center justify-center;
177
- transition: all 0.15s ease;
138
+ @apply transition-all duration-150 ease-in-out;
178
139
  }
179
140
 
180
- /* Flex layout already defined in template with Tailwind classes */
141
+ .country-item:hover {
142
+ @apply bg-dark-650;
143
+ }
181
144
  </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <button @click="toggle" class="w-22 cursor-pointer">
2
+ <button @click="toggle" class="w-22 cursor-pointer" :aria-label="value ? 'Hide' : 'Show'" :aria-pressed="value">
3
3
  <img v-if="value" class="w-5 h-5" src="@/assets/img/eyes/open.svg" alt="Open Eye" />
4
4
  <img v-else class="w-5 h-5" src="@/assets/img/eyes/closed.svg" alt="Closed Eye" />
5
5
  </button>
@@ -1,137 +1,56 @@
1
1
  <template>
2
2
  <button
3
- class="modern-checkbox"
3
+ class="checkbox-base"
4
+ :class="[
5
+ isHeader ? 'size-4.5 border-dark-550' : 'size-5 border-2 border-dark-700',
6
+ toggled ? 'bg-accent-green border-accent-green hover:bg-accent-green-hover hover:border-accent-green-hover' : 'hover:border-dark-550',
7
+ isHeader && !toggled ? 'hover:border-accent-green hover:bg-accent-green/10' : ''
8
+ ]"
9
+ role="checkbox"
10
+ :aria-checked="toggled"
11
+ :aria-label="isHeader ? 'Select all' : 'Select item'"
4
12
  @click="
5
13
  checked = !checked;
6
14
  $emit('valueUpdate', checked);
7
15
  "
8
- :class="{ checked: toggled, 'header-checkbox': isHeader }"
9
16
  >
10
- <div class="checkbox-inner">
11
- <!-- Header checkbox design -->
12
- <div v-if="isHeader" class="header-indicator" :class="{ visible: toggled }"></div>
13
-
14
- <!-- Row checkbox design -->
15
- <svg
16
- v-else
17
- class="checkmark"
18
- :class="{ visible: toggled }"
19
- viewBox="0 0 24 24"
20
- fill="none"
21
- xmlns="http://www.w3.org/2000/svg"
22
- >
23
- <path
24
- d="M20 6L9 17L4 12"
25
- stroke="currentColor"
26
- stroke-width="3"
27
- stroke-linecap="round"
28
- stroke-linejoin="round"
29
- />
30
- </svg>
31
- </div>
17
+ <!-- Header checkbox indicator -->
18
+ <div
19
+ v-if="isHeader"
20
+ class="size-1.5 rounded-full bg-white transition-all duration-200 ease-out"
21
+ :class="toggled ? 'opacity-100 scale-100' : 'opacity-0 scale-[0.3]'"
22
+ ></div>
23
+
24
+ <!-- Row checkbox checkmark -->
25
+ <svg
26
+ v-else
27
+ class="size-2 text-white transition-all duration-200 ease-out hover:[@media(hover:hover)]:scale-110"
28
+ :class="toggled ? 'opacity-100 scale-100' : 'opacity-0 scale-50'"
29
+ viewBox="0 0 24 24"
30
+ fill="none"
31
+ >
32
+ <path
33
+ d="M20 6L9 17L4 12"
34
+ stroke="currentColor"
35
+ stroke-width="3"
36
+ stroke-linecap="round"
37
+ stroke-linejoin="round"
38
+ />
39
+ </svg>
32
40
  </button>
33
41
  </template>
34
- <style lang="scss" scoped>
35
- .modern-checkbox {
36
- @apply relative flex items-center justify-center cursor-pointer flex-shrink-0;
37
- width: 18px;
38
- height: 18px;
39
- border-radius: 50%;
40
- border: 2px solid oklch(0.28 0 0);
41
- background: transparent;
42
- transition: all 0.2s ease;
43
-
44
- &:hover {
45
- border-color: oklch(0.33 0 0);
46
- transform: scale(1.05);
47
- }
48
-
49
- &.checked {
50
- background: oklch(0.72 0.15 145);
51
- border-color: oklch(0.72 0.15 145);
52
-
53
- &:hover {
54
- background: oklch(0.78 0.12 145);
55
- border-color: oklch(0.78 0.12 145);
56
- }
57
- }
58
-
59
- &.header-checkbox {
60
- width: 16px;
61
- height: 16px;
62
- border-color: oklch(0.33 0 0);
63
-
64
- &:hover {
65
- border-color: oklch(0.72 0.15 145);
66
- background: rgba(136, 201, 153, 0.1);
67
- }
68
-
69
- &.checked {
70
- background: oklch(0.72 0.15 145);
71
- border-color: oklch(0.72 0.15 145);
72
-
73
- &:hover {
74
- background: oklch(0.78 0.12 145);
75
- border-color: oklch(0.78 0.12 145);
76
- }
77
- }
78
- }
79
-
80
- &:focus-visible {
81
- outline: 2px solid oklch(0.72 0.15 145);
82
- outline-offset: 2px;
83
- }
84
- }
85
-
86
- .checkbox-inner {
87
- @apply relative w-full h-full flex items-center justify-center;
88
- }
89
-
90
- .checkmark {
91
- width: 8px;
92
- height: 8px;
93
- color: #ffffff;
94
- opacity: 0;
95
- transform: scale(0.5);
96
- transition: all 0.2s ease;
97
-
98
- &.visible {
99
- opacity: 1;
100
- transform: scale(1);
101
- }
102
- }
103
-
104
- .header-indicator {
105
- width: 6px;
106
- height: 6px;
107
- background: #ffffff;
108
- border-radius: 50%;
109
- opacity: 0;
110
- transform: scale(0.3);
111
- transition: all 0.2s ease;
112
42
 
113
- &.visible {
114
- opacity: 1;
115
- transform: scale(1);
116
- }
117
- }
118
-
119
- @media (hover: hover) {
120
- .modern-checkbox:hover {
121
- transform: scale(1.05);
122
- }
123
-
124
- .modern-checkbox.checked:hover .checkmark {
125
- transform: scale(1.1);
126
- }
127
- }
128
- </style>
129
43
  <script setup>
130
- import { CheckmarkIcon } from "@/components/icons";
131
44
  import { ref } from "vue";
132
45
  const props = defineProps({
133
- toggled: { type: Boolean, required: false, default: false },
134
- isHeader: { type: Boolean, required: false, default: false }
46
+ toggled: {
47
+ type: Boolean,
48
+ default: false
49
+ },
50
+ isHeader: {
51
+ type: Boolean,
52
+ default: false
53
+ }
135
54
  });
136
55
 
137
56
  const checked = ref(props.toggled);
@@ -1,5 +1,16 @@
1
1
  <template>
2
- <div @click="toggleOpened" class="dropdown" :class="[props.variant, { 'opened': opened }]" ref="dropdownRef">
2
+ <div
3
+ @click="toggleOpened"
4
+ class="dropdown"
5
+ :class="[props.variant, { 'opened': opened }]"
6
+ ref="dropdownRef"
7
+ role="combobox"
8
+ :aria-expanded="opened"
9
+ :aria-label="props.default"
10
+ tabindex="0"
11
+ @keydown.enter="toggleOpened"
12
+ @keydown.space.prevent="toggleOpened"
13
+ @keydown.escape="opened && ui.setCurrentDropdown('')">
3
14
  <span class="dropdown-display">
4
15
  <span class="dropdown-value" :class="capitalize ? 'capitalize' : ''">
5
16
  {{ currentValue ? currentValue : props.default }}
@@ -12,16 +23,17 @@
12
23
  v-if="opened"
13
24
  class="dropdown-menu-portal scrollable"
14
25
  :style="menuStyle"
26
+ role="listbox"
15
27
  @click.stop
16
- @wheel.stop
17
- @touchmove.stop>
28
+ @wheel.stop>
18
29
  <button
19
30
  v-bind:key="f"
20
31
  class="dropdown-item"
21
32
  :class="i !== 0 ? 'border-t border-dark-650' : ''"
22
33
  v-for="(f, i) in !allowDefault ? props.options : ['', ...props.options]"
23
- @mousedown.prevent.stop="chose(f)"
24
- @touchstart.prevent.stop="chose(f)">
34
+ role="option"
35
+ :aria-selected="(f || props.default) === currentValue"
36
+ @click.stop="chose(f)">
25
37
  <span class="dropdown-item-text" :class="capitalize ? 'capitalize' : ''">
26
38
  {{ f ? f : props.default }}
27
39
  </span>
@@ -42,16 +54,47 @@ import { useDropdownPosition } from "@/composables/useDropdownPosition";
42
54
  const ui = useUIStore();
43
55
 
44
56
  const props = defineProps({
45
- onClick: { type: Function },
46
- default: { type: String },
47
- value: { type: String },
48
- options: { type: Object },
49
- allowDefault: { type: Boolean },
50
- rightAmount: { type: String },
51
- topPadding: { type: String },
52
- capitalize: { type: Boolean },
53
- includeAdjacentButtons: { type: Boolean, default: false },
54
- variant: { type: String, default: "default" }
57
+ onClick: {
58
+ type: Function,
59
+ default: null
60
+ },
61
+ default: {
62
+ type: String,
63
+ default: ''
64
+ },
65
+ value: {
66
+ type: String,
67
+ default: ''
68
+ },
69
+ options: {
70
+ type: Object,
71
+ required: true
72
+ },
73
+ allowDefault: {
74
+ type: Boolean,
75
+ default: false
76
+ },
77
+ rightAmount: {
78
+ type: String,
79
+ default: ''
80
+ },
81
+ topPadding: {
82
+ type: String,
83
+ default: ''
84
+ },
85
+ capitalize: {
86
+ type: Boolean,
87
+ default: false
88
+ },
89
+ includeAdjacentButtons: {
90
+ type: Boolean,
91
+ default: false
92
+ },
93
+ variant: {
94
+ type: String,
95
+ default: 'default',
96
+ validator: (value) => ['default', 'transparent'].includes(value)
97
+ }
55
98
  });
56
99
 
57
100
  const currentValue = ref(props.value);
@@ -120,34 +163,41 @@ const chose = (f) => {
120
163
 
121
164
  <style scoped>
122
165
  .dropdown {
123
- @apply relative w-full text-white ml-auto rounded-lg ring-0 h-10 bg-dark-300 border border-dark-600;
124
- padding: 0.75rem;
166
+ @apply relative w-full text-white ml-auto rounded-lg ring-0 h-10 border-2 bg-bg-input border-border p-3;
125
167
  }
126
168
 
127
169
  .dropdown.transparent {
128
- @apply bg-transparent border-0 shadow-none p-0 h-10;
170
+ @apply !bg-transparent !border-none !shadow-none !p-0 !h-10;
129
171
  }
130
172
 
131
173
  .dropdown.transparent:hover,
132
174
  .dropdown.transparent:focus-within,
133
175
  .dropdown.transparent.opened {
134
- @apply border-0 bg-transparent shadow-none outline-none;
176
+ @apply !border-none !bg-transparent !shadow-none !outline-none;
177
+ }
178
+
179
+ .unified-search-group .dropdown:hover {
180
+ @apply !border-transparent;
135
181
  }
136
182
 
137
- .dropdown:not(.transparent):hover {
138
- border-color: oklch(0.30 0 0);
183
+ .dropdown:not(.transparent):not(.unified-search-group .dropdown):hover {
184
+ @apply border-dark-700;
139
185
  }
140
186
 
141
- .dropdown:not(.transparent):focus-within,
142
- .dropdown:not(.transparent).opened {
143
- @apply border-border-focus outline outline-1 outline-border-focus;
144
- outline-offset: 0;
187
+ .unified-search-group .dropdown:focus-within,
188
+ .unified-search-group .dropdown.opened {
189
+ @apply !border-0 !outline-0 !border-transparent;
190
+ }
191
+
192
+ .dropdown:not(.transparent):not(.unified-search-group .dropdown):focus-within,
193
+ .dropdown:not(.transparent):not(.unified-search-group .dropdown).opened {
194
+ @apply !border-primary !outline !outline-1 !outline-primary;
195
+ outline-offset: 0 !important;
145
196
  }
146
197
 
147
198
  @media (min-width: 768px) {
148
199
  .dropdown {
149
- @apply h-10;
150
- padding: 0.625rem;
200
+ @apply h-10 py-2.5 px-2.5;
151
201
  }
152
202
  }
153
203
 
@@ -156,38 +206,25 @@ const chose = (f) => {
156
206
  }
157
207
 
158
208
  .dropdown-value {
159
- @apply overflow-hidden truncate min-w-0 flex-1 mr-2 text-sm;
160
- }
161
-
162
- @media (min-width: 768px) {
163
- .dropdown-value {
164
- font-size: 12px;
165
- }
209
+ @apply overflow-hidden truncate min-w-0 flex-1 text-sm md:text-xs;
166
210
  }
167
211
 
168
212
  .dropdown-arrow {
169
- @apply w-4 h-4 transition-all duration-300;
170
- position: absolute;
171
- right: 0.75rem;
172
- top: 50%;
173
- transform: translateY(-50%);
174
- display: flex;
175
- align-items: center;
176
- justify-content: center;
213
+ @apply w-4 h-4 transition-all duration-300 flex-shrink-0;
177
214
  }
178
215
 
179
216
  .dropdown-menu-portal {
180
- @apply rounded-xl shadow-2xl bg-dark-300 border border-dark-600 overflow-x-auto overflow-y-auto touch-pan-x touch-pan-y;
181
- backdrop-filter: blur(12px);
182
- box-shadow: 0 20px 25px -5px oklch(0 0 0 / 0.4), 0 10px 10px -5px oklch(0 0 0 / 0.2),
183
- 0 0 0 1px oklch(1 0 0 / 0.05);
217
+ @apply rounded-xl z-modal border-2 border-dark-650 bg-dark-400 shadow-dropdown;
218
+ min-width: 200px;
219
+ max-width: min(90vw, 600px);
220
+ overflow-x: auto;
221
+ overflow-y: auto;
184
222
  overscroll-behavior: contain;
223
+ touch-action: pan-x pan-y;
185
224
  -webkit-overflow-scrolling: touch;
186
225
  scrollbar-width: thin;
187
- scrollbar-color: oklch(0.35 0 0) oklch(0.19 0 0);
188
- z-index: 1000;
189
- min-width: 200px;
190
- max-width: 90vw;
226
+ scrollbar-color: theme('colors.dark.750') theme('colors.dark.350');
227
+ scrollbar-gutter: stable;
191
228
  }
192
229
 
193
230
  .dropdown-menu-portal::-webkit-scrollbar {
@@ -196,43 +233,40 @@ const chose = (f) => {
196
233
  }
197
234
 
198
235
  .dropdown-menu-portal::-webkit-scrollbar-track {
199
- background: oklch(0.19 0 0);
236
+ @apply bg-transparent;
237
+ margin: 12px 0;
200
238
  }
201
239
 
202
240
  .dropdown-menu-portal::-webkit-scrollbar-thumb {
203
- background: oklch(0.35 0 0);
204
- border-radius: 3px;
241
+ @apply bg-dark-750 rounded-full;
242
+ border: 2px solid transparent;
243
+ background-clip: padding-box;
205
244
  }
206
245
 
207
246
  .dropdown-menu-portal::-webkit-scrollbar-thumb:hover {
208
- background: oklch(0.45 0 0);
247
+ @apply bg-dark-800;
209
248
  }
210
249
 
211
250
  .dropdown-item {
212
- @apply cursor-pointer text-left w-full text-white transition-all duration-200 flex items-center justify-between;
213
- padding: 0.75rem 1rem;
214
- font-size: 0.875rem;
215
- font-weight: 500;
216
- border-bottom: 1px solid rgba(61, 62, 68, 0.3);
251
+ @apply cursor-pointer text-left text-white transition-all duration-200 flex items-center justify-between;
252
+ @apply px-4 py-3 text-sm font-medium border-b border-dark-625/30;
253
+ min-width: 100%;
217
254
  }
218
255
 
219
256
  .dropdown-item:last-child {
220
- border-bottom: none;
257
+ @apply border-b-0;
221
258
  }
222
259
 
223
260
  .dropdown-item:hover {
224
- @apply bg-dark-600;
225
- color: oklch(1 0 0);
261
+ @apply bg-dark-550 text-white;
226
262
  }
227
263
 
228
264
  .dropdown-item:active {
229
- @apply bg-dark-650;
230
- box-shadow: inset 0 2px 4px oklch(0 0 0 / 0.4);
265
+ @apply bg-dark-650 shadow-input-inset;
231
266
  }
232
267
 
233
268
  .dropdown-item.selected {
234
- background: oklch(0.72 0.15 145 / 0.15);
235
- color: oklch(0.72 0.15 145);
269
+ @apply bg-primary/15 text-primary;
236
270
  }
237
271
 
238
272
  .dropdown-item:first-child {
@@ -244,37 +278,10 @@ const chose = (f) => {
244
278
  }
245
279
 
246
280
  .dropdown-item-text {
247
- @apply pr-2;
248
- white-space: nowrap;
249
- overflow: visible;
281
+ @apply pr-2 whitespace-nowrap;
250
282
  }
251
283
 
252
284
  .dropdown-item svg {
253
- @apply w-4 h-4;
254
- color: oklch(0.72 0.15 145);
255
- }
256
-
257
- .dropdown-fade-enter-active {
258
- @apply transition-all duration-300;
259
- }
260
-
261
- .dropdown-fade-leave-active {
262
- @apply transition-all duration-200;
263
- }
264
-
265
- .dropdown-fade-enter-from {
266
- @apply opacity-0;
267
- transform: translateY(-8px) scale(0.95);
268
- }
269
-
270
- .dropdown-fade-leave-to {
271
- @apply opacity-0;
272
- transform: translateY(-4px) scale(0.98);
273
- }
274
-
275
- .dropdown-fade-enter-to,
276
- .dropdown-fade-leave-from {
277
- @apply opacity-100;
278
- transform: translateY(0) scale(1);
285
+ @apply w-4 h-4 text-primary;
279
286
  }
280
287
  </style>