@nexxtmove/ui 1.2.5 → 1.2.6

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@nexxtmove/ui",
3
3
  "type": "module",
4
- "version": "1.2.5",
4
+ "version": "1.2.6",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  "./nuxt": "./dist/nuxt.js",
11
11
  "./ui.css": "./dist/ui.css",
12
12
  "./dist/ui.css": "./dist/ui.css",
13
- "./theme": "./tailwind/nexxtmove.tailwind.theme.css",
13
+ "./theme": "./tailwind/theme.css",
14
14
  "./components.json": "./src/components.json",
15
15
  "./components/*": "./src/components/*"
16
16
  },
@@ -36,12 +36,12 @@
36
36
  "@eslint/js": "^10.0.1",
37
37
  "@nuxt/kit": "^4.5.2",
38
38
  "@nuxt/schema": "^4.5.2",
39
- "@storybook/addon-a11y": "^10.5.7",
39
+ "@storybook/addon-a11y": "^10.5.10",
40
40
  "@storybook/addon-designs": "^11.1.4",
41
- "@storybook/addon-docs": "^10.5.7",
42
- "@storybook/addon-vitest": "^10.5.7",
43
- "@storybook/builder-vite": "^10.5.7",
44
- "@storybook/vue3-vite": "^10.5.7",
41
+ "@storybook/addon-docs": "^10.5.10",
42
+ "@storybook/addon-vitest": "^10.5.10",
43
+ "@storybook/builder-vite": "^10.5.10",
44
+ "@storybook/vue3-vite": "^10.5.10",
45
45
  "@tailwindcss/vite": "^4.3.3",
46
46
  "@types/node": "^26.2.0",
47
47
  "@types/react": "^19.2.18",
@@ -55,7 +55,7 @@
55
55
  "eslint": "^10.8.1",
56
56
  "eslint-config-prettier": "^10.1.8",
57
57
  "eslint-plugin-prettier": "^5.5.6",
58
- "eslint-plugin-storybook": "10.5.7",
58
+ "eslint-plugin-storybook": "10.5.10",
59
59
  "eslint-plugin-vue": "^10.10.0",
60
60
  "flag-icons": "^7.5.0",
61
61
  "globals": "^17.11.0",
@@ -65,7 +65,7 @@
65
65
  "react": "^19.2.8",
66
66
  "react-dom": "^19.2.8",
67
67
  "remark-frontmatter": "^5.0.0",
68
- "storybook": "^10.5.7",
68
+ "storybook": "^10.5.10",
69
69
  "typescript-eslint": "^8.67.0",
70
70
  "vite": "^8.2.1",
71
71
  "vite-plugin-dts": "^5.0.3",
