@teammodlr/ui-kit 3.0.0-beta.7 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/lib/components/checkbox/Checkbox.vue.d.ts +4 -4
  2. package/lib/components/clearbutton/ClearButton.vue.d.ts +7 -0
  3. package/lib/components/clearbutton/style/ClearButton.css.d.ts +2 -0
  4. package/lib/components/clearbutton/style/index.d.ts +1 -0
  5. package/lib/components/colorpicker/ColorPicker.vue.d.ts +0 -1
  6. package/lib/components/colorpicker/style/ColorPicker.css.d.ts +1 -0
  7. package/lib/components/dialog/style/Dialog.css.d.ts +2 -0
  8. package/lib/components/drawer/Drawer.vue.d.ts +142 -0
  9. package/lib/components/drawer/style/Drawer.css.d.ts +33 -0
  10. package/lib/components/drawer/style/index.d.ts +1 -0
  11. package/lib/components/hovercard/HoverCard.vue.d.ts +122 -0
  12. package/lib/components/hovercard/style/HoverCard.css.d.ts +3 -0
  13. package/lib/components/hovercard/style/index.d.ts +1 -0
  14. package/lib/components/index.d.ts +4 -0
  15. package/lib/components/input/Input.vue.d.ts +20 -5
  16. package/lib/components/input/style/Input.css.d.ts +4 -0
  17. package/lib/components/paneldialog/PanelDialog.vue.d.ts +167 -0
  18. package/lib/components/paneldialog/style/PanelDialog.css.d.ts +8 -0
  19. package/lib/components/paneldialog/style/index.d.ts +1 -0
  20. package/lib/components/popover/Popover.vue.d.ts +113 -0
  21. package/lib/components/popover/style/Popover.css.d.ts +4 -0
  22. package/lib/components/popover/style/index.d.ts +1 -0
  23. package/lib/components/radio/Radio.vue.d.ts +5 -5
  24. package/lib/components/radiobutton/RadioButton.vue.d.ts +4 -4
  25. package/lib/components/select/Select.vue.d.ts +72 -91
  26. package/lib/components/select/style/Select.css.d.ts +9 -1
  27. package/lib/components/switch/Switch.vue.d.ts +4 -4
  28. package/lib/components/textarea/Textarea.vue.d.ts +16 -5
  29. package/lib/components/textarea/style/Textarea.css.d.ts +2 -0
  30. package/lib/composables/useInput.d.ts +9 -2
  31. package/lib/index.cjs.js +3 -3
  32. package/lib/index.es.js +11870 -9642
  33. package/lib/style.css +1 -1
  34. package/lib/tsconfig.app.tsbuildinfo +1 -0
  35. package/package.json +7 -4
  36. package/src/components/cardcontextmenu/style/Dropdown.css.ts +7 -0
  37. package/src/components/clearbutton/ClearButton.vue +39 -0
  38. package/src/components/clearbutton/style/ClearButton.css.ts +37 -0
  39. package/src/components/clearbutton/style/index.ts +1 -0
  40. package/src/components/colorpicker/ColorPicker.vue +8 -11
  41. package/src/components/colorpicker/examples/basic.vue +8 -17
  42. package/src/components/colorpicker/style/ColorPicker.css.ts +6 -1
  43. package/src/components/dialog/Dialog.vue +2 -5
  44. package/src/components/dialog/style/Dialog.css.ts +30 -0
  45. package/src/components/drawer/Drawer.vue +276 -0
  46. package/src/components/drawer/examples/basic.vue +15 -0
  47. package/src/components/drawer/examples/custom-title.vue +21 -0
  48. package/src/components/drawer/examples/index.stories.ts +24 -0
  49. package/src/components/drawer/examples/index.ts +7 -0
  50. package/src/components/drawer/examples/no-mask.vue +15 -0
  51. package/src/components/drawer/examples/no-outside-close.vue +15 -0
  52. package/src/components/drawer/examples/placements.vue +28 -0
  53. package/src/components/drawer/examples/with-footer.vue +21 -0
  54. package/src/components/drawer/examples/with-trigger.vue +13 -0
  55. package/src/components/drawer/style/Drawer.css.ts +208 -0
  56. package/src/components/drawer/style/index.ts +1 -0
  57. package/src/components/dropdown/Dropdown.vue +1 -1
  58. package/src/components/hovercard/HoverCard.vue +163 -0
  59. package/src/components/hovercard/style/HoverCard.css.ts +175 -0
  60. package/src/components/hovercard/style/index.ts +1 -0
  61. package/src/components/index.ts +4 -0
  62. package/src/components/input/Input.vue +52 -4
  63. package/src/components/input/examples/clearable.vue +18 -0
  64. package/src/components/input/examples/index.stories.ts +3 -1
  65. package/src/components/input/examples/index.ts +1 -0
  66. package/src/components/input/style/Input.css.ts +19 -0
  67. package/src/components/messageprovider/MessageProvider.vue +33 -7
  68. package/src/components/paneldialog/PanelDialog.vue +500 -0
  69. package/src/components/paneldialog/examples/basic.vue +36 -0
  70. package/src/components/paneldialog/examples/index.stories.ts +22 -0
  71. package/src/components/paneldialog/examples/index.ts +2 -0
  72. package/src/components/paneldialog/examples/modal.vue +31 -0
  73. package/src/components/paneldialog/style/PanelDialog.css.ts +90 -0
  74. package/src/components/paneldialog/style/index.ts +1 -0
  75. package/src/components/popover/Popover.vue +155 -0
  76. package/src/components/popover/examples/arrow.vue +47 -0
  77. package/src/components/popover/examples/basic.vue +15 -0
  78. package/src/components/popover/examples/index.stories.ts +19 -0
  79. package/src/components/popover/examples/index.ts +4 -0
  80. package/src/components/popover/examples/placement.vue +59 -0
  81. package/src/components/popover/examples/variant.vue +30 -0
  82. package/src/components/popover/style/Popover.css.ts +203 -0
  83. package/src/components/popover/style/index.ts +1 -0
  84. package/src/components/select/Select.vue +122 -42
  85. package/src/components/select/examples/clearable.vue +18 -0
  86. package/src/components/select/examples/fill.vue +52 -0
  87. package/src/components/select/examples/index.stories.ts +3 -1
  88. package/src/components/select/examples/index.ts +2 -0
  89. package/src/components/select/style/Select.css.ts +140 -24
  90. package/src/components/tab/Tab.vue +1 -1
  91. package/src/components/tab/style/Tab.css.ts +6 -0
  92. package/src/components/textarea/Textarea.vue +40 -4
  93. package/src/components/textarea/examples/clearable.vue +16 -0
  94. package/src/components/textarea/examples/index.stories.ts +2 -1
  95. package/src/components/textarea/examples/index.ts +1 -0
  96. package/src/components/textarea/style/Textarea.css.ts +10 -0
  97. package/src/composables/useInput.ts +10 -2