@@ -58,8 +58,7 @@ onMounted(async () => {
58
58
  <!-- Scrollable drum -->
59
59
  <div
60
60
  ref="yearScrollerRef"
61
- class="relative h-full snap-y snap-mandatory overflow-y-scroll [&::-webkit-scrollbar]:hidden"
62
- style="scrollbar-width: none"
61
+ class="relative scrollbar-none h-full snap-y snap-mandatory overflow-y-scroll"
63
62
  >
64
63
  <div class="h-18" />
65
64
  <button
@@ -208,7 +208,7 @@ defineExpose({ focus })
208
208
  role="listbox"
209
209
  aria-multiselectable="true"
210
210
  tabindex="0"
211
- class="max-h-56 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-cornflower-blue-200 [&::-webkit-scrollbar-thumb:hover]:bg-gray-300 [&::-webkit-scrollbar-track]:bg-transparent"
211
+ class="scrollbar-thin max-h-56 overflow-y-auto"
212
212
  >
213
213
  <li
214
214
  v-for="option in filteredOptions"
@@ -298,11 +298,7 @@ defineExpose({ focus })
298
298
  </button>
299
299
  </TransitionGroup>
300
300
  </Transition>
301
- <ul
302
- role="listbox"
303
- aria-multiselectable="true"
304
- class="max-h-56 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-cornflower-blue-200 [&::-webkit-scrollbar-thumb:hover]:bg-gray-300 [&::-webkit-scrollbar-track]:bg-transparent"
305
- >
301
+ <ul role="listbox" aria-multiselectable="true" class="scrollbar-thin max-h-56 overflow-y-auto">
306
302
  <li
307
303
  v-for="option in filteredOptions"
308
304
  :key="getValue(option)"
@@ -125,10 +125,7 @@ const onOpen = async () => {
125
125
  placeholder="Zoeken..."
126
126
  />
127
127
  </div>
128
- <ul
129
- role="listbox"
130
- class="max-h-60 overflow-y-auto [&::-webkit-scrollbar]:w-1.5 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-cornflower-blue-200 [&::-webkit-scrollbar-thumb:hover]:bg-gray-300 [&::-webkit-scrollbar-track]:bg-transparent"
131
- >
128
+ <ul role="listbox" class="scrollbar-thin max-h-60 overflow-y-auto">
132
129
  <li
133
130
  v-for="country in filteredCountries"
134
131
  :key="country.code"
@@ -1,6 +1,8 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, watchEffect } from 'vue'
3
3
  import AnimatedNumber from '../AnimatedNumber/AnimatedNumber.vue'
4
+ import Icon from '../Icon/Icon.vue'
5
+ import FloatingPanel from '../FloatingPanel/FloatingPanel.vue'
4
6
 
5
7
  interface NexxtProgressBarProps {
6
8
  variant?: 'stepper' | 'percentage'
@@ -15,7 +17,7 @@ defineOptions({
15
17
  name: 'NexxtProgressBar',
16
18
  })
17
19
 
18
- defineEmits(['update:currentStep'])
20
+ const emit = defineEmits(['update:currentStep'])
19
21
 
20
22
  const {
21
23
  variant = 'stepper',
@@ -55,6 +57,11 @@ const stepDigits = computed(() => String(Math.max(steps, 0)).length)
55
57
  // the compact treatment (current title + "x/y" counter) at every breakpoint.
56
58
  const isCompact = computed(() => hasTitles.value && (stepTitles?.length ?? 0) > maxInlineSteps)
57
59
 
60
+ const selectStep = (index: number, close: () => void) => {
61
+ close()
62
+ if (index < clampedStep.value) emit('update:currentStep', index)
63
+ }
64
+
58
65
  watchEffect(() => {
59
66
  if (stepTitles && stepTitles.length !== steps) {
60
67
  console.warn(
@@ -110,10 +117,64 @@ watchEffect(() => {
110
117
  <span>{{ steps }}</span>
111
118
  </div>
112
119
  </div>
120
+ <div v-if="isCompact" class="order-first flex justify-center">
121
+ <FloatingPanel placement="bottom">
122
+ <template #trigger="{ isOpen, toggle }">
123
+ <button
124
+ type="button"
125
+ class="flex cursor-pointer items-center gap-1.5 rounded-xs body-normal text-sapphire-500 transition-colors duration-200 hover:text-sapphire-400 focus-visible:outline-3"
126
+ aria-haspopup="menu"
127
+ :aria-expanded="isOpen"
128
+ :aria-label="`Stap ${displayStep} van ${steps}: ${stepTitles?.[clampedStep]}. Kies een stap`"
129
+ @click="toggle"
130
+ >
131
+ {{ stepTitles?.[clampedStep] }}
132
+ <Icon
133
+ name="chevron-down"
134
+ class="text-xs transition-transform duration-200"
135
+ :class="{ 'rotate-180': isOpen }"
136
+ aria-hidden="true"
137
+ />
138
+ </button>
139
+ </template>
140
+
141
+ <template #content="{ close }">
142
+ <ol
143
+ role="menu"
144
+ class="scrollbar-thin max-h-72 min-w-52 overflow-y-auto rounded-lg border border-gray-200 bg-white py-1"
145
+ aria-label="Progress steps"
146
+ >
147
+ <li v-for="(title, index) in stepTitles" :key="title">
148
+ <button
149
+ type="button"
150
+ role="menuitem"
151
+ class="flex w-full items-center gap-2 p-3 text-left small-normal whitespace-nowrap transition-colors duration-200 focus:outline-none"
152
+ :class="
153
+ index > clampedStep
154
+ ? 'cursor-default text-gray-400'
155
+ : 'cursor-pointer text-gray-700 hover:bg-gray-100 hover:text-sapphire-400 focus-visible:bg-gray-100'
156
+ "
157
+ :disabled="index > clampedStep"
158
+ :aria-current="index === clampedStep ? 'step' : undefined"
159
+ @click="selectStep(index, close)"
160
+ >
161
+ <span
162
+ class="w-(--step-number-width) shrink-0 text-right tabular-nums"
163
+ :style="{ '--step-number-width': `${stepDigits}ch` }"
164
+ aria-hidden="true"
165
+ >
166
+ {{ index + 1 }}
167
+ </span>
168
+ <span :class="index === clampedStep ? 'text-sapphire-500' : ''">{{ title }}</span>
169
+ </button>
170
+ </li>
171
+ </ol>
172
+ </template>
173
+ </FloatingPanel>
174
+ </div>
113
175
  <ol
114
- v-if="hasTitles"
115
- class="flex @max-md:order-first"
116
- :class="isCompact ? 'order-first justify-center' : 'justify-between @max-md:justify-center'"
176
+ v-else-if="hasTitles"
177
+ class="flex justify-between @max-md:order-first @max-md:justify-center"
117
178
  aria-label="Progress steps"
118
179
  >
119
180
  <li
@@ -121,15 +182,8 @@ watchEffect(() => {
121
182
  :key="title"
122
183
  class="rounded-xs transition-colors duration-500 focus-visible:outline-3"
123
184
  :class="[
124
- isCompact
125
- ? index === clampedStep
126
- ? 'body-normal'
127
- : 'hidden'
128
- : [
129
- '@max-md:body-normal @min-md:small-normal',
130
- index === clampedStep ? '@max-md:inline' : '@max-md:hidden',
131
- ],
132
- index === clampedStep ? 'text-sapphire-500' : '',
185
+ '@max-md:body-normal @min-md:small-normal',
186
+ index === clampedStep ? 'text-sapphire-500 @max-md:inline' : '@max-md:hidden',
133
187
  index < clampedStep ? 'cursor-pointer duration-200! hover:text-sapphire-400' : '',
134
188
  ]"
135
189
  :aria-current="index === clampedStep ? 'step' : undefined"
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Hand-written utilities.
3
+ *
4
+ * The other files in this folder are generated by the Figma design-tokens
5
+ * plugin and get overwritten on every token sync, so anything we author by
6
+ * hand lives here. It is pulled in through `tailwind/theme.css`, the entry
7
+ * behind the `@nexxtmove/ui/theme` export.
8
+ */
9
+
10
+ /* Slim, branded scrollbar for scrollable panels (dropdowns, lists, drawers). */
11
+ @utility scrollbar-thin {
12
+ scrollbar-width: thin;
13
+ scrollbar-color: var(--color-cornflower-blue-200) transparent;
14
+
15
+ &::-webkit-scrollbar {
16
+ @apply h-1.5 w-1.5;
17
+ }
18
+
19
+ &::-webkit-scrollbar-track {
20
+ @apply bg-transparent;
21
+ }
22
+
23
+ &::-webkit-scrollbar-thumb {
24
+ @apply rounded-full bg-cornflower-blue-200 transition-colors duration-200;
25
+ }
26
+
27
+ &::-webkit-scrollbar-thumb:hover {
28
+ @apply bg-gray-300;
29
+ }
30
+ }
31
+
32
+ /* Scrollable, but without a visible scrollbar. */
33
+ @utility scrollbar-none {
34
+ scrollbar-width: none;
35
+
36
+ &::-webkit-scrollbar {
37
+ display: none;
38
+ }
39
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Entry point behind the `@nexxtmove/ui/theme` export.
3
+ *
4
+ * Keep this file free of anything generated: `nexxtmove.tailwind.theme.css`
5
+ * (and the utilities/components it imports) is overwritten by the Figma
6
+ * design-tokens sync, so hand-written CSS belongs in the custom file below.
7
+ */
8
+
9
+ @import './nexxtmove.tailwind.theme.css';
10
+ @import './nexxtmove.tailwind.custom.css';