@@ -0,0 +1 @@
1
+ export * from './Popover.css';
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <PopoverRoot :open="isOpen" @update:open="handleOpenChange">
3
- <div ref="selectRef" tabindex="-1">
3
+ <div ref="selectRef" tabindex="-1" :class="fillRootClass">
4
4
  <label v-if="label" :for="id" :class="style.label" :id="`${id}-label`">
5
5
  {{ label }}
6
6
  </label>
@@ -16,7 +16,7 @@
16
16
  <div :class="selectComputedClasses">
17
17
  <template v-if="multiple && Array.isArray(selected) && selected.length > 0">
18
18
  <MTag v-for="value in selectedMax" :key="value" :closeable="true"
19
- @close="event => removeSelected(event, value)" :size="size">
19
+ @close="() => removeSelected(value)" :size="size">
20
20
  {{ getSelectedLabel(value) }}
21
21
  </MTag>
22
22
  <template v-if="selectedCountNotShown > 0">
@@ -26,15 +26,16 @@
26
26
  </template>
27
27
  </template>
28
28
  <template v-else-if="!multiple && selected">
29
- {{ getSelectedLabel(selected) }}
29
+ <span :class="fillLabelClass">{{ getSelectedLabel(selected) }}</span>
30
30
  </template>
31
31
  <template v-else>
32
- <div :class="style.placeholder">{{ placeholder }}</div>
32
+ <div :class="[style.placeholder, fillLabelClass]">{{ placeholder }}</div>
33
33
  </template>
34
34
  <span :class="selectComputedArrowClasses">
35
35
  <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-chevron-down-icon lucide-chevron-down"><path d="m6 9 6 6 6-6"/></svg>
36
36
  </span>
37
37
  </div>
38
+ <MClearButton v-if="showClear" :class="style.clear" @clear="clearSelected" />
38
39
  </div>
39
40
  </PopoverTrigger>
40
41
 
@@ -71,24 +72,30 @@
71
72
  <input v-if="searchable" type="text" ref="searchRef" v-model="search" placeholder="Search"
72
73
  :class="style.searchInput" :data-input="`select-menu-search-${id}`" />
73
74
  </div>
74
- <div :class="style.options">
75
- <div v-for="(option, index) in computedOptions" :key="index" ref="optionsRef" :class="{
76
- [style.option]: true,
77
- [style.optionSelected]: option.active,
78
- [style.optionFocused]: selectedIndex === index
79
- }" @click.prevent="option.onClick" @mouseenter="selectedIndex = index"
80
- :data-element="`select-menu-option-${id}-${option.value}`">
81
- <span :class="style.optionIcon">
82
- <svg v-if="option.active" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
83
- <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"></path>
84
- </svg>
85
- </span>
86
- <span :class="style.optionLabel">{{ option.label }}</span>
87
- </div>
88
- <template v-if="computedOptions.length === 0">
89
- <div :class="style.noResults">No results</div>
75
+ <div v-if="computedOptions.length === 0" :class="style.noResults">No results</div>
76
+ <VList
77
+ v-else
78
+ ref="virtualListRef"
79
+ :data="computedOptions"
80
+ :item-size="optionItemHeight"
81
+ :style="{ height: optionsHeight + 'px', padding: '4px' }"
82
+ >
83
+ <template #default="{ item, index }">
84
+ <div :class="[optionSizeClass, {
85
+ [style.option]: true,
86
+ [style.optionSelected]: item.active,
87
+ [style.optionFocused]: selectedIndex === index
88
+ }]" @click.prevent="item.onClick" @mouseenter="selectedIndex = index"
89
+ :data-element="`select-menu-option-${id}-${item.value}`">
90
+ <span :class="style.optionIcon">
91
+ <svg v-if="item.active" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
92
+ <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"></path>
93
+ </svg>
94
+ </span>
95
+ <span :class="style.optionLabel">{{ item.label }}</span>
96
+ </div>
90
97
  </template>
91
- </div>
98
+ </VList>
92
99
  </PopoverContent>
93
100
  </Transition>
94
101
  </PopoverPortal>
@@ -101,7 +108,7 @@
101
108
  </template>
102
109
 
103
110
  <script lang="ts">
104
- import { useInput } from '../../composables/useInput';
111
+ import { useInput, type InputEmitsMap } from '../../composables/useInput';
105
112
  import type { MaybeArray, Size } from '../../types/props';
106
113
  import { PopoverContent, PopoverPortal, PopoverRoot, PopoverTrigger } from 'reka-ui';
107
114
  import { useEventListener } from '@vueuse/core';
@@ -115,7 +122,13 @@ import {
115
122
  type PropType
116
123
  } from 'vue';
117
124
  import MTag from '../tag/Tag.vue';
125
+ import MClearButton from '../clearbutton/ClearButton.vue';
126
+ import { VList } from 'virtua/vue';
118
127
  import * as style from './style';
128
+
129
+ interface VListHandle {
130
+ scrollToIndex(index: number, opts?: { align?: 'start' | 'center' | 'end' | 'nearest' }): void;
131
+ }
119
132
  import { fade } from '../../styles/transitions.css';
120
133
  import { useInteractive } from '../../composables/useInteractive';
121
134
  import type { OnUpdateValue, OnUpdateValueImpl } from './types';
@@ -127,7 +140,10 @@ let shouldOpenNextFocusedSelect = false;
127
140
  export default defineComponent({
128
141
  name: 'MSelect',
129
142
  emits: {
130
- ...useInput.emits()
143
+ ...(useInput.emits() as unknown as InputEmitsMap),
144
+ 'on-open': () => true,
145
+ 'on-close': () => true,
146
+ clear: () => true
131
147
  },
132
148
  props: {
133
149
  ...useInput.props(),
@@ -184,7 +200,7 @@ export default defineComponent({
184
200
  default: false
185
201
  },
186
202
  error: {
187
- type: String
203
+ type: String as PropType<string | null>
188
204
  },
189
205
  allowBlank: {
190
206
  type: Boolean,
@@ -202,9 +218,26 @@ export default defineComponent({
202
218
  type: Boolean,
203
219
  default: false
204
220
  },
221
+ fill: {
222
+ type: Boolean,
223
+ default: false
224
+ },
225
+ noBorder: {
226
+ type: Boolean,
227
+ default: false
228
+ },
205
229
  zIndex: {
206
230
  type: Number
207
231
  },
232
+ clearable: {
233
+ type: Boolean,
234
+ default: false
235
+ },
236
+ // Value a single select resets to when cleared (e.g. a "Don't restrict" option)
237
+ clearValue: {
238
+ type: [String, Number, Boolean, Object] as PropType<string | number | boolean | object | null>,
239
+ default: undefined
240
+ },
208
241
  showDataOptions: {
209
242
  type: Boolean,
210
243
  default: true
@@ -214,6 +247,8 @@ export default defineComponent({
214
247
  },
215
248
  components: {
216
249
  MTag,
250
+ MClearButton,
251
+ VList,
217
252
  PopoverContent,
218
253
  PopoverPortal,
219
254
  PopoverRoot,
@@ -221,7 +256,7 @@ export default defineComponent({
221
256
  },
222
257
  setup(props, { emit, expose }) {
223
258
  const container = ref<HTMLElement | null>(null);
224
- const optionsRef = ref<HTMLElement[]>([]);
259
+ const virtualListRef = ref<VListHandle | null>(null);
225
260
  const searchRef = ref<HTMLInputElement>();
226
261
  const selectRef = ref<HTMLElement>();
227
262
  const popper = ref<HTMLElement>();
@@ -593,9 +628,34 @@ export default defineComponent({
593
628
  }
594
629
  }
595
630
 
596
- function removeSelected(event: MouseEvent, value: string | number) {
597
- event.preventDefault();
598
- event.stopPropagation();
631
+ const hasValue = computed(() => {
632
+ if (props.multiple) {
633
+ return Array.isArray(selected.value) && selected.value.length > 0;
634
+ }
635
+
636
+ if (props.clearValue !== undefined && selected.value === props.clearValue) {
637
+ return false;
638
+ }
639
+
640
+ return !!selected.value;
641
+ });
642
+
643
+ const showClear = computed(() => {
644
+ return props.clearable
645
+ && hasValue.value
646
+ && !disabled.value
647
+ && !loading.value;
648
+ });
649
+
650
+ function clearSelected() {
651
+ selected.value = props.multiple
652
+ ? []
653
+ : (props.clearValue !== undefined ? props.clearValue : '');
654
+ emit('clear');
655
+ container.value?.focus();
656
+ }
657
+
658
+ function removeSelected(value: string | number) {
599
659
  if (!props.multiple) {
600
660
  return;
601
661
  }
@@ -741,20 +801,36 @@ export default defineComponent({
741
801
  ]
742
802
  })
743
803
 
804
+ const optionItemHeightMap: Record<string, number> = { xs: 30, sm: 32, md: 38, lg: 42, xl: 46 };
805
+ const optionItemHeight = computed(() => optionItemHeightMap[props.size] ?? 38);
806
+ const optionsHeight = computed(() => {
807
+ const total = computedOptions.value.length * optionItemHeight.value + 8; // 8px = paddingTop+paddingBottom
808
+ return Math.min(total, 222);
809
+ });
810
+ const optionSizeClass = computed(() => style.optionSizes[props.size]);
811
+ const fillRootClass = computed(() => props.fill ? style.fillRoot : undefined);
812
+ const fillLabelClass = computed(() => props.fill ? style.fillLabel : undefined);
813
+
744
814
  const computedWrapperClasses = computed(() => {
745
- return [style.wrapper];
815
+ return [
816
+ style.wrapper,
817
+ { [style.fill]: props.fill }
818
+ ];
746
819
  });
747
820
 
748
821
  const selectComputedClasses = computed(() => {
749
822
  return [
750
823
  style.base,
824
+ style.sizes[props.size],
751
825
  {
826
+ [style.hasClear]: showClear.value,
752
827
  [style.selectedTags]:
753
828
  props.multiple &&
754
829
  Array.isArray(selected.value) &&
755
830
  selected.value.length > 0,
756
- [style.focused]: open.value || focused.value,
757
- // [`m-select--${props.size}`]: props.size,
831
+ [style.focused]: !props.noBorder && (open.value || focused.value),
832
+ [style.fillBase]: props.fill,
833
+ [style.noBorder]: props.noBorder,
758
834
  'm-select--disabled': disabled.value || loading.value,
759
835
  'm-select--focused': open.value || focused.value,
760
836
  'm-select--multiple': props.multiple,
@@ -784,21 +860,20 @@ export default defineComponent({
784
860
  if (!keyboardNavigation.value) {
785
861
  return;
786
862
  }
787
- if (typeof index !== 'undefined' && optionsRef.value) {
788
- optionsRef.value[index].scrollIntoView({
789
- block: 'nearest',
790
- inline: 'nearest'
791
- });
863
+ if (typeof index !== 'undefined') {
864
+ virtualListRef.value?.scrollToIndex(index, { align: 'nearest' });
792
865
  }
793
866
  });
794
867
 
795
868
  watch(open, (value: boolean) => {
796
869
  nextTick(() => {
797
870
  if (!value) {
871
+ emit('on-close');
798
872
  search.value = '';
799
873
  }
800
874
 
801
875
  if (value) {
876
+ emit('on-open');
802
877
  zIndex.value = nextZIndex();
803
878
  }
804
879
 
@@ -816,7 +891,7 @@ export default defineComponent({
816
891
  });
817
892
  }
818
893
 
819
- if (value && optionsRef.value) {
894
+ if (value) {
820
895
  const selectedValue = Array.isArray(selected.value)
821
896
  ? selected.value[0]
822
897
  : selected.value;
@@ -824,9 +899,7 @@ export default defineComponent({
824
899
  i => i.value === selectedValue
825
900
  );
826
901
  if (index !== -1) {
827
- optionsRef.value[index].scrollIntoView({
828
- block: 'nearest'
829
- });
902
+ nextTick(() => virtualListRef.value?.scrollToIndex(index, { align: 'nearest' }));
830
903
  selectedIndex.value = index;
831
904
  } else if (computedOptions.value.length > 0) {
832
905
  selectedIndex.value = 0;
@@ -894,7 +967,7 @@ export default defineComponent({
894
967
 
895
968
  return {
896
969
  container,
897
- optionsRef,
970
+ virtualListRef,
898
971
  searchRef,
899
972
  selectRef,
900
973
  popper,
@@ -922,13 +995,20 @@ export default defineComponent({
922
995
  getSelectedLabel,
923
996
  openSelect,
924
997
  removeSelected,
998
+ showClear,
999
+ clearSelected,
925
1000
  inputError,
926
1001
  transitionName,
927
1002
  inputListeners,
928
1003
  style,
929
1004
  focused,
930
1005
  fade,
931
- toggleAllItems
1006
+ toggleAllItems,
1007
+ optionItemHeight,
1008
+ optionsHeight,
1009
+ optionSizeClass,
1010
+ fillRootClass,
1011
+ fillLabelClass
932
1012
  };
933
1013
  }
934
1014
  });
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div style="display: flex; flex-direction: column; gap: 12px; max-width: 320px;">
3
+ <MSelect v-model="single" :options="options" clearable />
4
+ <MSelect v-model="multiple" :options="options" multiple clearable />
5
+ </div>
6
+ </template>
7
+
8
+ <script lang="ts" setup>
9
+ import { ref } from 'vue';
10
+
11
+ const options = Array.from({ length: 10 }, (_, i) => ({
12
+ value: i + 1,
13
+ label: `Option ${i + 1}`
14
+ }));
15
+
16
+ const single = ref(2);
17
+ const multiple = ref([1, 2]);
18
+ </script>
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <div style="display: grid; grid-template-columns: 120px 1fr 1fr; border: 1px solid #e5e7eb;">
3
+ <div style="padding: 6px 8px; font-size: 13px; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; background: #f9fafb; font-weight: 500;">Row 1</div>
4
+ <div style="height: 36px; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;">
5
+ <MSelect size="xs" v-model="row1Status" :options="statusOptions" fill no-border />
6
+ </div>
7
+ <div style="height: 36px; border-bottom: 1px solid #e5e7eb;">
8
+ <MSelect size="xs" v-model="row1Priority" :options="priorityOptions" fill no-border />
9
+ </div>
10
+
11
+ <div style="padding: 6px 8px; font-size: 13px; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb; background: #f9fafb; font-weight: 500;">Row 2</div>
12
+ <div style="height: 36px; border-right: 1px solid #e5e7eb; border-bottom: 1px solid #e5e7eb;">
13
+ <MSelect size="xs" v-model="row2Status" :options="statusOptions" fill no-border />
14
+ </div>
15
+ <div style="height: 36px; border-bottom: 1px solid #e5e7eb;">
16
+ <MSelect size="xs" v-model="row2Priority" :options="priorityOptions" fill no-border />
17
+ </div>
18
+
19
+ <div style="padding: 6px 8px; font-size: 13px; border-right: 1px solid #e5e7eb; background: #f9fafb; font-weight: 500;">Row 3</div>
20
+ <div style="height: 36px; border-right: 1px solid #e5e7eb;">
21
+ <MSelect size="xs" v-model="row3Status" :options="statusOptions" fill no-border />
22
+ </div>
23
+ <div style="height: 36px;">
24
+ <MSelect size="xs" v-model="row3Priority" :options="priorityOptions" fill no-border />
25
+ </div>
26
+ </div>
27
+ </template>
28
+
29
+ <script lang="ts" setup>
30
+ import { ref } from 'vue';
31
+
32
+ const statusOptions = [
33
+ { value: 'todo', label: 'To Do' },
34
+ { value: 'in_progress', label: 'In Progress' },
35
+ { value: 'in_review', label: 'In Review' },
36
+ { value: 'done', label: 'Done' }
37
+ ];
38
+
39
+ const priorityOptions = [
40
+ { value: 'low', label: 'Low' },
41
+ { value: 'medium', label: 'Medium' },
42
+ { value: 'high', label: 'High' },
43
+ { value: 'critical', label: 'Critical' }
44
+ ];
45
+
46
+ const row1Status = ref('in_progress');
47
+ const row1Priority = ref('high');
48
+ const row2Status = ref('todo');
49
+ const row2Priority = ref('medium');
50
+ const row3Status = ref('done');
51
+ const row3Priority = ref('low');
52
+ </script>
@@ -1,5 +1,5 @@
1
1
  import MSelect from '../Select.vue';
2
- import { MSelectBasic, MSelectSearchable, MSelectMultiple } from './index';
2
+ import { MSelectBasic, MSelectSearchable, MSelectMultiple, MSelectFill, MSelectClearable } from './index';
3
3
 
4
4
  import { createStory, sizeArgType } from '../../../__storybook__';
5
5
 
@@ -14,3 +14,5 @@ export default {
14
14
  export const Basic = createStory(MSelectBasic);
15
15
  export const Searchable = createStory(MSelectSearchable);
16
16
  export const Multiple = createStory(MSelectMultiple);
17
+ export const Fill = createStory(MSelectFill);
18
+ export const Clearable = createStory(MSelectClearable);
@@ -1,3 +1,5 @@
1
1
  export { default as MSelectBasic } from './basic.vue';
2
2
  export { default as MSelectSearchable } from './searchable.vue';
3
3
  export { default as MSelectMultiple } from './multiple.vue';
4
+ export { default as MSelectFill } from './fill.vue';
5
+ export { default as MSelectClearable } from './clearable.vue';
@@ -6,7 +6,7 @@ import {
6
6
  } from '@vanilla-extract/css';
7
7
  import { themeVars } from '../../../styles/theme.css';
8
8
 
9
- const sizes = {
9
+ const heights = {
10
10
  xs: '26px',
11
11
  sm: '30px',
12
12
  md: '38px',
@@ -42,7 +42,7 @@ export const wrapper = style({
42
42
 
43
43
  export const base = style({
44
44
  vars: {
45
- [vars.height]: sizes.md,
45
+ [vars.height]: heights.md,
46
46
  [vars.radius]: borderRadiuses.md,
47
47
  [vars.paddingX]: themeVars.space[2],
48
48
  [vars.paddingY]: themeVars.space[0],
@@ -189,8 +189,7 @@ export const menu = style({
189
189
  borderRadius: '4px',
190
190
  border: `1px solid ${themeVars.color.gray[200]}`,
191
191
  boxShadow: themeVars.shadow.md,
192
- maxHeight: '230px',
193
- overflowY: 'auto'
192
+ overflow: 'hidden'
194
193
  });
195
194
 
196
195
  export const placeholder = style({
@@ -199,11 +198,7 @@ export const placeholder = style({
199
198
  });
200
199
 
201
200
  export const search = style({
202
- // padding: `${themeVars.space[1]} ${themeVars.space[1]} 0`,
203
201
  backgroundColor: '#FFFFFF',
204
- position: 'sticky',
205
- top: 0,
206
- zIndex: 1,
207
202
  borderBottom: `1px solid ${themeVars.color.gray[200]}`,
208
203
  display: 'flex'
209
204
  });
@@ -219,10 +214,7 @@ export const searchInput = style({
219
214
  });
220
215
 
221
216
  export const options = style({
222
- padding: themeVars.space[1],
223
- display: 'flex',
224
- flexDirection: 'column',
225
- gap: themeVars.space[0.5]
217
+ overflow: 'hidden'
226
218
  });
227
219
 
228
220
  export const option = style({
@@ -234,10 +226,7 @@ export const option = style({
234
226
  display: 'flex',
235
227
  alignItems: 'center',
236
228
  cursor: 'pointer',
237
- minHeight: '36px',
238
- fontSize: themeVars.fontSize.base,
239
- paddingBlock: themeVars.space['1.5'],
240
- paddingInline: themeVars.space['3'],
229
+ marginBottom: '2px',
241
230
  gap: themeVars.space[2],
242
231
  color: vars.optionColor,
243
232
  transition: 'background-color 0.05s ease-in-out',
@@ -280,6 +269,39 @@ export const optionSelected = style({
280
269
 
281
270
  export const optionLabel = style({});
282
271
 
272
+ export const optionSizes = styleVariants({
273
+ xs: {
274
+ minHeight: '28px',
275
+ fontSize: themeVars.fontSize.small,
276
+ paddingBlock: themeVars.space['1'],
277
+ paddingInline: themeVars.space['2']
278
+ },
279
+ sm: {
280
+ minHeight: '30px',
281
+ fontSize: themeVars.fontSize.base,
282
+ paddingBlock: themeVars.space['1'],
283
+ paddingInline: themeVars.space['2.5']
284
+ },
285
+ md: {
286
+ minHeight: '36px',
287
+ fontSize: themeVars.fontSize.base,
288
+ paddingBlock: themeVars.space['1.5'],
289
+ paddingInline: themeVars.space['3']
290
+ },
291
+ lg: {
292
+ minHeight: '40px',
293
+ fontSize: themeVars.fontSize.large,
294
+ paddingBlock: themeVars.space['2'],
295
+ paddingInline: themeVars.space['3']
296
+ },
297
+ xl: {
298
+ minHeight: '44px',
299
+ fontSize: themeVars.fontSize.large,
300
+ paddingBlock: themeVars.space['2.5'],
301
+ paddingInline: themeVars.space['3']
302
+ }
303
+ });
304
+
283
305
  export const checkAll = style({
284
306
  display: 'flex',
285
307
  alignItems: 'center',
@@ -357,13 +379,15 @@ export const noResults = style({
357
379
  fontSize: themeVars.fontSize.small
358
380
  });
359
381
 
360
- export const clearable = style({
361
- width: themeVars.space[4],
362
- height: themeVars.space[4],
382
+ export const clear = style({
363
383
  position: 'absolute',
364
- right: themeVars.space[2],
365
- top: '0',
366
- display: 'flex'
384
+ top: '50%',
385
+ right: '2.25rem',
386
+ transform: 'translateY(-50%)'
387
+ });
388
+
389
+ export const hasClear = style({
390
+ paddingRight: '3.75rem'
367
391
  });
368
392
 
369
393
  export const arrow = style({
@@ -371,12 +395,104 @@ export const arrow = style({
371
395
  height: themeVars.space[4],
372
396
  position: 'absolute',
373
397
  right: themeVars.space[3],
374
- top: themeVars.space[3],
398
+ top: '50%',
399
+ transform: 'translateY(-50%)',
375
400
  display: 'flex',
376
401
  color: themeVars.color.gray[500],
377
402
  transition: 'transform 0.3s ease',
378
403
  });
379
404
 
380
405
  export const arrowOpen = style({
381
- transform: 'rotate(180deg)',
406
+ transform: 'translateY(-50%) rotate(180deg)',
382
407
  })
408
+
409
+ export const fillRoot = style({
410
+ display: 'flex',
411
+ flexDirection: 'column',
412
+ height: '100%',
413
+ width: '100%'
414
+ });
415
+
416
+ export const fill = style({
417
+ flexGrow: 1,
418
+ width: '100%',
419
+ minHeight: 0
420
+ });
421
+
422
+ export const sizes = styleVariants({
423
+ xs: {
424
+ vars: {
425
+ [vars.height]: heights.xs,
426
+ [vars.radius]: borderRadiuses.xs,
427
+ [vars.paddingX]: themeVars.space[1]
428
+ },
429
+ fontSize: themeVars.fontSize.small
430
+ },
431
+ sm: {
432
+ vars: {
433
+ [vars.height]: heights.sm,
434
+ [vars.radius]: borderRadiuses.sm,
435
+ [vars.paddingX]: themeVars.space[1.5]
436
+ },
437
+ fontSize: themeVars.fontSize.small
438
+ },
439
+ md: {
440
+ vars: {
441
+ [vars.height]: heights.md,
442
+ [vars.radius]: borderRadiuses.md
443
+ }
444
+ },
445
+ lg: {
446
+ vars: {
447
+ [vars.height]: heights.lg,
448
+ [vars.radius]: borderRadiuses.lg,
449
+ [vars.paddingX]: themeVars.space[2.5]
450
+ },
451
+ fontSize: themeVars.fontSize.large
452
+ },
453
+ xl: {
454
+ vars: {
455
+ [vars.height]: heights.xl,
456
+ [vars.radius]: borderRadiuses.xl,
457
+ [vars.paddingX]: themeVars.space[3]
458
+ },
459
+ fontSize: themeVars.fontSize.large
460
+ }
461
+ });
462
+
463
+ export const fillBase = style({
464
+ minHeight: 'unset',
465
+ height: '100%',
466
+ lineHeight: 'normal',
467
+ display: 'flex',
468
+ alignItems: 'center',
469
+ overflow: 'hidden',
470
+ paddingRight: '2rem'
471
+ });
472
+
473
+ export const fillLabel = style({
474
+ overflow: 'hidden',
475
+ whiteSpace: 'nowrap',
476
+ textOverflow: 'ellipsis',
477
+ flex: 1,
478
+ minWidth: 0
479
+ });
480
+
481
+ export const noBorder = style({
482
+ vars: {
483
+ [vars.borderColor]: 'transparent'
484
+ },
485
+ borderRadius: 0,
486
+ boxShadow: 'none',
487
+ ':hover': {
488
+ vars: {
489
+ [vars.borderColor]: 'transparent'
490
+ }
491
+ },
492
+ ':focus': {
493
+ vars: {
494
+ [vars.borderColor]: 'transparent'
495
+ },
496
+ boxShadow: 'none'
497
+ }
498
+ });
@@ -14,7 +14,7 @@
14
14
 
15
15
  <teleport v-if="teleportTo && hasContent" :to="teleportTo">
16
16
  <TabsContent :value="computedValue" as-child>
17
- <div>
17
+ <div style="outline: none">
18
18
  <slot />
19
19
  </div>
20
20
  </TabsContent>
@@ -91,6 +91,12 @@ export const baseButton = style({
91
91
  vars: {
92
92
  color: themeVars.color.blue[400],
93
93
  },
94
+ },
95
+ '&:focus': {
96
+ outline: 'none',
97
+ },
98
+ '&:focus-visible': {
99
+ outline: 'none',
94
100
  }
95
101
  }
96
102
  });