Compare commits

...

298 Commits

Author SHA1 Message Date
Benjamin Canac
268e29b041 chore(release): v3.2.0 2025-06-25 17:00:05 +02:00
Benjamin Canac
b0364b96b7 fix(SelectMenu): dynamic input size 2025-06-25 16:04:04 +02:00
Benjamin Canac
ba3c6e8788 fix(InputMenu/SelectMenu): dynamic empty size
Resolves #4377
2025-06-25 16:01:04 +02:00
Benjamin Canac
01da3cbf31 docs(components): add illustrations 2025-06-25 11:46:58 +02:00
Estéban
595fc64515 feat(Table): add body-top / body-bottom slots (#4354)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-25 11:17:02 +02:00
Estéban
81569713e9 feat(Modal/Slideover): add actions slot (#4358)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-24 18:03:53 +02:00
Jack Bobakanoosh
1a8feb751e fix(Form): expose reactive fields (#4386) 2025-06-24 17:56:12 +02:00
Maxime Pauvert
1d281e915a docs(app): use findPageBreadcrumb from @nuxt/content (#4359) 2025-06-24 17:45:52 +02:00
Artea
c3adc381c9 fix(Card/Drawer/Modal): prevent scrollbars overflow (#4368)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-24 17:16:13 +02:00
Lars Eberhardt
edca3bcb74 fix(Table): use tr as separator (#4083)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-24 17:09:04 +02:00
Benjamin Canac
8f32ee3d24 chore(deps): update @nuxt/ui-pro 2025-06-24 16:42:56 +02:00
Hugo Richard
9172bb7dc2 docs(app): add copy markdown button (#4369) 2025-06-24 12:11:23 +02:00
renovate[bot]
32dae2e002 chore(deps): update dependency better-sqlite3 to v12 (v3) (#4385)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 14:39:02 +02:00
Estéban
be41aed1f3 fix(components): remove default md size on buttons (#4357) 2025-06-23 12:47:30 +02:00
renovate[bot]
bf678412ca chore(deps): lock file maintenance (v3) (#4389)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 12:39:12 +02:00
renovate[bot]
a999600e9f chore(deps): update all non-major dependencies (v3) (#4362)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-23 12:05:11 +02:00
Benjamin Canac
04f12adc5b docs(examples): use useClipboard instead of navigator.clipboard 2025-06-18 14:16:54 +02:00
Sigve Hansen
abfd0ede03 fix(Toaster): smoother visibility transition for stacked toasts (#4367) 2025-06-17 16:56:33 +02:00
Vachmara
2fa8db64dd fix(NavigationMenu): nested accordion context at every level (#4363)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-17 10:49:07 +02:00
Benjamin Canac
52f1963833 chore(cli): improve templates 2025-06-17 10:10:08 +02:00
renovate[bot]
9a83c9c7f4 chore(deps): update devdependency happy-dom to v18 (v3) (#4353)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 23:03:17 +02:00
renovate[bot]
f2510cb342 chore(deps): lock file maintenance (v3) (#4352)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-16 12:52:42 +02:00
Estéban
4dd56c8111 fix(Pagination): match default button size (#4350) 2025-06-16 11:46:59 +02:00
renovate[bot]
6e3ec6a077 chore(deps): update all non-major dependencies (v3) (#4349)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-16 11:24:09 +02:00
Hugo Richard
59c26ec123 feat(CommandPalette): handle children in items (#4226)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-13 14:49:43 +02:00
Julien Augugliaro
67ef866a40 docs(input): fix typo in mask example (#4334) 2025-06-12 23:48:01 +02:00
J-Michalek
5170cfd7eb feat(Timeline): add reverse prop (#4316)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-12 17:06:51 +02:00
Benjamin Canac
9bcf1ad92f docs(input-tags): add illustration 2025-06-12 16:40:08 +02:00
Benjamin Canac
7a2bd4e617 feat(Select/SelectMenu/Tabs): expose trigger refs
Resolves #4292
2025-06-12 15:38:43 +02:00
Benjamin Canac
8781a07909 fix(InputTags): extend emits interface 2025-06-12 15:35:20 +02:00
Benjamin Canac
2492526d7c docs(showcase): improve file parse 2025-06-12 12:40:57 +02:00
zhong666
54bb2282c5 feat(InputTags): new component (#4261)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-12 12:10:48 +02:00
renovate[bot]
2a2495a652 chore(deps): update tailwindcss to ^4.1.10 (v3) (#4332)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 10:53:49 +02:00
renovate[bot]
f17b15ed1e chore(deps): update tailwindcss to ^4.1.9 (v3) (#4326)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-11 17:19:05 +02:00
Eugen Istoc
66355ba301 fix(useOverlay): set props to original props when defaultOpen is set (#4308)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-11 17:05:55 +02:00
Benjamin Canac
4873b3a043 chore(deps): update @nuxt/ui-pro 2025-06-11 17:02:44 +02:00
Benjamin Canac
0d4baf7851 docs(app): improve header dropdown items 2025-06-11 16:55:25 +02:00
syvixor
04333cd8cb docs(app): update v2 versions in header (#4325)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-11 15:27:19 +02:00
renovate[bot]
cb3522ed18 chore(deps): update dependency colortranslator to v5 (v3) (#4314)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-11 12:56:00 +02:00
Benjamin Canac
1a4de49c16 feat(Select/SelectMenu): handle dynamic autofocus
Resolves #4324
2025-06-11 12:53:57 +02:00
Benjamin Canac
3eb7812f2d chore(github): update stale workflow 2025-06-11 12:17:19 +02:00
Benjamin Canac
080aed7225 chore(github): handle workflow_dispatch 2025-06-11 12:11:55 +02:00
Benjamin Canac
d77fd6102a chore(github): update stale workflow 2025-06-11 12:04:30 +02:00
Benjamin Canac
0f558fc0d0 feat(extendLocale): new composable
Resolves #3729
2025-06-11 10:58:20 +02:00
J-Michalek
1841e13b32 docs(timeline): fix duplicate separator field on item.ui (#4313)
Co-authored-by: Jakub <jakub.michalek@freelo.io>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-10 18:21:14 +02:00
Hugo Richard
4e7c1c9c30 fix(defineShortcuts): allow meta_- shortcut (#4321) 2025-06-10 17:54:15 +02:00
renovate[bot]
4b3dd48778 chore(deps): update nuxt-hub/action action to v2 (v3) (#4315)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-10 17:44:59 +02:00
renovate[bot]
a9e8ea9231 chore(deps): update all non-major dependencies (v3) (#4277)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 17:17:33 +02:00
Benjamin Canac
4dd9344ff9 chore(deps): use workspace:* syntax 2025-06-10 16:53:07 +02:00
renovate[bot]
180c150e0f chore(deps): update dependency reka-ui to v2.3.1 (v3) (#4310)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-10 16:16:01 +02:00
Estéban
145cae798c docs(installation): add tip to improve types in vue (#4318)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-10 15:58:09 +02:00
Benjamin Canac
9aea54267a chore(deps): add @internationalized/date in playground 2025-06-10 15:49:17 +02:00
Benjamin Canac
9400552491 chore(github): improve sha retrieval 2025-06-10 14:52:35 +02:00
Benjamin Canac
89753fc337 chore(github): update workflows permissions 2025-06-10 13:02:32 +02:00
Benjamin Canac
f8a6bd3bf6 chore(github): add stale workflow 2025-06-06 12:29:23 +02:00
Benjamin Canac
228d4c9835 docs(input): add mask example 2025-06-06 11:37:26 +02:00
Benjamin Canac
150b334b1d fix(Modal/Slideover): don't emit close:prevent on closeAutoFocus 2025-06-05 17:22:42 +02:00
Eugen Istoc
bf56e15a2e fix(useOverlay): use original props when not provided to open (#4269) 2025-06-05 15:48:47 +02:00
Benjamin Canac
09151df170 chore(renovate): add vaul-vue to group 2025-06-05 12:47:08 +02:00
Benjamin Canac
22b917a0f7 chore(deps): pin reka-ui & vaul-vue dependencies
Related to https://github.com/nuxt/ui/issues/4257
2025-06-05 12:47:08 +02:00
adjabaev
43cbb94ee2 feat(locale): add Luxembourgish language (#4264) 2025-06-05 12:34:38 +02:00
Benjamin Canac
3bf5acb683 fix(Toast): calc height on next tick
Resolves #4265
2025-06-05 12:13:35 +02:00
Eugen Istoc
d37315cc83 docs(use-overlay): add caveats section regarding provide/inject limit (#4287)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-04 16:01:02 +02:00
renovate[bot]
326bb9a31e chore(deps): update nuxt framework to ^3.17.5 (v3) (#4284)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 10:34:41 +02:00
Benjamin Canac
4157260a02 docs(timeline): improve responsive 2025-06-03 18:09:36 +02:00
Benjamin Canac
03b20fdb26 chore: prefer nuxt over nuxi 2025-06-02 12:51:40 +02:00
renovate[bot]
004c93bfa2 chore(deps): lock file maintenance (v3) (#4278)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 12:46:59 +02:00
renovate[bot]
18eb5e6b97 chore(deps): update tailwindcss to ^4.1.8 (v3) (#4275)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 10:55:39 +02:00
renovate[bot]
42f7f94521 chore(deps): update all non-major dependencies (v3) (#4273)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 10:22:38 +02:00
dan hale
ea0c459306 feat(Form): expose loading state to default slot (#4247)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-06-01 16:48:16 +02:00
Eugen Istoc
546df572fc fix(useOverlay)!: correct spelling of unmount function (#4051)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-30 17:27:22 +02:00
Tankosin
37abcc6a5b fix(Form): conditionally type form data via transform prop (#4188)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-30 15:29:01 +02:00
Rajeev R Sharma
accf69046c docs(input): update button group example (#4252) 2025-05-30 15:27:28 +02:00
J-Michalek
80177679f2 feat(Timeline): new component (#4215)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
Co-authored-by: Jakub <jakub.michalek@freelo.io>
2025-05-30 15:27:11 +02:00
Benjamin Canac
536b7afcc1 chore(github): add CODEOWNERS file 2025-05-30 10:58:05 +02:00
Benjamin Canac
483e473e3f fix(Select/SelectMenu): prevent empty string display when multiple
Regression of 7df7ee336a
2025-05-28 17:33:59 +02:00
Joseph Anson
5835eb5f0f feat(Modal/Slideover): add close method in slots (#4219)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-28 15:57:12 +02:00
renovate[bot]
ca507c6a0d chore(deps): update dependency @octokit/rest to v22 (v3) (#4222)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-28 12:47:16 +02:00
Benjamin Canac
03ac395164 feat(Avatar): add chip prop (#4224) 2025-05-28 12:46:30 +02:00
renovate[bot]
f761369888 chore(deps): update dependency reka-ui to ^2.3.0 (v3) (#4234)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-28 11:55:12 +02:00
Benjamin Canac
7df7ee336a fix(Select/SelectMenu): display falsy values 2025-05-27 13:00:30 +02:00
J-Michalek
2ee1c5ac2e feat(Carousel): allow customization of active dot color (#4229) 2025-05-26 17:48:30 +02:00
Benjamin Canac
62bc7b25a2 fix(NavigationMenu): set content max-height in horizontal orientation
Resolves #4208
2025-05-26 17:46:46 +02:00
renovate[bot]
66f6c7743c chore(deps): update dependency vue to ^3.5.15 (v3) (#4227)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 16:09:06 +02:00
Benjamin Canac
dec2b9fd6a chore(deps): update @nuxt/ui-pro 2025-05-26 15:55:06 +02:00
Benjamin Canac
4604da0f16 docs(content): update badges 2025-05-26 15:02:39 +02:00
Benjamin Canac
a9d693095b docs(navigation-menu): update type field 2025-05-26 15:02:30 +02:00
Benjamin Canac
cddcb95ed4 chore(release): v3.1.3 2025-05-26 14:49:46 +02:00
renovate[bot]
967968e02e chore(deps): lock file maintenance (v3) (#4225)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 12:43:35 +02:00
renovate[bot]
f8e560525f chore(deps): update all non-major dependencies (v3) (#4184)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-26 12:08:50 +02:00
Benjamin Canac
8216b59d4f playground: add default-value for combobox components 2025-05-26 11:15:09 +02:00
Byambajav
44ea02c0d6 feat(locale): add Mongolian language (#4214)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-26 10:26:35 +02:00
Benjamin Canac
f95abf8d1d fix(InputMenu/Select/SelectMenu): manual viewport to display scrollbars
Resolves #4069
2025-05-23 17:41:30 +02:00
Benjamin Canac
dcf34a7ac2 fix(ContextMenu/DropdownMenu): wrap groups in a viewport
Resolves #3315
2025-05-23 17:39:17 +02:00
Benjamin Canac
2ba94db09e fix(CommandPalette): add presentation role to viewport 2025-05-23 17:32:18 +02:00
Eugen Istoc
d9e9fea35e feat(Modal/Slideover): add after:enter event (#4187) 2025-05-23 12:39:53 +02:00
Hugo Richard
dae9f0b863 fix(theme): define old-neutral color as static (#4193) 2025-05-23 12:38:33 +02:00
Benjamin Canac
0a72024361 docs(drawer): add interactive background example
Resolves #4199
2025-05-23 12:24:03 +02:00
Benjamin Canac
41087d4c95 fix(Drawer): improve title & description accessibility
Related to #4199

Follow-up e419dcbe61
2025-05-23 11:46:56 +02:00
Scott Carlton
6aab62ec30 fix(Textarea): missing imports (#4207)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-22 21:52:37 +02:00
renovate[bot]
742a37201e chore(deps): update dependency @iconify/vue to v5 (v3) (#4068)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-22 17:55:00 +02:00
J-Michalek
473513c246 feat(Popover): add anchor slot (#4119)
Co-authored-by: Jakub <jakub.michalek@freelo.io>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-22 17:04:17 +02:00
Alec Armbruster
fe4e1f859d fix(icons): update loading icon (#4163)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-22 16:51:46 +02:00
Hugo Richard
3243fb88f7 fix(Input/Textarea): define model modifiers types (#4195)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-22 14:51:24 +02:00
Alireza Alibeiki
43d281f6d1 fix(CheckboxGroup/RadioGroup): variant table borders in RTL mode (#4192) 2025-05-22 14:36:44 +02:00
aydin
405304775e feat(locale): add Kyrgyz language (#4189) 2025-05-22 14:35:30 +02:00
renovate[bot]
0559beb365 chore(deps): lock file maintenance (v3) (#4200)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 14:34:46 +02:00
renovate[bot]
56fc757244 chore(deps): update nuxt framework to ^3.17.4 (v3) (#4205)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 13:00:32 +02:00
Benjamin Canac
9cf9f25f44 feat(NavigationMenu): add trigger type in items 2025-05-22 12:51:44 +02:00
Benjamin Canac
02363994d6 fix(NavigationMenu): remove font-medium in popover children 2025-05-22 11:56:49 +02:00
Benjamin Canac
f2682fd2ae feat(NavigationMenu): add tooltip and popover props
Resolves #4186
2025-05-21 18:39:02 +02:00
Benjamin Canac
0634a756a4 fix(Tooltip): increase padding for consistency 2025-05-21 15:24:20 +02:00
Benjamin Canac
44f536fd00 fix(NavigationMenu): only display tooltip when collapsed 2025-05-20 17:06:20 +02:00
Benjamin Canac
d0be59946b fix(NavigationMenu): incorrect hover when disabled and active 2025-05-20 17:06:20 +02:00
Benjamin Canac
1e2a10b4bd feat(NavigationMenu): handle vertical orientation with Accordion instead of Collapsible
Resolves #4072, resolves #3911
2025-05-20 17:06:20 +02:00
Benjamin Canac
3c78e2fd98 fix(NavigationMenu)!: revert new collapsible field
Reverts 2be60cddfe
2025-05-20 14:36:57 +02:00
Benjamin Canac
6887e33aae chore(deps): update @nuxt/ui-pro 2025-05-20 14:22:31 +02:00
renovate[bot]
28e869e8aa chore(deps): update all non-major dependencies (v3) (#4178)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 11:05:40 +02:00
zikju
d86956e1d5 feat(locale): add Lithuanian language (#4171)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-19 10:53:02 +02:00
renovate[bot]
23e4f0ec4d chore(deps): update tailwindcss to ^4.1.7 (v3) (#4179)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 10:52:00 +02:00
Muhammad Syahmi Mohd Ikram
c00f6e8cdf feat(locale): add Malay language (#4160) 2025-05-16 12:14:21 +02:00
Benjamin Canac
d29e1481f2 chore(deps): update @nuxt/ui-pro 2025-05-15 15:57:54 +02:00
Benjamin Canac
79aa161c6d docs(showcase): remove submit button 2025-05-15 15:42:25 +02:00
Benjamin Canac
94ea75f441 docs(content): update badges 2025-05-15 15:30:02 +02:00
Benjamin Canac
0c368c8ab8 chore(release): v3.1.2 2025-05-15 15:26:25 +02:00
renovate[bot]
c5796c4f82 chore(deps): update all non-major dependencies (v3) (#4129)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-15 15:10:05 +02:00
Benjamin Canac
204953b780 fix(ButtonGroup): add z-index on focused element 2025-05-15 14:30:56 +02:00
Benjamin Canac
2e4c3082a1 fix(InputNumber): handle inside button group
Resolves #4155
2025-05-15 14:26:32 +02:00
Benjamin Canac
f2fd778c0a fix(Checkbox/RadioGroup): render correct element without variant
Resolves #3998
2025-05-15 11:32:15 +02:00
Romain Hamel
d79da9d7b6 fix(FormField): block form field injection after use (#4150) 2025-05-14 19:24:47 +02:00
Benjamin Canac
a4429eee09 docs(app): add theme query in examples page 2025-05-14 19:05:06 +02:00
Benjamin Canac
0905b2b3d5 chore(components): move back item.class on link
Partial revert of #4060
2025-05-14 18:18:21 +02:00
Hugo Richard
c7fba2e0eb feat(InputNumber): add increment-disabled / decrement-disabled props (#4141) 2025-05-14 17:41:34 +02:00
Maxime Pauvert
4167f04205 docs(theme): add note about color definition (#3976)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-14 14:32:19 +02:00
Benjamin Canac
276268d311 fix(module): configure @nuxt/fonts with default weights 2025-05-14 13:18:09 +02:00
Benjamin Canac
717e35f098 docs(app): improve slug page metas 2025-05-14 12:55:58 +02:00
Benjamin Canac
459a0410ab fix(FormField): use div for error and help slots 2025-05-14 12:55:58 +02:00
J-Michalek
b9adc83e78 feat(components): add ui field in items (#4060)
Co-authored-by: Jakub <jakub.michalek@freelo.io>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-13 17:40:29 +02:00
Benjamin Canac
d7a4d029b7 fix(Slider): handle generic types 2025-05-13 17:21:42 +02:00
Benjamin Canac
3c8d6cd01d fix(Input/Textarea): handle generic types
Resolves nuxt/ui-pro#887
2025-05-13 17:18:06 +02:00
Benjamin Canac
67da90a2f6 fix(Link): consistent behavior between nuxt, vue and inertia (#4134) 2025-05-13 14:45:18 +02:00
Daniele Nicosia
894e8a61b6 feat(Badge): add square prop (#4008)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-13 14:44:23 +02:00
TribeWeb
1b6ab271ea feat(CheckboxGroup): add table variant (#3997)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-13 14:28:15 +02:00
Vachmara
0dc4678c68 fix(NavigationMenu): arrow position conflict (#4137)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-13 14:02:02 +02:00
kacijan
e86dc79e51 feat(locale): add Slovenian language (#4140)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-13 12:45:52 +02:00
renovate[bot]
35997377a6 chore(deps): update nuxt framework to ^3.17.3 (v3) (#4133)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 17:17:58 +02:00
Benjamin Canac
12303a87be fix(inertia): make useAppConfig reactive
Follow-up 869c0708bd
2025-05-12 17:11:19 +02:00
renovate[bot]
f84ccddcd6 chore(deps): lock file maintenance (v3) (#4081)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: HugoRCD <hugo.richard@epitech.eu>
2025-05-12 16:42:17 +02:00
Benjamin Canac
869c0708bd fix(vue): make useAppConfig reactive
Resolves #3952

Co-Authored-By: Hugo Richard <hugo.richard@epitech.eu>
2025-05-12 15:05:25 +02:00
Benjamin Canac
c63d2f380a fix(Toaster): allow base slot override 2025-05-12 14:53:09 +02:00
Hugo Richard
92632e969e feat(Toast): add progress prop to hide progress bar (#4125)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-12 14:47:02 +02:00
renovate[bot]
f6d7994a55 chore(deps): update all non-major dependencies (v3) (#4127)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 11:56:05 +02:00
Benjamin Canac
f738f68f76 docs(navigation-menu): improve 2025-05-12 11:31:23 +02:00
Benjamin Canac
17d6803329 docs(ComponentProps): improve schema collapsible display 2025-05-12 11:31:22 +02:00
Benjamin Canac
732a67aa88 docs(app): remove banner 2025-05-12 11:31:22 +02:00
renovate[bot]
bdf129fc38 chore(deps): update tailwindcss to ^4.1.6 (v3) (#4128)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-12 11:18:16 +02:00
Benjamin Canac
d140acc608 feat(Slider): handle tooltip around thumbs
Resolves #1469
2025-05-10 21:53:12 +02:00
Mateusz Kalinowski
cc20a26f07 fix(ColorPicker): make thumb touch draggable (#4101)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-10 20:03:56 +02:00
Hugo Richard
983c6382d1 docs(llms): handle prose props in llms-full.txt (#4111) 2025-05-10 19:52:01 +02:00
Benjamin Canac
37eabc89bd docs(tabs): improve active item example
Resolves #4092
2025-05-10 18:11:33 +02:00
Benjamin Canac
a57844e416 fix(Stepper): use div tag for title & description
Resolves #4096
2025-05-10 17:59:27 +02:00
Benjamin Canac
2be60cddfe feat(NavigationMenu): add collapsible field in items
Resolves #3353, resolves #3911

Reverts 07e1b4f1f4
2025-05-10 17:51:49 +02:00
Norbiros
09b4699aea fix(Select): support more primitive types in value field (#4105) 2025-05-10 15:06:20 +02:00
Benjamin Canac
46c2987ebf feat(NavigationMenu): handle tooltip in items
Resolves #4050
2025-05-10 13:09:21 +02:00
Malik
f244d15b96 fix(Badge/Button): handle zero value in label correctly (#4108) 2025-05-09 19:27:00 +02:00
Benjamin Canac
aaa60c0798 chore(github): update reproduire workflow 2025-05-09 15:08:21 +02:00
Hugo Richard
5467d71cc2 docs(llms): some ::component-code not parsed in llms-full.txt (#4099)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-09 13:49:06 +02:00
renovate[bot]
941a54e5e3 chore(deps): update all non-major dependencies (v3) (#4078)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-09 10:40:46 +02:00
Benjamin Canac
655f98ffed docs(Header): update raycast extension link 2025-05-08 18:46:09 +02:00
Benjamin Canac
999a0f8467 fix(Tabs): set focus:outline-none with link variant 2025-05-07 21:20:36 +02:00
Benjamin Canac
2739939c46 chore(deps): update @nuxt/ui-pro 2025-05-07 19:37:21 +02:00
Benjamin Canac
2a241c87c3 chore(github): update reproduire workflow 2025-05-07 17:29:40 +02:00
Benjamin Canac
e6e510b848 fix(components): class should have priority over ui prop 2025-05-07 17:23:27 +02:00
Benjamin Canac
a655da1394 chore(github): add reproduire workflow 2025-05-07 15:58:36 +02:00
Benjamin Canac
3a71256d59 docs(contributions): update content url 2025-05-07 15:58:36 +02:00
Benjamin Canac
404359a6ca chore(github): improve v3 issue templates 2025-05-07 15:58:36 +02:00
Igor G
1e4e9c4708 docs(table): add grouped rows example (#4074)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-07 15:25:59 +02:00
Benjamin Canac
6f07f6bd6e docs(examples): remove key from useFetch with params watch 2025-05-07 10:52:06 +02:00
Benjamin Canac
4c1093bde4 docs(examples): add missing @vueuse/core imports 2025-05-07 10:51:46 +02:00
Benjamin Canac
7d51a9e479 fix(Calendar): wrong color for today date with neutral color
Resolves #4084

Possible regression of #3629
2025-05-06 17:36:46 +02:00
Benjamin Canac
04bdbcfc6e chore(module): remove processCSSVariables option
Not needed since https://github.com/nuxt/fonts/releases/tag/v0.11.0
2025-05-06 17:02:12 +02:00
Benjamin Canac
58aa296425 playground(vue): missing fonts 2025-05-06 16:49:36 +02:00
Benjamin Canac
d3df3bb929 fix(templates): dont write unused variants in theme files 2025-05-06 16:03:28 +02:00
Benjamin Canac
4863775e17 docs(app): fix tabs trigger width
Regression of 06e5689da8
2025-05-06 15:22:52 +02:00
Benjamin Canac
7551a85ad2 fix(CheckboxGroup): relative UCheckbox import
Resolves #4090
2025-05-06 12:15:54 +02:00
Benjamin Canac
c2bcb8e264 docs(kbd): update title to fix llms-full.txt 2025-05-06 10:45:31 +02:00
renovate[bot]
88124b85c5 chore(deps): update dependency reka-ui to ^2.2.1 (v3) (#4082)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-05-05 18:46:26 +02:00
Benjamin Canac
9f539c9545 chore(renovate): remove vue-tsc ignore 2025-05-05 18:25:34 +02:00
Benjamin Canac
41d4ffe5b5 chore(renovate): add group for reka-ui 2025-05-05 18:20:11 +02:00
renovate[bot]
d8a0bbe710 chore(deps): update nuxt framework to ^3.17.2 (v3) (#4079)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 18:09:35 +02:00
Benjamin Canac
06e5689da8 fix(Tabs): prevent trigger truncate without parent width
Resolves #4056
2025-05-05 15:47:27 +02:00
Benjamin Canac
67d19f582a docs(team): center cards 2025-05-05 15:01:24 +02:00
Benjamin Canac
650bc40253 docs(index): update contributors count 2025-05-05 15:01:24 +02:00
renovate[bot]
2f0f317a12 chore(deps): update devdependency vite to ^6.3.5 (v3) (#4071)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 14:55:16 +02:00
renovate[bot]
d2a26939ad chore(deps): update all non-major dependencies (v3) (#4066)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 10:14:30 +02:00
renovate[bot]
b7a8146898 chore(deps): update tailwindcss to ^4.1.5 (v3) (#4067)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-05 10:14:12 +02:00
Victor Bianchi
e81464a43e fix(inertia): link always render as anchor tag (#3989)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
Co-authored-by: Eugen Istoc <eugenistoc@gmail.com>
Co-authored-by: Romain Hamel <rom.hml@gmail.com>
2025-05-04 17:36:45 +02:00
Benjamin Canac
4b3d2a7b00 chore(deps): update @nuxt/ui-pro 2025-05-02 19:20:03 +02:00
Benjamin Canac
6f6fa6ae4a chore(release): v3.1.1 2025-05-02 18:28:20 +02:00
Jez McKean
c7bb6d4c4b docs(toast): fix toaster example links (#4044) 2025-05-02 18:20:10 +02:00
Daniel Jimenez Gutierrez
c23f85fe33 docs(use-overlay): typo on unMount method (#4047) 2025-05-02 18:18:47 +02:00
Benjamin Canac
591d59fe89 fix(theme): improve app config types for ui object
Resolves #3579
2025-05-02 17:06:20 +02:00
Benjamin Canac
caa3bf9c7e docs(carousel): improve thumbnails example
Resolves #4032
2025-05-02 11:58:55 +02:00
Benjamin Canac
2731011bb7 docs(nuxt.config): put back local module import 2025-05-02 11:52:43 +02:00
Benjamin Canac
aebf0b3dca fix(NavigationMenu): remove sm:w-auto from content slot
Resolves #3987

Reverts abe0859691
2025-05-02 11:48:34 +02:00
renovate[bot]
6651987dc6 chore(deps): update nuxt framework to ^3.17.1 (v3) (#4003)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 10:21:32 +02:00
Eugen Istoc
61aabd72e4 chore(deps): add missing vue-component-type-helpers dependency (#4043) 2025-05-01 22:57:50 +02:00
Vitor Camarotto
8dfdd63ce3 fix(Calendar): add place-items-center to grid row (#4034) 2025-05-01 19:02:06 +02:00
renovate[bot]
e6369a6746 chore(deps): update devdependency vite to v6.3.4 [security] (v3) (#4037)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-01 18:49:10 +02:00
Eugen Istoc
a4f3f6d531 feat(useOverlay): add isOpen method to check overlay state (#4041) 2025-05-01 18:48:41 +02:00
Sandro Circi
c5bdec0f64 fix(templates): put back args to watch in dev (#4033) 2025-05-01 18:47:03 +02:00
renovate[bot]
87a7828931 chore(deps): update dependency motion-v to v1 (v3) (#4004)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 15:48:32 +02:00
Hugo Richard
501468960b docs(templates): add portfolio template (#4031) 2025-04-30 15:33:06 +02:00
Benjamin Canac
13cd6be679 docs(command-palette): wrong reka-ui link 2025-04-29 22:46:59 +02:00
Benjamin Canac
e421ea57ec docs(pin-input): missing reka-ui link 2025-04-29 22:46:59 +02:00
Malik
799d7ae422 docs(input-number): broken reka-ui link (#4028)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-29 22:44:53 +02:00
Benjamin Canac
be9b1f659a docs(team): update grid 2025-04-29 18:16:59 +02:00
Eugen Istoc
39e29fccf1 fix(useOverlay): improve types and docs (#4012)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-29 18:09:39 +02:00
reslear
195773ec7d fix(RadioGroup): improve items value field type (#3995) 2025-04-29 18:02:38 +02:00
Benjamin Canac
d7710795df chore(github): add playground job in module workflow (#4021) 2025-04-29 17:48:09 +02:00
Benjamin Canac
53f8b34bef chore: use module workspace 2025-04-29 17:21:43 +02:00
Benjamin Canac
df83ab355e chore(deps): update vue-tsc (#4023) 2025-04-29 17:07:24 +02:00
Hugo Richard
e5df026993 fix(theme): add missing ring-offset-* utilities (#3992)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-29 16:10:53 +02:00
Benjamin Canac
6131871a0d fix(theme): use @theme inline to properly reference css variables
Resolves #4018

https://tailwindcss.com/docs/theme#referencing-other-variables
2025-04-29 14:39:08 +02:00
Alain Limoges
9543bce787 docs(form-field/switch): fix typo (#4015) 2025-04-29 14:36:40 +02:00
renovate[bot]
5e345a8a73 chore(deps): update all non-major dependencies (v3) (#4002)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 14:36:40 +02:00
Benjamin Canac
8acf3c51db fix(theme): define default shades for named tailwindcss colors
Resolves #3977
2025-04-29 14:36:31 +02:00
Benjamin Canac
f3b8b17dc5 fix(defineShortcuts): bring back meta to ctrl convert on non macos platforms
Resolves #3869, resolves #3318

Co-Authored-By: Sylvain Marroufin <marroufin.sylvain@gmail.com>
2025-04-29 14:36:31 +02:00
Daniel Roe
bc0a296f9d fix(module): support nuxt-nightly (#3996) 2025-04-29 14:36:31 +02:00
Eugen Istoc
ac4c1946ec feat(useOverlay): add closeAll method (#3984) 2025-04-29 14:36:31 +02:00
Benjamin Canac
82b5f322eb fix(theme): add missing border-bg / divide-bg utilities 2025-04-29 14:36:19 +02:00
Benjamin Canac
fb6cf708a6 chore(deps): update @nuxt/content 2025-04-24 21:35:59 +02:00
Benjamin Canac
8ab1f75e47 chore(github): revert docs trigger 2025-04-24 17:44:30 +02:00
Benjamin Canac
e9b19349ba chore(deps): update @nuxt/ui-pro 2025-04-24 16:16:57 +02:00
Benjamin Canac
b2b206e3f4 docs: update badges 2025-04-24 16:16:29 +02:00
Benjamin Canac
b779064129 docs(radio-group): add missing types on variant 2025-04-24 16:16:29 +02:00
Benjamin Canac
94155258e2 chore(github): prevent docs workflow to run on tags 2025-04-24 16:16:29 +02:00
Maxime Pauvert
c63a6dd133 chore(readme): add pro link (#3970) 2025-04-24 15:43:12 +02:00
Benjamin Canac
79833035de chore(release): v3.1.0 2025-04-24 14:29:07 +02:00
Benjamin Canac
79e7c7b729 chore(deps): update @nuxt/ui-pro 2025-04-24 13:00:11 +02:00
Benjamin Canac
bc06185282 fix(CheckboxGroup): proxy slots & ui prop 2025-04-24 12:38:44 +02:00
Guillaume REMBERT
6e27304d8c fix(Table): improve data reactivity (#3967)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-24 12:10:37 +02:00
Benjamin Canac
b4f8ac7ff7 chore(deps): update nuxt-component-meta 2025-04-24 12:10:29 +02:00
renovate[bot]
a2fa1accaa chore(deps): update all non-major dependencies (v3) (#3946)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-24 12:03:00 +02:00
kyyy
f486423381 feat(Modal/Popover/Slideover): add close:prevent event (#3958)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-23 17:38:44 +02:00
Romain Hamel
975331a7b1 docs(installation): update instructions for inertia (#3964)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-23 17:36:06 +02:00
Benjamin Canac
75e4792f7f fix(Accordion): use div instead of h3 for header tag
Resolves #3963
2025-04-23 16:12:13 +02:00
Benjamin Canac
4a969a8b9e chore(github): add release workflow on v3* tags 2025-04-23 15:31:30 +02:00
Benjamin Canac
664a8c7524 chore(deps): missing caret on motion-v 2025-04-23 13:08:23 +02:00
Benjamin Canac
fbcc3139a3 chore(Skeleton): remove aria-busy:cursor-progress class 2025-04-23 11:25:43 +02:00
Guillaume Chau
1a46394668 feat(components): add new content-top and content-bottom slots (#3886)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-23 11:02:50 +02:00
Benjamin Canac
9ca213bd33 fix(InputMenu/SelectMenu): remove valueKey string case
Resolves #3949

Regression of #3331
2025-04-23 10:22:28 +02:00
kyyy
3484832822 fix(Skeleton): improve accessibility (#3613)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 22:06:05 +02:00
andr35
80dfa88ea4 feat(Table): conditionally apply classes to tr and td (#3866)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 21:14:57 +02:00
Benjamin Canac
d710141a1b chore(deps): update nuxt-component-meta 2025-04-22 18:50:45 +02:00
Hugo Richard
d3e2a3f33a docs(checkbox-group): add og images (#3957) 2025-04-22 18:47:55 +02:00
TribeWeb
9c3d53a02d feat(CheckboxGroup): new component (#3862)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
Co-authored-by: Romain Hamel <rom.hml@gmail.com>
2025-04-22 18:03:27 +02:00
Polly
22edfd708a feat(Carousel): add select event (#3678)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 16:44:47 +02:00
Kheuval
e25aa78050 docs(table): add infinite scroll example (#3656)
Co-authored-by: Hadrien Hartstein <hadrien@emagma.fr>
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 16:14:59 +02:00
Igor G
122e8ac8f4 fix(Table): pass header colspan to th (#3926) 2025-04-22 16:07:23 +02:00
Hung Chang
5fc6312ab1 docs(carousel): add thumbnails example (#3740)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 15:44:40 +02:00
Stijn Slats
83f0a24704 docs(table): add drag and drop example (#3700)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 15:31:57 +02:00
Evan Schleret
13c299533f docs(calendar): add external controls example (#3793)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-22 15:17:17 +02:00
Nathanaël Louison
db11db6ff1 fix(usePortal): adjust portal target resolution logic (#3954) 2025-04-22 12:05:14 +02:00
Benjamin Canac
50863635d6 fix(Alert/Toast): display actions when using slots
Fixes #3950
2025-04-21 18:25:52 +02:00
Nathanaël Louison
29fa46276d feat(App): add global portal prop (#3688)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-21 17:42:55 +02:00
Benjamin Canac
7a35baebc7 chore(templates): wrong theme keys for fill and stroke 2025-04-21 16:52:57 +02:00
Benjamin Canac
b6f6cee1a9 chore(deps): update @nuxt/ui-pro 2025-04-21 16:27:51 +02:00
Benjamin Canac
d49e0dadee feat(module): define neutral utilities (#3629)
Co-authored-by: Sébastien Chopin <atinux@gmail.com>
2025-04-21 15:20:53 +02:00
renovate[bot]
2b315fd855 chore(deps): lock file maintenance (v3) (#3941)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 11:48:01 +02:00
Romain Hamel
f42949820b fix(Form): input and output type inference (#3938)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-21 11:04:23 +02:00
renovate[bot]
d2ba99797c chore(deps): update pnpm to v10.9.0 (v3) (#3944)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 11:02:27 +02:00
renovate[bot]
fd23038b1a chore(deps): update devdependency release-it to v19 (v3) (#3931)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 11:01:51 +02:00
renovate[bot]
fe3ec0c183 chore(deps): update all non-major dependencies (v3) (#3888)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-21 10:42:50 +02:00
Romain Hamel
1a0d7a3103 feat(Form): add attach prop to opt-out of nested form attachement (#3939) 2025-04-20 17:29:36 +02:00
Federico Mameli
c31bffad1b fix(vite): vitest skipping nuxt imports transformations (#3925) 2025-04-18 10:34:21 +02:00
Sébastien Chopin
dd8f7a77a5 docs: don't import color mode from vueuse (#3929) 2025-04-18 09:04:26 +02:00
ExXTreMe315
eb46e31ffb docs(modal): typo in programmatic emit (#3918)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-17 17:49:04 +02:00
Lo
8ea99f0c4f docs(color-mode): fix computed setter logic in ColorModeButton.vue example (#3903) 2025-04-17 17:18:26 +02:00
Hannes Küttner
f6b376110c fix(InputMenu/Select/SelectMenu): add min-w-fit to content slot (#3922) 2025-04-17 14:13:55 +02:00
Hannes Küttner
01d8dc72ad fix(components): respect transform-origin in popper content (#3919)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-17 12:05:04 +02:00
Benjamin Canac
445aac2d57 docs(templates): add chat template 2025-04-16 18:08:11 +02:00
Hugo Richard
391828a2c2 docs(llms): improve llms-full.txt content (#3848)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-16 16:55:42 +02:00
Soryn
02b6b38a56 docs: change favicon color on theme color change (#3917) 2025-04-16 16:50:23 +02:00
Danila Poyarkov
47cdc2e1d8 fix(Link): proxy download property (#3879) 2025-04-16 16:15:13 +02:00
Benjamin Canac
a7d3097f8d chore(locale): order exports 2025-04-16 16:12:44 +02:00
Benjamin Canac
7ac7aa9ba7 feat(module): define default color shades (#3916) 2025-04-16 16:10:54 +02:00
Benjamin Canac
f9737c8f40 feat(module): dynamic rounded-* utilities (#3906) 2025-04-16 15:57:32 +02:00
Benjamin Canac
4e39cc59f8 chore(deps): update @nuxt/ui-pro 2025-04-16 15:47:36 +02:00
renovate[bot]
28accc4aa0 chore(deps): lock file maintenance (v3) (#3812)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-16 10:31:03 +02:00
Sandro Circi
5d10f242bd chore(github): separate builds (#3885) 2025-04-16 10:26:10 +02:00
ElshadBeg
2d5c881639 chore(locale): rename Uyghur language code (#3908) 2025-04-16 10:25:44 +02:00
Selemon Brahanu
ad63753b5e docs(installation): improve .vscode/settings.json json (#3881)
Co-authored-by: Benjamin Canac <canacb1@gmail.com>
2025-04-15 17:53:20 +02:00
Neil Richter
e5a1e26f9d fix(types): allow color identifiers with dashes (#3896) 2025-04-15 10:58:14 +02:00
Maxime Pauvert
113e2e7166 docs(form): fix typo in expose section (#3895) 2025-04-15 10:28:57 +02:00
renovate[bot]
9d4880be35 chore(deps): update tailwindcss to ^4.1.4 (v3) (#3899)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-15 10:22:42 +02:00
Sandro Circi
8dd9d08209 fix(types): improve dynamic slots (#3857) 2025-04-14 16:09:20 +02:00
Benjamin Canac
f309a46b8d chore(deps): update @nuxt/ui-pro 2025-04-14 14:13:21 +02:00
527 changed files with 36412 additions and 24450 deletions

1
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1 @@
* @benjamincanac

View File

@@ -5,12 +5,12 @@ body:
- type: markdown
attributes:
value: |
Before reporting a bug, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before reporting a bug, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: env
attributes:
label: Environment
description: You can use `npx nuxi info` to fill this section
description: You can use `npx nuxt info` to fill this section
placeholder: |
- Operating System: `Darwin`
- Node Version: `v18.16.0`
@@ -44,7 +44,7 @@ body:
id: reproduction
attributes:
label: Reproduction
description: Please provide a reproduction link using the Nuxt template https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks or the Vue template https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn. A minimal [reproduction is required](https://antfu.me/posts/why-reproductions-are-required) unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided we might close it.
description: Please provide a reproduction link using the Nuxt template https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks or the Vue template https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn. A minimal [reproduction is required](https://antfu.me/posts/why-reproductions-are-required) unless you are absolutely sure that the issue is obvious and the provided information is enough to understand the problem. If a report is vague (e.g. just a generic error message) and has no reproduction, it will receive a "needs reproduction" label. If no reproduction is provided, it will be closed automatically after a while.
placeholder: https://github.com/my/reproduction
validations:
required: true

View File

@@ -10,7 +10,7 @@ body:
id: env
attributes:
label: Environment
description: You can use `npx nuxi info` to fill this section
description: You can use `npx nuxt info` to fill this section
placeholder: |
- Operating System: `Darwin`
- Node Version: `v18.16.0`

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Before requesting a feature, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before requesting a feature, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: description
attributes:

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Before asking a question, please make sure that you have read through our [v3 documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
Before asking a question, please make sure that you have read through our [documentation](https://ui.nuxt.com/) and existing [issues](https://github.com/nuxt/ui/issues?q=is%3Aissue%20is%3Aopen%20sort%3Aupdated-desc%20label%3Av3).
- type: textarea
id: description
attributes:

View File

@@ -0,0 +1,30 @@
Would you be able to provide a [reproduction](https://nuxt.com/docs/community/reporting-bugs/#create-a-minimal-reproduction)? 🙏
<details>
<summary>More info</summary>
### Why do I need to provide a reproduction?
Reproductions make it possible for us to triage and fix issues quickly with a relatively small team. It helps us discover the source of the problem, and also can reveal assumptions you or we might be making.
### What will happen?
If you've provided a reproduction, we'll remove the label and try to reproduce the issue. If we can, we'll mark it as a bug and prioritise it based on its severity and how many people we think it might affect.
If `needs reproduction` labeled issues don't receive any substantial activity (e.g., new comments featuring a reproduction link), they will be closed automatically after a while. That's not because we don't care! At any point, feel free to comment with a reproduction and we'll reopen it.
### How can I create a reproduction?
We have templates to create a minimal reproduction:
* **Nuxt**: https://codesandbox.io/p/devbox/nuxt-ui3-n3sxks
* **Vue**: https://codesandbox.io/p/devbox/nuxt-ui3-vue-4h5gqn
Please ensure that the reproduction is as **minimal** as possible. See more details [in our guide](https://nuxt.com/docs/community/reporting-bugs/#create-a-minimal-reproduction).
You might also find these other articles interesting and/or helpful:
- [The Importance of Reproductions](https://antfu.me/posts/why-reproductions-are-required)
- [How to Generate a Minimal, Complete, and Verifiable Example](https://stackoverflow.com/help/mcve)
</details>

View File

@@ -6,10 +6,6 @@ jobs:
deploy:
runs-on: ${{ matrix.os }}
environment:
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
url: ${{ steps.deploy.outputs.deployment-url }}
permissions:
contents: read
id-token: write
@@ -40,14 +36,10 @@ jobs:
- name: Prepare build
run: pnpm run dev:prepare
- name: Build application
run: pnpm run docs:build
- name: Deploy to NuxtHub
uses: nuxt-hub/action@v2
env:
NODE_OPTIONS: '--max-old-space-size=8192'
- name: Deploy to NuxtHub
uses: nuxt-hub/action@v1
id: deploy
with:
project-key: ui-7eg3
directory: docs/dist
directory: docs

View File

@@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest] # macos-latest
os: ${{ github.event_name == 'pull_request' && fromJSON('["ubuntu-latest"]') || fromJSON('["ubuntu-latest", "windows-latest"]') }} # macos-latest
node: [22]
env:
@@ -65,9 +65,57 @@ jobs:
run: pnpm run dev:vue:build
- name: Publish
if: matrix.os != 'windows-latest'
# Only publish preview package on ubuntu during PRs
if: matrix.os == 'ubuntu-latest'
run: pnpx pkg-pr-new publish --compact --no-template --pnpm
playground:
needs: build
runs-on: ${{ matrix.os }}
defaults:
run:
working-directory: ./playground
permissions:
contents: read
pull-requests: read
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install node
uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- name: Install latest nuxt/ui
run: pnpm install https://pkg.pr.new/@nuxt/ui@${{ env.COMMIT_SHA }} --lockfile-only
- name: Install dependencies
run: pnpm install --ignore-workspace
- name: Prepare
run: pnpm nuxt prepare
- name: Typecheck
run: pnpm run typecheck
starter-nuxt:
needs: build
@@ -90,7 +138,7 @@ jobs:
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm
uses: pnpm/action-setup@v4
@@ -135,7 +183,7 @@ jobs:
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm
uses: pnpm/action-setup@v4
@@ -187,7 +235,7 @@ jobs:
- name: Store commit SHA
run: |
echo "COMMIT_SHA=$(echo ${{ github.workflow_sha }} | cut -c1-7)" >> $GITHUB_ENV
echo "COMMIT_SHA=$(echo ${{ github.event.pull_request.head.sha || github.sha }} | cut -c1-7)" >> $GITHUB_ENV
- name: Install pnpm
uses: pnpm/action-setup@v4

View File

@@ -9,10 +9,6 @@ jobs:
deploy:
runs-on: ${{ matrix.os }}
environment:
name: ${{ github.ref == 'refs/heads/v3' && 'production' || 'preview' }}
url: ${{ steps.deploy.outputs.deployment-url }}
permissions:
contents: read
id-token: write
@@ -40,14 +36,10 @@ jobs:
- name: Prepare build
run: pnpm run dev:prepare
- name: Build application
run: pnpm run dev:build
env:
NITRO_PRESET: cloudflare-pages
- name: Deploy to NuxtHub
uses: nuxt-hub/action@v1
id: deploy
uses: nuxt-hub/action@v2
env:
NODE_OPTIONS: '--max-old-space-size=8192'
with:
project-key: ui3-playground-pb9b
directory: playground/dist
directory: playground

54
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,54 @@
name: release
on:
push:
tags:
- 'v3*'
jobs:
publish:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest] # macos-latest, windows-latest
node: [22]
env:
NUXT_GITHUB_TOKEN: ${{ secrets.NUXT_GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install node
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node }}
cache: pnpm
- name: Install dependencies
run: pnpm install
- name: Prepare
run: pnpm run dev:prepare
- name: Lint
run: pnpm run lint
- name: Typecheck
run: pnpm run typecheck
- name: Test
run: pnpm run test run
- name: Test (vue)
run: pnpm run test:vue run
- name: Publish
run: ./scripts/release.sh
env:
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}

27
.github/workflows/reproduction.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
name: reproduction
on:
workflow_dispatch:
schedule:
- cron: '30 1 * * *'
jobs:
reproduction:
runs-on: ubuntu-latest
permissions:
actions: write
issues: write
steps:
- uses: actions/stale@v9
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: 'needs reproduction' # Label that flags an issue as stale.
only-labels: 'needs reproduction' # Only process these issues
days-before-issue-close: 7
ignore-updates: true
remove-stale-when-updated: false
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
close-issue-label: closed-by-bot
operations-per-run: 300 #default 30

17
.github/workflows/reproduire.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: reproduire
on:
issues:
types: [labeled]
permissions:
issues: write
jobs:
reproduire:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: Hebilicious/reproduire@4b686ae9cbb72dad60f001d278b6e3b2ce40a9ac # v0.0.9-mp
with:
label: needs reproduction

View File

@@ -1,6 +1,7 @@
name: stale
on:
workflow_dispatch:
schedule:
- cron: '30 1 * * *'
@@ -9,17 +10,28 @@ jobs:
runs-on: ubuntu-latest
permissions:
actions: write
issues: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@4c023f01d613e60293d8004f251a18bfb9bbd71d
with:
days-before-stale: -1 # Issues and PR will never be flagged stale automatically.
stale-issue-label: 'needs reproduction' # Label that flags an issue as stale.
only-labels: 'needs reproduction' # Only process these issues
days-before-issue-close: 7
ignore-updates: true
remove-stale-when-updated: false
close-issue-message: This issue was closed because it was open for 7 days without a reproduction.
close-issue-label: closed-by-bot
operations-per-run: 300 #default 30
days-before-pr-stale: -1
days-before-stale: 60
days-before-close: 7
stale-issue-label: 'stale'
close-issue-label: 'closed-by-bot'
close-issue-message: |
Hi! 👋
This issue has been automatically **closed** due to prolonged inactivity.
We're a small team and can't address every report, but we appreciate your feedback and contributions.
If this issue is still relevant with the latest version of Nuxt UI, please feel free to reopen or create a new issue with updated details.
Thank you for your understanding and support!
— Nuxt UI Team
exempt-issue-labels: 'feature,announcement'
operations-per-run: 300

View File

@@ -3,6 +3,9 @@
"commitMessage": "chore(release): v${version}",
"tagName": "v${version}"
},
"npm": {
"publish": false
},
"github": {
"release": true,
"releaseName": "v${version}",

View File

@@ -1,5 +1,218 @@
# Changelog
## [3.2.0](https://github.com/nuxt/ui/compare/v3.1.3...v3.2.0) (2025-06-25)
### ⚠ BREAKING CHANGES
* **useOverlay:** correct spelling of `unmount` function (#4051)
### Features
* **Avatar:** add `chip` prop ([#4224](https://github.com/nuxt/ui/issues/4224)) ([03ac395](https://github.com/nuxt/ui/commit/03ac395164c02c964361c68743268b1bc90aae59))
* **Carousel:** allow customization of active dot color ([#4229](https://github.com/nuxt/ui/issues/4229)) ([2ee1c5a](https://github.com/nuxt/ui/commit/2ee1c5ac2e20ab9ce2f4037a8e8c64e561b0428b))
* **CommandPalette:** handle `children` in items ([#4226](https://github.com/nuxt/ui/issues/4226)) ([59c26ec](https://github.com/nuxt/ui/commit/59c26ec1230375a24fbaf8a630a696ae854700c7))
* **extendLocale:** new composable ([0f558fc](https://github.com/nuxt/ui/commit/0f558fc0d014d51549222accfc50286d1770d1aa)), closes [#3729](https://github.com/nuxt/ui/issues/3729)
* **Form:** expose loading state to default slot ([#4247](https://github.com/nuxt/ui/issues/4247)) ([ea0c459](https://github.com/nuxt/ui/commit/ea0c459306be585bacaaf5b433114d072550c824))
* **InputTags:** new component ([#4261](https://github.com/nuxt/ui/issues/4261)) ([54bb228](https://github.com/nuxt/ui/commit/54bb2282c58d3bf5a7dde4cdee687c68efd934a0))
* **locale:** add Luxembourgish language ([#4264](https://github.com/nuxt/ui/issues/4264)) ([43cbb94](https://github.com/nuxt/ui/commit/43cbb94ee25106b414fc8fe979fa65ebaa9ccc76))
* **Modal/Slideover:** add `actions` slot ([#4358](https://github.com/nuxt/ui/issues/4358)) ([8156971](https://github.com/nuxt/ui/commit/81569713e9da9d5531ecdf4614660b84c686fa81))
* **Modal/Slideover:** add `close` method in slots ([#4219](https://github.com/nuxt/ui/issues/4219)) ([5835eb5](https://github.com/nuxt/ui/commit/5835eb5f0f835b5f03646dec78f85b2f556a109b))
* **Select/SelectMenu/Tabs:** expose trigger refs ([7a2bd4e](https://github.com/nuxt/ui/commit/7a2bd4e6179373902ba6f285903ea896fd1d378f)), closes [#4292](https://github.com/nuxt/ui/issues/4292)
* **Select/SelectMenu:** handle dynamic `autofocus` ([1a4de49](https://github.com/nuxt/ui/commit/1a4de49c1665c9ef65279315be0393d6272447b9)), closes [#4324](https://github.com/nuxt/ui/issues/4324)
* **Table:** add `body-top` / `body-bottom` slots ([#4354](https://github.com/nuxt/ui/issues/4354)) ([595fc64](https://github.com/nuxt/ui/commit/595fc64515613fe82c3a56fc5518f2e3fcce6e19))
* **Timeline:** add `reverse` prop ([#4316](https://github.com/nuxt/ui/issues/4316)) ([5170cfd](https://github.com/nuxt/ui/commit/5170cfd7eb44a25c64673cf12979f9ca1049695f))
* **Timeline:** new component ([#4215](https://github.com/nuxt/ui/issues/4215)) ([8017767](https://github.com/nuxt/ui/commit/80177679f2aa0d7f0e39e639a02d527a06e6172c))
### Bug Fixes
* **Card/Drawer/Modal:** prevent scrollbars overflow ([#4368](https://github.com/nuxt/ui/issues/4368)) ([c3adc38](https://github.com/nuxt/ui/commit/c3adc381c90dad7152e27fc303ee678efc7c4c94))
* **components:** remove default `md` size on buttons ([#4357](https://github.com/nuxt/ui/issues/4357)) ([be41aed](https://github.com/nuxt/ui/commit/be41aed1f3d3476801e1840dbb8766926bc93c05))
* **defineShortcuts:** allow `meta_-` shortcut ([#4321](https://github.com/nuxt/ui/issues/4321)) ([4e7c1c9](https://github.com/nuxt/ui/commit/4e7c1c9c305b45dd76d4c238e70a6aeedae78c8b))
* **Form:** conditionally type form data via `transform` prop ([#4188](https://github.com/nuxt/ui/issues/4188)) ([37abcc6](https://github.com/nuxt/ui/commit/37abcc6a5b0a678be626673af5067956657a50d6))
* **Form:** expose reactive fields ([#4386](https://github.com/nuxt/ui/issues/4386)) ([1a8feb7](https://github.com/nuxt/ui/commit/1a8feb751e6827c414ef82fe9fb259ba7dcc7e08))
* **InputMenu/SelectMenu:** dynamic `empty` size ([ba3c6e8](https://github.com/nuxt/ui/commit/ba3c6e8788ed75d86d4406749797da52d7816b84)), closes [#4377](https://github.com/nuxt/ui/issues/4377)
* **InputTags:** extend emits interface ([8781a07](https://github.com/nuxt/ui/commit/8781a079096def0d3bae5b8d896db0df6ce37e23))
* **Modal/Slideover:** don't emit `close:prevent` on `closeAutoFocus` ([150b334](https://github.com/nuxt/ui/commit/150b334b1d242c6dc132193e23359c03e6f35666))
* **NavigationMenu:** nested accordion context at every level ([#4363](https://github.com/nuxt/ui/issues/4363)) ([2fa8db6](https://github.com/nuxt/ui/commit/2fa8db64ddf4c92a19e73774143518d87d001b72))
* **NavigationMenu:** set content `max-height` in `horizontal` orientation ([62bc7b2](https://github.com/nuxt/ui/commit/62bc7b25a2d205d8dffb47a109196f91ff3e823a)), closes [#4208](https://github.com/nuxt/ui/issues/4208)
* **Pagination:** match default button `size` ([#4350](https://github.com/nuxt/ui/issues/4350)) ([4dd56c8](https://github.com/nuxt/ui/commit/4dd56c8111e5a224105b82d541b7742b46abb34a))
* **Select/SelectMenu:** display falsy values ([7df7ee3](https://github.com/nuxt/ui/commit/7df7ee336a925d7ee07f866551dad9350785c9fc))
* **Select/SelectMenu:** prevent empty string display when multiple ([483e473](https://github.com/nuxt/ui/commit/483e473e3f5681cc97c3766ea47283dc95f76345))
* **SelectMenu:** dynamic input size ([b0364b9](https://github.com/nuxt/ui/commit/b0364b96b73b9e543781a35962c03b5a983352c4))
* **Table:** use `tr` as separator ([#4083](https://github.com/nuxt/ui/issues/4083)) ([edca3bc](https://github.com/nuxt/ui/commit/edca3bcb743c7eb63e6abbaa801d3858342a8777))
* **Toast:** calc height on next tick ([3bf5acb](https://github.com/nuxt/ui/commit/3bf5acb683f0ad09735b2417d265d6fcfd901b11)), closes [#4265](https://github.com/nuxt/ui/issues/4265)
* **Toaster:** smoother visibility transition for stacked toasts ([#4367](https://github.com/nuxt/ui/issues/4367)) ([abfd0ed](https://github.com/nuxt/ui/commit/abfd0ede036fa2953f9abc841d77ac71bbd3bba9))
* **useOverlay:** correct spelling of `unmount` function ([#4051](https://github.com/nuxt/ui/issues/4051)) ([546df57](https://github.com/nuxt/ui/commit/546df572fca60325315bed17c9be3367052fb7a9))
* **useOverlay:** set props to original props when `defaultOpen` is set ([#4308](https://github.com/nuxt/ui/issues/4308)) ([66355ba](https://github.com/nuxt/ui/commit/66355ba301d569b9f44527bafc5f8f09bcda63c0))
* **useOverlay:** use original props when not provided to `open` ([#4269](https://github.com/nuxt/ui/issues/4269)) ([bf56e15](https://github.com/nuxt/ui/commit/bf56e15a2eed7d51199d5641649a822e91ca41ba))
## [3.1.3](https://github.com/nuxt/ui/compare/v3.1.2...v3.1.3) (2025-05-26)
### ⚠ BREAKING CHANGES
* **NavigationMenu:** revert new `collapsible` field
### Features
* **locale:** add Kyrgyz language ([#4189](https://github.com/nuxt/ui/issues/4189)) ([4053047](https://github.com/nuxt/ui/commit/405304775e4b2b4e8b37a2364f3e5ee34b46036e))
* **locale:** add Lithuanian language ([#4171](https://github.com/nuxt/ui/issues/4171)) ([d86956e](https://github.com/nuxt/ui/commit/d86956e1d57482b3e98eef2d34bff13544284b0b))
* **locale:** add Malay language ([#4160](https://github.com/nuxt/ui/issues/4160)) ([c00f6e8](https://github.com/nuxt/ui/commit/c00f6e8cdfd88eeba58812b78d94a2326c13f164))
* **locale:** add Mongolian language ([#4214](https://github.com/nuxt/ui/issues/4214)) ([44ea02c](https://github.com/nuxt/ui/commit/44ea02c0d64322ef0cfda63b234369c00d3d0180))
* **Modal/Slideover:** add `after:enter` event ([#4187](https://github.com/nuxt/ui/issues/4187)) ([d9e9fea](https://github.com/nuxt/ui/commit/d9e9fea35e4b22d68324c9e85b3aa221a7987d0f))
* **NavigationMenu:** add `tooltip` and `popover` props ([f2682fd](https://github.com/nuxt/ui/commit/f2682fd2ae8abb7807977727fc22ef34cb5752e5)), closes [#4186](https://github.com/nuxt/ui/issues/4186)
* **NavigationMenu:** add `trigger` type in items ([9cf9f25](https://github.com/nuxt/ui/commit/9cf9f25f4424447691e03e9034155d1541badd43))
* **NavigationMenu:** handle `vertical` orientation with Accordion instead of Collapsible ([1e2a10b](https://github.com/nuxt/ui/commit/1e2a10b4bdebaef12316ac60f98a956dad21c1ec)), closes [#4072](https://github.com/nuxt/ui/issues/4072) [#3911](https://github.com/nuxt/ui/issues/3911)
* **Popover:** add `anchor` slot ([#4119](https://github.com/nuxt/ui/issues/4119)) ([473513c](https://github.com/nuxt/ui/commit/473513c2460d4329d7d2e0a0ea69bf1310a072d1))
### Bug Fixes
* **CheckboxGroup/RadioGroup:** variant `table` borders in RTL mode ([#4192](https://github.com/nuxt/ui/issues/4192)) ([43d281f](https://github.com/nuxt/ui/commit/43d281f6d1d8b0017ed61d929c5e311fb5b03447))
* **CommandPalette:** add `presentation` role to viewport ([2ba94db](https://github.com/nuxt/ui/commit/2ba94db09e1ba86020d5d289f1ca1e24ef706299))
* **ContextMenu/DropdownMenu:** wrap groups in a viewport ([dcf34a7](https://github.com/nuxt/ui/commit/dcf34a7ac236b96b1302ec2eae155b8f2d3784ef)), closes [#3315](https://github.com/nuxt/ui/issues/3315)
* **Drawer:** improve title & description accessibility ([41087d4](https://github.com/nuxt/ui/commit/41087d4c9569eb00c04bd748e055cd151c2f762c)), closes [#4199](https://github.com/nuxt/ui/issues/4199)
* **icons:** update `loading` icon ([#4163](https://github.com/nuxt/ui/issues/4163)) ([fe4e1f8](https://github.com/nuxt/ui/commit/fe4e1f859d42aa3c32bb7b75302e84a280abe525))
* **Input/Textarea:** define model modifiers types ([#4195](https://github.com/nuxt/ui/issues/4195)) ([3243fb8](https://github.com/nuxt/ui/commit/3243fb88f71c5475824bfdc4d7c4f303b2d6790b))
* **InputMenu/Select/SelectMenu:** manual viewport to display scrollbars ([f95abf8](https://github.com/nuxt/ui/commit/f95abf8d1d7b9149e400d7dc6f96f93f5154da7a)), closes [#4069](https://github.com/nuxt/ui/issues/4069)
* **NavigationMenu:** incorrect hover when disabled and active ([d0be599](https://github.com/nuxt/ui/commit/d0be59946bfe30c79a6f75476385ab8538aa51b8))
* **NavigationMenu:** only display `tooltip` when collapsed ([44f536f](https://github.com/nuxt/ui/commit/44f536fd0034facb3550d910fae71d4f9442ed19))
* **NavigationMenu:** remove `font-medium` in popover children ([0236399](https://github.com/nuxt/ui/commit/02363994d66d3c2d11b9913f31167fa25f5c5de2))
* **NavigationMenu:** revert new `collapsible` field ([3c78e2f](https://github.com/nuxt/ui/commit/3c78e2fd983f19b5cec65b4a94a8a8b14e548e5e))
* **Textarea:** missing imports ([#4207](https://github.com/nuxt/ui/issues/4207)) ([6aab62e](https://github.com/nuxt/ui/commit/6aab62ec30e266c5f0da0cd24aefbb7c53f447ac))
* **theme:** define `old-neutral` color as static ([#4193](https://github.com/nuxt/ui/issues/4193)) ([dae9f0b](https://github.com/nuxt/ui/commit/dae9f0b8631b3b9fb60ef47753f7aded0c36c4a2))
* **Tooltip:** increase padding for consistency ([0634a75](https://github.com/nuxt/ui/commit/0634a756a496f5131841abafd218ae7e4aaa61e5))
## [3.1.2](https://github.com/nuxt/ui/compare/v3.1.1...v3.1.2) (2025-05-15)
### Features
* **Badge:** add `square` prop ([#4008](https://github.com/nuxt/ui/issues/4008)) ([894e8a6](https://github.com/nuxt/ui/commit/894e8a61b6fea3618fc863bd77678385e9d021c2))
* **CheckboxGroup:** add `table` variant ([#3997](https://github.com/nuxt/ui/issues/3997)) ([1b6ab27](https://github.com/nuxt/ui/commit/1b6ab271ea3875a7c77ffe9367c7c341083dd53c))
* **components:** add `ui` field in items ([#4060](https://github.com/nuxt/ui/issues/4060)) ([b9adc83](https://github.com/nuxt/ui/commit/b9adc83e787db02507e6e7bb1aabc684eccc197b))
* **InputNumber:** add `increment-disabled` / `decrement-disabled` props ([#4141](https://github.com/nuxt/ui/issues/4141)) ([c7fba2e](https://github.com/nuxt/ui/commit/c7fba2e0ebfb7153f3bfb727165d653bbd3dbe54))
* **locale:** add Slovenian language ([#4140](https://github.com/nuxt/ui/issues/4140)) ([e86dc79](https://github.com/nuxt/ui/commit/e86dc79e51b2773a77ada5f12d4f0964fbc83354))
* **NavigationMenu:** add `collapsible` field in items ([2be60cd](https://github.com/nuxt/ui/commit/2be60cddfe10fd1e2466900fd53e21ee0c877227)), closes [#3353](https://github.com/nuxt/ui/issues/3353) [#3911](https://github.com/nuxt/ui/issues/3911)
* **NavigationMenu:** handle `tooltip` in items ([46c2987](https://github.com/nuxt/ui/commit/46c2987ebfd30b2b071a96a745b7270e852e96de)), closes [#4050](https://github.com/nuxt/ui/issues/4050)
* **Slider:** handle `tooltip` around thumbs ([d140acc](https://github.com/nuxt/ui/commit/d140acc608c6ae11c0a0531fe443588776ea7807)), closes [#1469](https://github.com/nuxt/ui/issues/1469)
* **Toast:** add `progress` prop to hide progress bar ([#4125](https://github.com/nuxt/ui/issues/4125)) ([92632e9](https://github.com/nuxt/ui/commit/92632e969eaa11521a166e50e346753929b7f523))
### Bug Fixes
* **Badge/Button:** handle zero value in label correctly ([#4108](https://github.com/nuxt/ui/issues/4108)) ([f244d15](https://github.com/nuxt/ui/commit/f244d15b96d97cd8ba34ba9c18f23965e17e3cef))
* **ButtonGroup:** add `z-index` on focused element ([204953b](https://github.com/nuxt/ui/commit/204953b780bde08dbfde230fc8887674449227b7))
* **Calendar:** wrong color for today date with `neutral` color ([7d51a9e](https://github.com/nuxt/ui/commit/7d51a9e479cb6105ea37759c5cd67ff9f7702c49)), closes [#4084](https://github.com/nuxt/ui/issues/4084) [#3629](https://github.com/nuxt/ui/issues/3629)
* **Checkbox/RadioGroup:** render correct element without `variant` ([f2fd778](https://github.com/nuxt/ui/commit/f2fd778c0a604f2d65aec9f3fe2d54b6d4e8c3a2)), closes [#3998](https://github.com/nuxt/ui/issues/3998)
* **CheckboxGroup:** relative `UCheckbox` import ([7551a85](https://github.com/nuxt/ui/commit/7551a85ad2d92b59e2909396affb862403d5b27a)), closes [#4090](https://github.com/nuxt/ui/issues/4090)
* **ColorPicker:** make thumb touch draggable ([#4101](https://github.com/nuxt/ui/issues/4101)) ([cc20a26](https://github.com/nuxt/ui/commit/cc20a26f07268d19119ab4c7c254033143bb63f4))
* **components:** `class` should have priority over `ui` prop ([e6e510b](https://github.com/nuxt/ui/commit/e6e510b848d995a286a51d50a120d67483e11232))
* **FormField:** block form field injection after use ([#4150](https://github.com/nuxt/ui/issues/4150)) ([d79da9d](https://github.com/nuxt/ui/commit/d79da9d7b60c9972af64acd8e6eef4ae7d6bc3eb))
* **FormField:** use `div` for `error` and `help` slots ([459a041](https://github.com/nuxt/ui/commit/459a0410ab729fde60865e84632b36903465f57e))
* **inertia:** link always render as anchor tag ([#3989](https://github.com/nuxt/ui/issues/3989)) ([e81464a](https://github.com/nuxt/ui/commit/e81464a43ede4e63ce3dc92429bbfef48614f731))
* **inertia:** make `useAppConfig` reactive ([12303a8](https://github.com/nuxt/ui/commit/12303a87be62dae84ef774e3a9795deb0ac90cc7))
* **Input/Textarea:** handle generic types ([3c8d6cd](https://github.com/nuxt/ui/commit/3c8d6cd01dfafed5844c376f52adbdda0c814420)), closes [nuxt/ui-pro#887](https://github.com/nuxt/ui-pro/issues/887)
* **InputNumber:** handle inside button group ([2e4c308](https://github.com/nuxt/ui/commit/2e4c3082a1e66fa597086dc3431fec37fa29ef62)), closes [#4155](https://github.com/nuxt/ui/issues/4155)
* **Link:** consistent behavior between nuxt, vue and inertia ([#4134](https://github.com/nuxt/ui/issues/4134)) ([67da90a](https://github.com/nuxt/ui/commit/67da90a2f638124f640c4271d3376c5ff3fab6a1))
* **module:** configure `@nuxt/fonts` with default weights ([276268d](https://github.com/nuxt/ui/commit/276268d311f57715cec47bc600a0ccc3d3885682))
* **NavigationMenu:** arrow position conflict ([#4137](https://github.com/nuxt/ui/issues/4137)) ([0dc4678](https://github.com/nuxt/ui/commit/0dc4678c68e4b500be49c38336dc75b73843e38d))
* **Select:** support more primitive types in `value` field ([#4105](https://github.com/nuxt/ui/issues/4105)) ([09b4699](https://github.com/nuxt/ui/commit/09b4699aeadaa195ea081509f8e237bb2c346238))
* **Slider:** handle generic types ([d7a4d02](https://github.com/nuxt/ui/commit/d7a4d029b77d2dfa0b8efcd2755d482fa5e31fd3))
* **Stepper:** use `div` tag for `title` & `description` ([a57844e](https://github.com/nuxt/ui/commit/a57844e41676c13ed1af861424961b88cee7b4da)), closes [#4096](https://github.com/nuxt/ui/issues/4096)
* **Tabs:** prevent trigger truncate without parent width ([06e5689](https://github.com/nuxt/ui/commit/06e5689da80b36205d0548d5d6b58510938e4a6e)), closes [#4056](https://github.com/nuxt/ui/issues/4056)
* **Tabs:** set `focus:outline-none` with `link` variant ([999a0f8](https://github.com/nuxt/ui/commit/999a0f84671fad20fa3dc50c6774af2e0200b32e))
* **templates:** dont write unused variants in theme files ([d3df3bb](https://github.com/nuxt/ui/commit/d3df3bb929fe6732f27b182d1664213884a662ec))
* **Toaster:** allow `base` slot override ([c63d2f3](https://github.com/nuxt/ui/commit/c63d2f380aac16f1d1e812516df3dca7fa7c8034))
* **vue:** make `useAppConfig` reactive ([869c070](https://github.com/nuxt/ui/commit/869c0708bd351c7be44e5e430c348b19dd316db9)), closes [#3952](https://github.com/nuxt/ui/issues/3952)
## [3.1.1](https://github.com/nuxt/ui/compare/v3.1.0...v3.1.1) (2025-05-02)
### Features
* **useOverlay:** add `closeAll` method ([#3984](https://github.com/nuxt/ui/issues/3984)) ([ac4c194](https://github.com/nuxt/ui/commit/ac4c1946ec399aec59b4bce9d538e3ff67868abf))
* **useOverlay:** add `isOpen` method to check overlay state ([#4041](https://github.com/nuxt/ui/issues/4041)) ([a4f3f6d](https://github.com/nuxt/ui/commit/a4f3f6d531f9c0281f99085a6688d296f8f13f2f))
### Bug Fixes
* **Calendar:** add `place-items-center` to grid row ([#4034](https://github.com/nuxt/ui/issues/4034)) ([8dfdd63](https://github.com/nuxt/ui/commit/8dfdd63ce3b3a0e904f7c013c774cf9aaf46b240))
* **defineShortcuts:** bring back `meta` to `ctrl` convert on non macos platforms ([f3b8b17](https://github.com/nuxt/ui/commit/f3b8b17dc5f43936ef7ffb11c1ed7f9a5f94d0bb)), closes [#3869](https://github.com/nuxt/ui/issues/3869) [#3318](https://github.com/nuxt/ui/issues/3318)
* **module:** support `nuxt-nightly` ([#3996](https://github.com/nuxt/ui/issues/3996)) ([bc0a296](https://github.com/nuxt/ui/commit/bc0a296f9d68ca72cd991b11cd3489b63c7b13db))
* **NavigationMenu:** remove `sm:w-auto` from content slot ([aebf0b3](https://github.com/nuxt/ui/commit/aebf0b3dca50c51c093cb6abf16c4fd995fc1b39)), closes [#3987](https://github.com/nuxt/ui/issues/3987)
* **RadioGroup:** improve items `value` field type ([#3995](https://github.com/nuxt/ui/issues/3995)) ([195773e](https://github.com/nuxt/ui/commit/195773ec7dac12ccc3a0a67867751e8ca634cc04))
* **templates:** put back args to watch in dev ([#4033](https://github.com/nuxt/ui/issues/4033)) ([c5bdec0](https://github.com/nuxt/ui/commit/c5bdec0f64963ef602975270a09a1ee795cdacf9))
* **theme:** add missing `border-bg` / `divide-bg` utilities ([82b5f32](https://github.com/nuxt/ui/commit/82b5f322ebd8a08e63588122bd4ef567dcb8ba8c))
* **theme:** add missing `ring-offset-*` utilities ([#3992](https://github.com/nuxt/ui/issues/3992)) ([e5df026](https://github.com/nuxt/ui/commit/e5df0269935be59df759fe0e1378acb2b0d9014a))
* **theme:** define default shades for named tailwindcss colors ([8acf3c5](https://github.com/nuxt/ui/commit/8acf3c51db6c2f9443d04be6ba7d9f062c5cf8ab)), closes [#3977](https://github.com/nuxt/ui/issues/3977)
* **theme:** improve app config types for `ui` object ([591d59f](https://github.com/nuxt/ui/commit/591d59fe89f1d9bf016c121bf9160f73fe0a290d)), closes [#3579](https://github.com/nuxt/ui/issues/3579)
* **theme:** use `[@theme](https://github.com/theme) inline` to properly reference css variables ([6131871](https://github.com/nuxt/ui/commit/6131871a0d124c5942d60dc5dff20981e8542e51)), closes [#4018](https://github.com/nuxt/ui/issues/4018)
* **useOverlay:** improve types and docs ([#4012](https://github.com/nuxt/ui/issues/4012)) ([39e29fc](https://github.com/nuxt/ui/commit/39e29fccf1840c723a13237d65002501b2829b70))
## [3.1.0](https://github.com/nuxt/ui/compare/v3.0.2...v3.1.0) (2025-04-24)
### ⚠ BREAKING CHANGES
* **OverlayProvider:** return an overlay instance from `.open()` (#3829)
### Features
* **App:** add global `portal` prop ([#3688](https://github.com/nuxt/ui/issues/3688)) ([29fa462](https://github.com/nuxt/ui/commit/29fa46276d6bf69b5b87880c476c6f778c2820bf))
* **Carousel:** add `select` event ([#3678](https://github.com/nuxt/ui/issues/3678)) ([22edfd7](https://github.com/nuxt/ui/commit/22edfd708ae3eeadbd4ff6c830cdfd5632948286))
* **CheckboxGroup:** new component ([#3862](https://github.com/nuxt/ui/issues/3862)) ([9c3d53a](https://github.com/nuxt/ui/commit/9c3d53a02d6254f6b5c90e5fed826b8aefcdb042))
* **components:** add new `content-top` and `content-bottom` slots ([#3886](https://github.com/nuxt/ui/issues/3886)) ([1a46394](https://github.com/nuxt/ui/commit/1a463946681e152aa18372118d0fef4a7d8055a5))
* **Form:** add `attach` prop to opt-out of nested form attachement ([#3939](https://github.com/nuxt/ui/issues/3939)) ([1a0d7a3](https://github.com/nuxt/ui/commit/1a0d7a3103cf7591b019ef3ad685e2f3786ef6f2))
* **Form:** export loading state ([#3861](https://github.com/nuxt/ui/issues/3861)) ([fdee252](https://github.com/nuxt/ui/commit/fdee2522bb9d8361ff3e9fdd4aa2350be8e49b05))
* **InputMenu/SelectMenu:** handle `resetSearchTermOnSelect` ([cea881a](https://github.com/nuxt/ui/commit/cea881abdc139b39df89b503cf2ab872f4246c8f)), closes [#3782](https://github.com/nuxt/ui/issues/3782)
* **InputNumber:** add support for `stepSnapping` & `disableWheelChange` props ([#3731](https://github.com/nuxt/ui/issues/3731)) ([f5e6284](https://github.com/nuxt/ui/commit/f5e62849c9313063396ab0e3a9b7d22d98ef69bc))
* **locale:** add Bulgarian language ([#3783](https://github.com/nuxt/ui/issues/3783)) ([a0c9731](https://github.com/nuxt/ui/commit/a0c9731f634020e76aa98a9a68d673591d35e8c9))
* **locale:** add Kazakh language ([#3875](https://github.com/nuxt/ui/issues/3875)) ([43153c4](https://github.com/nuxt/ui/commit/43153c4e91034b728059e7a9bed05888e48f8890))
* **locale:** add Tajik language ([#3850](https://github.com/nuxt/ui/issues/3850)) ([f42a79b](https://github.com/nuxt/ui/commit/f42a79b5efe8dc65430a83799ebb0ee737773820))
* **locale:** add Uyghur language ([#3878](https://github.com/nuxt/ui/issues/3878)) ([b7fc69b](https://github.com/nuxt/ui/commit/b7fc69baa718ff65b3988d0fa9f143306fa8fac4))
* **Modal/Popover/Slideover:** add `close:prevent` event ([#3958](https://github.com/nuxt/ui/issues/3958)) ([f486423](https://github.com/nuxt/ui/commit/f4864233812eac0ed37e0a2d076a95c285a22c01))
* **module:** define default color shades ([#3916](https://github.com/nuxt/ui/issues/3916)) ([7ac7aa9](https://github.com/nuxt/ui/commit/7ac7aa9ba73b6aca1bc29b0de2e95c60b2700135))
* **module:** define neutral utilities ([#3629](https://github.com/nuxt/ui/issues/3629)) ([d49e0da](https://github.com/nuxt/ui/commit/d49e0dadeea2a58e05e60b2c461b29ce1d334d2b))
* **module:** dynamic `rounded-*` utilities ([#3906](https://github.com/nuxt/ui/issues/3906)) ([f9737c8](https://github.com/nuxt/ui/commit/f9737c8f401bf8bc5307674fad6defe2aeeeb907))
* **OverlayProvider:** return an overlay instance from `.open()` ([#3829](https://github.com/nuxt/ui/issues/3829)) ([f3098df](https://github.com/nuxt/ui/commit/f3098df84a3b7f58f7ccc1233bc8b45eab99ee10))
* **PinInput:** add `autofocus` / `autofocus-delay` props ([0456670](https://github.com/nuxt/ui/commit/0456670dac1153340220603c8c116e3b71f72ae7)), closes [#3717](https://github.com/nuxt/ui/issues/3717)
* **RadioGroup:** add `card` and `table` variants ([#3178](https://github.com/nuxt/ui/issues/3178)) ([4d138ad](https://github.com/nuxt/ui/commit/4d138ad6719a074f5f994006d12745ca05bec9c4))
* **Select:** handle `onSelect` field in items ([8640831](https://github.com/nuxt/ui/commit/864083156a79dfb5d0be868658b7f9fc77570178))
* **Table:** conditionally apply classes to `tr` and `td` ([#3866](https://github.com/nuxt/ui/issues/3866)) ([80dfa88](https://github.com/nuxt/ui/commit/80dfa88ea442571ee1dc673317cc7baa8cacd8a3))
* **Tabs:** add `list-leading` and `list-trailing` slots ([#3837](https://github.com/nuxt/ui/issues/3837)) ([3447a06](https://github.com/nuxt/ui/commit/3447a062b636a469089d6e9bdcfcb3dce9063ee5))
* **Textarea:** add `autoresize-delay` prop ([06414d3](https://github.com/nuxt/ui/commit/06414d344b151ad6e1a3225a9f5f1f76d58d319c)), closes [#3730](https://github.com/nuxt/ui/issues/3730)
* **Textarea:** add `icon`, `loading`, etc. props to match Input ([cb193f1](https://github.com/nuxt/ui/commit/cb193f1d25b5c73ca03dcf10864800350dd1c290))
* **Textarea:** add `resize-none` class with `autoresize` prop ([ffafd81](https://github.com/nuxt/ui/commit/ffafd81e1ed25074430668c792e5e1c6afc22bd0))
* **unplugin:** routing support for inertia ([#3845](https://github.com/nuxt/ui/issues/3845)) ([d059efc](https://github.com/nuxt/ui/commit/d059efca258da7ae5116e829189a492824ac1d87))
### Bug Fixes
* **Accordion:** use `div` instead of `h3` for header tag ([75e4792](https://github.com/nuxt/ui/commit/75e4792f7f00c55229253289c4f806f2b6fc9854)), closes [#3963](https://github.com/nuxt/ui/issues/3963)
* **Alert/Toast:** display actions when using slots ([5086363](https://github.com/nuxt/ui/commit/50863635d653c8083772046ddc5b828fba7047d0)), closes [#3950](https://github.com/nuxt/ui/issues/3950)
* **Carousel:** move arrows inside container on mobile ([d339dcb](https://github.com/nuxt/ui/commit/d339dcbfb8fe244bd198d247d8448e3ef856dfef)), closes [#3813](https://github.com/nuxt/ui/issues/3813)
* **CheckboxGroup:** proxy slots & `ui` prop ([bc06185](https://github.com/nuxt/ui/commit/bc061852822edd2dfb832a46dd6388123ec5771e))
* **CommandPalette:** consistent alignement with other components ([d25265c](https://github.com/nuxt/ui/commit/d25265c8b7d34e01af8827d9af5eccb98bf30e9e))
* **CommandPalette:** increase input font size to avoid zoom ([d227a10](https://github.com/nuxt/ui/commit/d227a105d8d409ea0753153afaecf639ddb80fed))
* **CommandPalette:** prevent hover background on disabled items ([ba534f1](https://github.com/nuxt/ui/commit/ba534f18b94383c97b2654d892ee4b8b024b3fab))
* **components:** refactor types after `@nuxt/module-builder` upgrade ([#3855](https://github.com/nuxt/ui/issues/3855)) ([39c861a](https://github.com/nuxt/ui/commit/39c861a64bbd452256ebd1a14a257b94c35855d4))
* **components:** respect `transform-origin` in popper content ([#3919](https://github.com/nuxt/ui/issues/3919)) ([01d8dc7](https://github.com/nuxt/ui/commit/01d8dc72adb0b32ad68bb4a98bf24b17f435a89c))
* **ContextMenu/DropdownMenu:** handle RTL mode ([#3744](https://github.com/nuxt/ui/issues/3744)) ([1ae5cc0](https://github.com/nuxt/ui/commit/1ae5cc09cb2eca6b6f53eb04db9dcc731b696cae))
* **ContextMenuContent/DropdownMenuContent:** remove unwanted `any` ([#3741](https://github.com/nuxt/ui/issues/3741)) ([97274f1](https://github.com/nuxt/ui/commit/97274f15b8bfe457e7e206f81b32e3febf0f875d))
* **Form:** input and output type inference ([#3938](https://github.com/nuxt/ui/issues/3938)) ([f429498](https://github.com/nuxt/ui/commit/f42949820be9be9fca41abc653dc12c033e1eeec))
* **Form:** loses focus on submit ([#3796](https://github.com/nuxt/ui/issues/3796)) ([8e78eb1](https://github.com/nuxt/ui/commit/8e78eb15c85beef1c814206c4a192d4eb00a7e86))
* **InputMenu/Select/SelectMenu:** add `min-w-fit` to `content` slot ([#3922](https://github.com/nuxt/ui/issues/3922)) ([f6b3761](https://github.com/nuxt/ui/commit/f6b376110c8bee2c41ae3137bb972aad402ebff1))
* **InputMenu/SelectMenu:** correctly call `onSelect` events ([#3735](https://github.com/nuxt/ui/issues/3735)) ([f25fed5](https://github.com/nuxt/ui/commit/f25fed58e988b304e79cdb536d544d257395cf89))
* **InputMenu/SelectMenu:** prevent `disabled` items to be selected ([8435a0f](https://github.com/nuxt/ui/commit/8435a0fe1622eb5b6863b6e4751c9d2d1be36db9)), closes [#3474](https://github.com/nuxt/ui/issues/3474)
* **InputMenu/SelectMenu:** remove `valueKey` string case ([9ca213b](https://github.com/nuxt/ui/commit/9ca213bd3340492d7503a34bd142e1f79a697050)), closes [#3949](https://github.com/nuxt/ui/issues/3949) [#3331](https://github.com/nuxt/ui/issues/3331)
* **InputMenu/SelectMenu:** support arbitrary `value` ([#3779](https://github.com/nuxt/ui/issues/3779)) ([52a97e2](https://github.com/nuxt/ui/commit/52a97e2df7903f91e3134931eb0d6bd4c528f71f))
* **InputMenu:** emit `change` on multiple item removal ([9d2fed1](https://github.com/nuxt/ui/commit/9d2fed125013e3bbfbf9435678729cd05254a5e8)), closes [#3756](https://github.com/nuxt/ui/issues/3756)
* **Link:** proxy `download` property ([#3879](https://github.com/nuxt/ui/issues/3879)) ([47cdc2e](https://github.com/nuxt/ui/commit/47cdc2e1d8cd9803ebc954ccae110d62b9a08779))
* **NavigationMenu:** add `sm:w-auto` content slot ([abe0859](https://github.com/nuxt/ui/commit/abe0859691e06564f68335bd82dcd121e976408e)), closes [#3788](https://github.com/nuxt/ui/issues/3788)
* **Skeleton:** improve accessibility ([#3613](https://github.com/nuxt/ui/issues/3613)) ([3484832](https://github.com/nuxt/ui/commit/3484832822015a224ce6fbeae5132018875557e6))
* **Stepper:** ui prop override on `icon` and `content` slots ([1d45980](https://github.com/nuxt/ui/commit/1d459803dc052a16b8966ee89c71646bf6ef1c16)), closes [#3785](https://github.com/nuxt/ui/issues/3785)
* **Table:** improve `data` reactivity ([#3967](https://github.com/nuxt/ui/issues/3967)) ([6e27304](https://github.com/nuxt/ui/commit/6e27304d8ca459a04667bac404084264a8cf58fd))
* **Table:** pass header `colspan` to `th` ([#3926](https://github.com/nuxt/ui/issues/3926)) ([122e8ac](https://github.com/nuxt/ui/commit/122e8ac8f41ba093cd350c3ce642263263f77296))
* **Tree:** simplify reusable template types ([#3836](https://github.com/nuxt/ui/issues/3836)) ([3deed4c](https://github.com/nuxt/ui/commit/3deed4c271cad4adc2a4c47d5dd02e95a14ce11a))
* **types:** allow color identifiers with dashes ([#3896](https://github.com/nuxt/ui/issues/3896)) ([e5a1e26](https://github.com/nuxt/ui/commit/e5a1e26f9db763b54caed4ca313f44d1b5fe269d))
* **types:** handle `ClassValue` in `ui` prop ([eea1415](https://github.com/nuxt/ui/commit/eea14155aa612649bc969d806ec5df4295945c70)), closes [#3860](https://github.com/nuxt/ui/issues/3860)
* **types:** improve dynamic slots ([#3857](https://github.com/nuxt/ui/issues/3857)) ([8dd9d08](https://github.com/nuxt/ui/commit/8dd9d08209e47a7d9a5654db4fb936b4cbcfc021))
* **usePortal:** adjust portal target resolution logic ([#3954](https://github.com/nuxt/ui/issues/3954)) ([db11db6](https://github.com/nuxt/ui/commit/db11db6ff1ce4b27a66aaa03f07870ba36426181))
* **vite:** vitest skipping nuxt imports transformations ([#3925](https://github.com/nuxt/ui/issues/3925)) ([c31bffa](https://github.com/nuxt/ui/commit/c31bffad1b8afeda584bca8c73bb7f790eb12a9f))
## [3.0.2](https://github.com/nuxt/ui/compare/v3.0.1...v3.0.2) (2025-03-28)
### Features

View File

@@ -16,6 +16,10 @@ Nuxt UI harnesses the combined strengths of [Reka UI](https://reka-ui.com/), [Ta
> [!NOTE]
> You are on the `v3` development branch, check out the [v2 branch](https://github.com/nuxt/ui/tree/v2) for Nuxt UI v2.
> [!TIP]
> **Looking for more components ?**
> Check out [Nuxt UI Pro](https://ui.nuxt.com/pro), a collection of premium Vue components, composables, and utilities built on top of Nuxt UI for faster and more powerful app development.
## Documentation
Visit https://ui.nuxt.com to explore the documentation.

View File

@@ -11,7 +11,7 @@ export default defineBuildConfig({
delimiters: ['', ''],
values: {
// Used in development to import directly from theme
'const isUiDev = true': 'const isUiDev = false'
'process.argv.includes(\'--uiDev\')': 'false'
}
}
},

View File

@@ -31,8 +31,9 @@ const component = ({ name, primitive, pro, prose, content }) => {
? `
<script lang="ts">
import type { AppConfig } from '@nuxt/schema'
${pro ? `import type { ComponentConfig } from '@nuxt/ui'` : ''}
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
import type { ComponentConfig } from '../types/utils'
${!pro ? `import type { ComponentConfig } from '../types/utils'` : ''}
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
@@ -62,11 +63,11 @@ defineSlots<${upperName}Slots>()
const appConfig = useAppConfig() as ${upperName}['AppConfig']
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.${pro ? 'uiPro' : 'ui'}?.${camelName} || {}) })())
</script>
<template>
<Primitive :as="as" :class="ui.root({ class: [props.class, props.ui?.root] })">
<Primitive :as="as" :class="ui.root({ class: [props.ui?.root, props.class] })">
<slot />
</Primitive>
</template>
@@ -75,8 +76,9 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName}
<script lang="ts">
import type { ${upperName}RootProps, ${upperName}RootEmits } from 'reka-ui'
import type { AppConfig } from '@nuxt/schema'
${pro ? `import type { ComponentConfig } from '@nuxt/ui'` : ''}
import theme from '#build/${path}/${prose ? 'prose/' : ''}${content ? 'content/' : ''}${kebabName}'
import type { ComponentConfig } from '../types/utils'
${!pro ? `import type { ComponentConfig } from '../types/utils'` : ''}
type ${upperName} = ComponentConfig<typeof theme, AppConfig, ${upperName}${pro ? `, '${key}'` : ''}>
@@ -105,11 +107,11 @@ const appConfig = useAppConfig() as ${upperName}['AppConfig']
const rootProps = useForwardPropsEmits(reactivePick(props), emits)
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.${camelName} || {}) })())
const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.${pro ? 'uiPro' : 'ui'}?.${camelName} || {}) })())
</script>
<template>
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.class, props.ui?.root] })" />
<${upperName}Root v-bind="rootProps" :class="ui.root({ class: [props.ui?.root, props.class] })" />
</template>
`
}
@@ -186,6 +188,7 @@ links:${primitive
- label: GitHub
icon: i-simple-icons-github
to: https://github.com/nuxt/${pro ? 'ui-pro' : 'ui'}/tree/v3/src/runtime/components/${upperName}.vue
navigation.badge: Soon
---
## Usage

View File

@@ -23,7 +23,7 @@ useHead({
{ key: 'theme-color', name: 'theme-color', content: color }
],
link: [
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
// { rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' },
{ rel: 'canonical', href: `https://ui.nuxt.com${withoutTrailingSlash(route.path)}` }
],
style: [
@@ -40,6 +40,8 @@ useServerSeoMeta({
twitterCard: 'summary_large_image'
})
useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
@@ -51,7 +53,7 @@ provide('navigation', mappedNavigation)
<NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
<template v-if="!route.path.startsWith('/examples')">
<Banner />
<!-- <Banner /> -->
<Header :links="links" />
</template>

View File

@@ -1,7 +1,7 @@
@import "tailwindcss" theme(static) source("../../../..");
@import "@nuxt/ui-pro";
@source "../../../content";
@source "../../../content/**/*";
@source "../../../node_modules/.c12";
@theme static {

View File

@@ -23,27 +23,27 @@ onMounted(() => {
@reference "../assets/css/main.css";
.carbon :deep(#carbonads) {
@apply relative border border-(--ui-border) rounded-[calc(var(--ui-radius)*1.5)] hover:bg-(--ui-bg-elevated)/50 w-full transition-colors min-h-[220px] p-2;
@apply relative border border-default rounded-md hover:bg-elevated/50 w-full transition-colors min-h-[220px] p-2;
.carbon-img {
@apply flex justify-center w-full;
& > img {
@apply !max-w-full w-full rounded-(--ui-radius);
@apply !max-w-full w-full rounded-sm;
}
}
.carbon-text {
@apply text-sm text-(--ui-text-muted) transition-colors text-center text-pretty flex pt-2;
@apply text-sm text-muted transition-colors text-center text-pretty flex pt-2;
}
.carbon-poweredby {
@apply block text-xs text-center text-(--ui-text-muted) pt-2;
@apply block text-xs text-center text-muted pt-2;
}
&:hover {
.carbon-text {
@apply text-(--ui-text);
@apply text-default;
}
}
}

View File

@@ -22,8 +22,8 @@ const links = [{
<UFooter>
<template #left>
<NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-sm text-(--ui-text-muted)">
Published under <span class="text-(--ui-text-highlighted)">MIT License</span>
<NuxtLink to="https://github.com/nuxt/ui" target="_blank" class="text-sm text-muted">
Published under <span class="text-highlighted">MIT License</span>
</NuxtLink>
</template>

View File

@@ -19,8 +19,8 @@ watch(framework, () => {
:content="false"
color="neutral"
:ui="{
indicator: 'bg-(--ui-bg)',
trigger: 'px-1 data-[state=active]:text-(--ui-text-highlighted)'
indicator: 'bg-default',
trigger: 'px-1 data-[state=active]:text-highlighted w-full'
}"
size="xs"
@update:model-value="(framework = $event as string)"

View File

@@ -22,9 +22,7 @@ onMounted(() => {
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
const githubLink = computed(() => {
return `https://github.com/nuxt/${value.value}`
})
const githubLink = computed(() => `https://github.com/nuxt/${value.value}`)
const desktopLinks = computed(() => props.links.map(({ icon, ...link }) => link))
const mobileLinks = computed(() => [
@@ -36,12 +34,22 @@ const mobileLinks = computed(() => [
target: '_blank'
}
])
const items = computed(() => {
const ui2 = { label: 'v2.22.0', to: 'https://ui2.nuxt.com' }
const uiPro1 = { label: 'v1.8.0', to: 'https://ui2.nuxt.com/pro' }
return [
{ label: `v${config.version}`, active: true, color: 'primary' as const, checked: true, type: 'checkbox' as const },
route.path === '/' ? ui2 : route.path.startsWith('/pro') ? uiPro1 : module.value === 'ui-pro' ? uiPro1 : ui2
]
})
</script>
<template>
<UHeader :ui="{ left: 'min-w-0' }" :menu="{ shouldScaleBackground: true }">
<template #left>
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-(--ui-text-highlighted) min-w-0 focus-visible:outline-(--ui-primary) shrink-0" aria-label="Nuxt UI">
<NuxtLink to="/" class="flex items-end gap-2 font-bold text-xl text-highlighted min-w-0 focus-visible:outline-primary shrink-0" aria-label="Nuxt UI">
<Logo v-if="route.path === '/'" class="w-auto h-6 shrink-0" />
<LogoPro v-else-if="route.path.startsWith('/pro')" class="w-auto h-6 shrink-0" />
<template v-else>
@@ -53,7 +61,7 @@ const mobileLinks = computed(() => [
<UDropdownMenu
v-slot="{ open }"
:modal="false"
:items="[{ label: `v${config.version}`, active: true, color: 'primary', checked: true, type: 'checkbox' }, { label: module === 'ui-pro' ? 'v1.7.1' : 'v2.21.1', to: module === 'ui-pro' ? 'https://ui2.nuxt.com/pro' : 'https://ui2.nuxt.com' }]"
:items="items"
:ui="{ content: 'w-(--reka-dropdown-menu-trigger-width) min-w-0' }"
size="xs"
>
@@ -63,7 +71,7 @@ const mobileLinks = computed(() => [
trailing-icon="i-lucide-chevron-down"
size="xs"
class="-mb-[6px] font-semibold rounded-full truncate"
:class="[open && 'bg-(--ui-primary)/15 ']"
:class="[open && 'bg-primary/15 ']"
:ui="{
trailingIcon: ['transition-transform duration-200', open ? 'rotate-180' : undefined].filter(Boolean).join(' ')
}"
@@ -108,7 +116,7 @@ const mobileLinks = computed(() => [
<span class="inline-flex items-center gap-0.5">
{{ link.title }}
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-(--ui-primary)">PRO</sup>
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-primary">PRO</sup>
</span>
</template>
</UContentNavigation>

View File

@@ -19,8 +19,8 @@ watch(module, () => {
:content="false"
color="neutral"
:ui="{
indicator: 'bg-(--ui-bg)',
trigger: 'px-1 data-[state=active]:text-(--ui-text-highlighted)'
indicator: 'bg-default',
trigger: 'px-1 data-[state=active]:text-highlighted w-full'
}"
size="xs"
@update:model-value="(module = $event as string)"

View File

@@ -0,0 +1,77 @@
<script setup lang="ts">
const route = useRoute()
const toast = useToast()
const { copy, copied } = useClipboard()
const site = useSiteConfig()
const mdPath = computed(() => `${site.url}/raw${route.path}.md`)
const items = [
{
label: 'Copy Markdown link',
icon: 'i-lucide-link',
onSelect() {
copy(mdPath.value)
toast.add({
title: 'Copied to clipboard',
icon: 'i-lucide-check-circle'
})
}
},
{
label: 'View as Markdown',
icon: 'i-simple-icons:markdown',
target: '_blank',
to: `/raw${route.path}.md`
},
{
label: 'Open in ChatGPT',
icon: 'i-simple-icons:openai',
target: '_blank',
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
},
{
label: 'Open in Claude',
icon: 'i-simple-icons:anthropic',
target: '_blank',
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
}
]
async function copyPage() {
copy(await $fetch<string>(`/raw${route.path}.md`))
}
</script>
<template>
<UButtonGroup>
<UButton
label="Copy page"
:icon="copied ? 'i-lucide-copy-check' : 'i-lucide-copy'"
color="neutral"
variant="outline"
:ui="{
leadingIcon: [copied ? 'text-primary' : 'text-neutral', 'size-3.5']
}"
@click="copyPage"
/>
<UDropdownMenu
:items="items"
:content="{
align: 'end',
side: 'bottom',
sideOffset: 8
}"
:ui="{
content: 'w-48'
}"
>
<UButton
icon="i-lucide-chevron-down"
size="sm"
color="neutral"
variant="outline"
/>
</UDropdownMenu>
</UButtonGroup>
</template>

View File

@@ -153,7 +153,8 @@ const options = computed(() => {
const items = propItems.length
? propItems.map((item: any) => ({
value: item,
label: String(item)
label: String(item),
chip: key.toLowerCase().endsWith('color') ? { color: item } : undefined
}))
: prop?.type === 'boolean' || prop?.type === 'boolean | undefined'
? [{ value: true, label: 'true' }, { value: false, label: 'false' }]
@@ -329,15 +330,15 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
<template>
<div class="my-5">
<div class="relative">
<div v-if="options.length" class="flex flex-wrap items-center gap-2.5 border border-(--ui-border-muted) border-b-0 relative rounded-t-[calc(var(--ui-radius)*1.5)] px-4 py-2.5 overflow-x-auto">
<div v-if="options.length" class="flex flex-wrap items-center gap-2.5 border border-muted border-b-0 relative rounded-t-md px-4 py-2.5 overflow-x-auto">
<template v-for="option in options" :key="option.name">
<UFormField
:label="option.label"
size="sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -348,7 +349,7 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
value-key="value"
color="neutral"
variant="soft"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
class="rounded-sm rounded-l-none min-w-12"
:class="[option.name.toLowerCase().endsWith('color') && 'pl-6']"
:ui="{ itemLeadingChip: 'size-2' }"
@update:model-value="setComponentProp(option.name, $event)"
@@ -370,14 +371,14 @@ const { data: ast } = await useAsyncData(`component-code-${name}-${hash({ props:
:model-value="getComponentProp(option.name)"
color="neutral"
variant="soft"
:ui="{ base: 'rounded-(--ui-radius) rounded-l-none min-w-12' }"
:ui="{ base: 'rounded-sm rounded-l-none min-w-12' }"
@update:model-value="setComponentProp(option.name, $event)"
/>
</UFormField>
</template>
</div>
<div v-if="component" class="flex justify-center border border-b-0 border-(--ui-border-muted) relative p-4 z-[1]" :class="[!options.length && 'rounded-t-[calc(var(--ui-radius)*1.5)]', props.class, { 'overflow-hidden': props.overflowHidden }]">
<div v-if="component" class="flex justify-center border border-b-0 border-muted relative p-4 z-[1]" :class="[!options.length && 'rounded-t-md', props.class, { 'overflow-hidden': props.overflowHidden }]">
<component :is="component" v-bind="{ ...componentProps, ...componentEvents }">
<template v-for="slot in Object.keys(slots || {})" :key="slot" #[slot]>
<slot :name="slot" mdc-unwrap="p">

View File

@@ -150,8 +150,8 @@ const urlSearchParams = computed(() => {
<template>
<div ref="el" class="my-5">
<template v-if="preview">
<div class="border border-(--ui-border-muted) relative z-[1]" :class="[{ 'border-b-0 rounded-t-[calc(var(--ui-radius)*1.5)]': props.source, 'rounded-[calc(var(--ui-radius)*1.5)]': !props.source, 'overflow-hidden': props.overflowHidden }]">
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-(--ui-border-muted)">
<div class="border border-muted relative z-[1]" :class="[{ 'border-b-0 rounded-t-md': props.source, 'rounded-md': !props.source, 'overflow-hidden': props.overflowHidden }]">
<div v-if="props.options?.length || !!slots.options" class="flex gap-4 p-4 border-b border-muted">
<slot name="options" />
<UFormField
@@ -160,10 +160,10 @@ const urlSearchParams = computed(() => {
:label="option.label"
:name="option.name"
size="sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -175,7 +175,7 @@ const urlSearchParams = computed(() => {
:value-key="option.name.toLowerCase().endsWith('color') ? 'value' : undefined"
color="neutral"
variant="soft"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
class="rounded-sm rounded-l-none min-w-12"
:multiple="option.multiple"
:class="[option.name.toLowerCase().endsWith('color') && 'pl-6']"
:ui="{ itemLeadingChip: 'size-2' }"
@@ -196,7 +196,7 @@ const urlSearchParams = computed(() => {
:model-value="get(optionsValues, option.name)"
color="neutral"
variant="soft"
:ui="{ base: 'rounded-(--ui-radius) rounded-l-none min-w-12' }"
:ui="{ base: 'rounded-sm rounded-l-none min-w-12' }"
@update:model-value="set(optionsValues, option.name, $event)"
/>
</UFormField>

View File

@@ -112,7 +112,7 @@ const metaProps: ComputedRef<ComponentMeta['props']> = computed(() => {
<ProseTd>
<HighlightInlineType v-if="prop.type" :type="prop.type" />
<MDC v-if="prop.description" :value="prop.description" class="text-(--ui-text-toned) mt-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-description`" />
<MDC v-if="prop.description" :value="prop.description" class="text-toned mt-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-description`" />
<ComponentPropsLinks v-if="prop.tags?.length" :prop="prop" />
<ComponentPropsSchema v-if="prop.schema" :prop="prop" :ignore="ignore" />

View File

@@ -38,12 +38,12 @@ const schemaProps = computed(() => {
</script>
<template>
<ProseCollapsible v-if="schemaProps?.length" class="mt-1">
<ProseCollapsible v-if="schemaProps?.length" class="mt-1 mb-0">
<ProseUl>
<ProseLi v-for="schemaProp in schemaProps" :key="schemaProp.name">
<HighlightInlineType :type="`${schemaProp.name}${schemaProp.required === false ? '?' : ''}: ${schemaProp.type}`" />
<MDC v-if="schemaProp.description" :value="schemaProp.description" class="text-(--ui-text-muted) my-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-${schemaProp.name}-description`" />
<MDC v-if="schemaProp.description" :value="schemaProp.description" class="text-muted my-1" :cache-key="`${kebabCase(route.path)}-${prop.name}-${schemaProp.name}-description`" />
</ProseLi>
</ProseUl>
</ProseCollapsible>

View File

@@ -36,7 +36,7 @@ const meta = await fetchComponentMeta(name as any)
<ProseTd>
<HighlightInlineType v-if="slot.type" :type="slot.type" />
<MDC v-if="slot.description" :value="slot.description" class="text-(--ui-text-toned) mt-1" :cache-key="`${kebabCase(route.path)}-${slot.name}-description`" />
<MDC v-if="slot.description" :value="slot.description" class="text-toned mt-1" :cache-key="`${kebabCase(route.path)}-${slot.name}-description`" />
</ProseTd>
</ProseTr>
</ProseTbody>

View File

@@ -1,6 +1,6 @@
<template>
<div class="relative overflow-hidden rounded-(--ui-radius) border border-dashed border-(--ui-border-accented) opacity-75 px-4 flex items-center justify-center">
<svg class="absolute inset-0 h-full w-full stroke-(--ui-border-inverted)/10" fill="none">
<div class="relative overflow-hidden rounded-sm border border-dashed border-accented opacity-75 px-4 flex items-center justify-center">
<svg class="absolute inset-0 h-full w-full stroke-inverted/10" fill="none">
<defs>
<pattern
id="pattern-5c1e4f0e-62d5-498b-8ff0-cf77bb448c8e"

View File

@@ -25,7 +25,11 @@ function getEmojiFlag(locale: string): string {
kk: 'kz', // Kazakh -> Kazakhstan
km: 'kh', // Khmer -> Cambodia
ko: 'kr', // Korean -> South Korea
ky: 'kg', // Kyrgyz -> Kyrgyzstan
lb: 'lu', // Luxembourgish -> Luxembourg
ms: 'my', // Malay -> Malaysia
nb: 'no', // Norwegian Bokmål -> Norway
sl: 'si', // Slovenian -> Slovenia
sv: 'se', // Swedish -> Sweden
uk: 'ua', // Ukrainian -> Ukraine
ur: 'pk', // Urdu -> Pakistan

View File

@@ -20,7 +20,7 @@ const items: AccordionItem[] = [
<template>
<UAccordion :items="items">
<template #content="{ item }">
<p class="pb-3.5 text-sm text-(--ui-text-muted)">
<p class="pb-3.5 text-sm text-muted">
This is the {{ item.label }} panel.
</p>
</template>

View File

@@ -24,7 +24,7 @@ const items = [
<template>
<UAccordion :items="items">
<template #colors="{ item }">
<p class="text-sm pb-3.5 text-(--ui-primary)">
<p class="text-sm pb-3.5 text-primary">
{{ item.content }}
</p>
</template>

View File

@@ -3,7 +3,7 @@
<ULink
to="https://github.com/benjamincanac"
target="_blank"
class="hover:ring-(--ui-primary) transition"
class="hover:ring-primary transition"
raw
>
<UAvatar
@@ -15,7 +15,7 @@
<ULink
to="https://github.com/romhml"
target="_blank"
class="hover:ring-(--ui-primary) transition"
class="hover:ring-primary transition"
raw
>
<UAvatar
@@ -27,7 +27,7 @@
<ULink
to="https://github.com/noook"
target="_blank"
class="hover:ring-(--ui-primary) transition"
class="hover:ring-primary transition"
raw
>
<UAvatar

View File

@@ -20,7 +20,7 @@ const items: BreadcrumbItem[] = [
<template>
<UBreadcrumb :items="items">
<template #separator>
<span class="mx-2 text-(--ui-text-muted)">/</span>
<span class="mx-2 text-muted">/</span>
</template>
</UBreadcrumb>
</template>

View File

@@ -0,0 +1,21 @@
<script setup lang="ts">
import { CalendarDate } from '@internationalized/date'
const date = shallowRef(new CalendarDate(2025, 4, 2))
</script>
<template>
<div class="flex flex-col gap-4">
<UCalendar v-model="date" :month-controls="false" :year-controls="false" />
<div class="flex justify-between gap-4">
<UButton color="neutral" variant="outline" @click="date = date.subtract({ months: 1 })">
Prev
</UButton>
<UButton color="neutral" variant="outline" @click="date = date.add({ months: 1 })">
Next
</UButton>
</div>
</div>
</template>

View File

@@ -0,0 +1,58 @@
<script setup lang="ts">
const items = [
'https://picsum.photos/640/640?random=1',
'https://picsum.photos/640/640?random=2',
'https://picsum.photos/640/640?random=3',
'https://picsum.photos/640/640?random=4',
'https://picsum.photos/640/640?random=5',
'https://picsum.photos/640/640?random=6'
]
const carousel = useTemplateRef('carousel')
const activeIndex = ref(0)
function onClickPrev() {
activeIndex.value--
}
function onClickNext() {
activeIndex.value++
}
function onSelect(index: number) {
activeIndex.value = index
}
function select(index: number) {
activeIndex.value = index
carousel.value?.emblaApi?.scrollTo(index)
}
</script>
<template>
<div class="flex-1 w-full">
<UCarousel
ref="carousel"
v-slot="{ item }"
arrows
:items="items"
:prev="{ onClick: onClickPrev }"
:next="{ onClick: onClickNext }"
class="w-full max-w-xs mx-auto"
@select="onSelect"
>
<img :src="item" width="320" height="320" class="rounded-lg">
</UCarousel>
<div class="flex gap-1 justify-between pt-4 max-w-xs mx-auto">
<div
v-for="(item, index) in items"
:key="index"
class="size-11 opacity-25 hover:opacity-100 transition-opacity"
:class="{ 'opacity-100': activeIndex === index }"
@click="select(index)"
>
<img :src="item" width="44" height="44" class="rounded-lg">
</div>
</div>
</div>
</template>

View File

@@ -83,7 +83,7 @@ const groups = [
</template>
<template #billing-label="{ item }">
{{ item.label }}
<span class="font-medium text-primary">{{ item.label }}</span>
<UBadge variant="subtle" size="sm">
50% off

View File

@@ -1,9 +1,10 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'command-palette-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string, email: string }[]) => {
return data?.map(user => ({ id: user.id, label: user.name, suffix: user.email, avatar: { src: `https://i.pravatar.cc/120?img=${user.id}` } })) || []

View File

@@ -0,0 +1,119 @@
<script setup lang="ts">
const toast = useToast()
const groups = [{
id: 'actions',
label: 'Actions',
items: [{
label: 'Create new',
icon: 'i-lucide-plus',
children: [{
label: 'New file',
icon: 'i-lucide-file-plus',
suffix: 'Create a new file in the current directory',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New file created!' })
},
kbds: ['meta', 'N']
}, {
label: 'New folder',
icon: 'i-lucide-folder-plus',
suffix: 'Create a new folder in the current directory',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New folder created!' })
},
kbds: ['meta', 'F']
}, {
label: 'New project',
icon: 'i-lucide-folder-git',
suffix: 'Create a new project from a template',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'New project created!' })
},
kbds: ['meta', 'P']
}]
}, {
label: 'Share',
icon: 'i-lucide-share',
children: [{
label: 'Copy link',
icon: 'i-lucide-link',
suffix: 'Copy a link to the current item',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Link copied to clipboard!' })
},
kbds: ['meta', 'L']
}, {
label: 'Share via email',
icon: 'i-lucide-mail',
suffix: 'Share the current item via email',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Share via email dialog opened!' })
}
}, {
label: 'Share on social',
icon: 'i-lucide-share-2',
suffix: 'Share the current item on social media',
children: [{
label: 'Twitter',
icon: 'i-simple-icons-twitter',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on Twitter!' })
}
}, {
label: 'LinkedIn',
icon: 'i-simple-icons-linkedin',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on LinkedIn!' })
}
}, {
label: 'Facebook',
icon: 'i-simple-icons-facebook',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Shared on Facebook!' })
}
}]
}]
}, {
label: 'Settings',
icon: 'i-lucide-settings',
children: [{
label: 'General',
icon: 'i-lucide-sliders',
suffix: 'Configure general settings',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'General settings opened!' })
}
}, {
label: 'Appearance',
icon: 'i-lucide-palette',
suffix: 'Customize the appearance',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Appearance settings opened!' })
}
}, {
label: 'Security',
icon: 'i-lucide-shield',
suffix: 'Manage security settings',
onSelect(e: Event) {
e.preventDefault()
toast.add({ title: 'Security settings opened!' })
}
}]
}]
}]
</script>
<template>
<UCommandPalette :groups="groups" class="flex-1" />
</template>

View File

@@ -35,7 +35,7 @@ const items = computed<ContextMenuItem[]>(() => [{
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>

View File

@@ -28,7 +28,7 @@ const items: ContextMenuItem[][] = [
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
</UContextMenu>

View File

@@ -19,7 +19,7 @@ const items = [
<template>
<UContextMenu :items="items" :ui="{ content: 'w-48' }">
<div class="flex items-center justify-center rounded-md border border-dashed border-(--ui-border-accented) text-sm aspect-video w-72">
<div class="flex items-center justify-center rounded-md border border-dashed border-accented text-sm aspect-video w-72">
Right click here
</div>
@@ -28,7 +28,7 @@ const items = [
</template>
<template #refresh-trailing>
<UIcon v-if="loading" name="i-lucide-refresh-cw" class="shrink-0 size-5 text-(--ui-primary) animate-spin" />
<UIcon v-if="loading" name="i-lucide-loader-circle" class="shrink-0 size-5 text-primary animate-spin" />
</template>
</UContextMenu>
</template>

View File

@@ -3,11 +3,11 @@ const open = ref(false)
</script>
<template>
<UDrawer v-model:open="open" :dismissible="false" :ui="{ header: 'flex items-center justify-between' }">
<UDrawer v-model:open="open" :dismissible="false" :handle="false" :ui="{ header: 'flex items-center justify-between' }">
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #header>
<h2 class="text-(--ui-text-highlighted) font-semibold">
<h2 class="text-highlighted font-semibold">
Drawer non-dismissible
</h2>

View File

@@ -0,0 +1,28 @@
<script setup lang="ts">
const open = ref(false)
</script>
<template>
<UDrawer
v-model:open="open"
:dismissible="false"
:overlay="false"
:handle="false"
:modal="false"
:ui="{ header: 'flex items-center justify-between' }"
>
<UButton label="Open" color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-up" />
<template #header>
<h2 class="text-highlighted font-semibold">
Drawer non-dismissible
</h2>
<UButton color="neutral" variant="ghost" icon="i-lucide-x" @click="open = false" />
</template>
<template #body>
<Placeholder class="h-48" />
</template>
</UDrawer>
</template>

View File

@@ -21,7 +21,7 @@ const items = [
<UButton label="Open" color="neutral" variant="outline" icon="i-lucide-menu" />
<template #profile-trailing>
<UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-(--ui-primary)" />
<UIcon name="i-lucide-badge-check" class="shrink-0 size-5 text-primary" />
</template>
</UDropdownMenu>
</template>

View File

@@ -15,6 +15,9 @@ const schema = z.object({
select: z.string().refine(value => value === 'option-2', {
message: 'Select Option 2'
}),
selectMultiple: z.array(z.string()).refine(values => values.includes('option-2'), {
message: 'Include Option 2'
}),
selectMenu: z.any().refine(option => option?.value === 'option-2', {
message: 'Select Option 2'
}),
@@ -30,6 +33,9 @@ const schema = z.object({
radioGroup: z.string().refine(value => value === 'option-2', {
message: 'Select Option 2'
}),
checkboxGroup: z.any().refine(values => !!values?.find((option: any) => option === 'option-2'), {
message: 'Include Option 2'
}),
slider: z.number().max(20, { message: 'Must be less than 20' }),
pin: z.string().regex(/^\d$/).array().length(5)
})
@@ -78,6 +84,10 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<USelect v-model="state.select" :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMultiple" label="Select (Multiple)">
<USelect v-model="state.selectMultiple" multiple :items="items" class="w-full" />
</UFormField>
<UFormField name="selectMenu" label="Select Menu">
<USelectMenu v-model="state.selectMenu" :items="items" class="w-full" />
</UFormField>
@@ -101,11 +111,14 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UFormField label="Textarea" name="textarea">
<UTextarea v-model="state.textarea" class="w-full" />
</UFormField>
<UFormField name="radioGroup">
<URadioGroup v-model="state.radioGroup" legend="Radio group" :items="items" />
</UFormField>
<div class="flex gap-4">
<UFormField name="radioGroup">
<URadioGroup v-model="state.radioGroup" legend="Radio group" :items="items" />
</UFormField>
<UFormField name="checkboxGroup">
<UCheckboxGroup v-model="state.checkboxGroup" legend="Checkbox group" :items="items" />
</UFormField>
</div>
<UFormField name="pin" label="Pin Input" :error-pattern="/(pin)\..*/">
<UPinInput v-model="state.pin" />
</UFormField>

View File

@@ -39,7 +39,7 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UCheckbox v-model="state.news" name="news" label="Register to our newsletter" @update:model-value="state.email = undefined" />
</div>
<UForm v-if="state.news" :state="state" :schema="nestedSchema">
<UForm v-if="state.news" :state="state" :schema="nestedSchema" attach>
<UFormField label="Email" name="email">
<UInput v-model="state.email" placeholder="john@lennon.com" />
</UFormField>

View File

@@ -51,7 +51,14 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
<UInput v-model="state.customer" placeholder="Wonka Industries" />
</UFormField>
<UForm v-for="item, count in state.items" :key="count" :state="item" :schema="itemSchema" class="flex gap-2">
<UForm
v-for="item, count in state.items"
:key="count"
:state="item"
:schema="itemSchema"
attach
class="flex gap-2"
>
<UFormField :label="!count ? 'Description' : undefined" name="description">
<UInput v-model="item.description" />
</UFormField>

View File

@@ -36,7 +36,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template #item-label="{ item }">
{{ item.label }}
<span class="text-(--ui-text-muted)">
<span class="text-muted">
{{ item.email }}
</span>
</template>

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({

View File

@@ -0,0 +1,9 @@
<script setup lang="ts">
const tags = ref(['Vue'])
</script>
<template>
<UFormField label="Tags" required>
<UInputTags v-model="tags" placeholder="Enter tags..." />
</UFormField>
</template>

View File

@@ -10,12 +10,12 @@ const domain = ref(domains[0])
v-model="value"
placeholder="nuxt"
:ui="{
base: 'pl-[57px]',
base: 'pl-14.5',
leading: 'pointer-events-none'
}"
>
<template #leading>
<p class="text-sm text-(--ui-text-muted)">
<p class="text-sm text-muted">
https://
</p>
</template>

View File

@@ -13,7 +13,7 @@ const maxLength = 15
<template #trailing>
<div
id="character-count"
class="text-xs text-(--ui-text-muted) tabular-nums"
class="text-xs text-muted tabular-nums"
aria-live="polite"
role="status"
>

View File

@@ -1,15 +1,9 @@
<script setup lang="ts">
const value = ref('npx nuxi module add ui')
const copied = ref(false)
import { useClipboard } from '@vueuse/core'
function copy() {
navigator.clipboard.writeText(value.value)
copied.value = true
const value = ref('npx nuxt module add ui')
setTimeout(() => {
copied.value = false
}, 2000)
}
const { copy, copied } = useClipboard()
</script>
<template>
@@ -25,7 +19,7 @@ function copy() {
size="sm"
:icon="copied ? 'i-lucide-copy-check' : 'i-lucide-copy'"
aria-label="Copy to clipboard"
@click="copy"
@click="copy(value)"
/>
</UTooltip>
</template>

View File

@@ -4,8 +4,8 @@ const value = ref('')
<template>
<UInput v-model="value" placeholder="" :ui="{ base: 'peer' }">
<label class="pointer-events-none absolute left-0 -top-2.5 text-(--ui-text-highlighted) text-xs font-medium px-1.5 transition-all peer-focus:-top-2.5 peer-focus:text-(--ui-text-highlighted) peer-focus:text-xs peer-focus:font-medium peer-placeholder-shown:text-sm peer-placeholder-shown:text-(--ui-text-dimmed) peer-placeholder-shown:top-1.5 peer-placeholder-shown:font-normal">
<span class="inline-flex bg-(--ui-bg) px-1">Email address</span>
<label class="pointer-events-none absolute left-0 -top-2.5 text-highlighted text-xs font-medium px-1.5 transition-all peer-focus:-top-2.5 peer-focus:text-highlighted peer-focus:text-xs peer-focus:font-medium peer-placeholder-shown:text-sm peer-placeholder-shown:text-dimmed peer-placeholder-shown:top-1.5 peer-placeholder-shown:font-normal">
<span class="inline-flex bg-default px-1">Email address</span>
</label>
</UInput>
</template>

View File

@@ -0,0 +1,14 @@
<script setup lang="ts">
import { vMaska } from 'maska/vue'
</script>
<template>
<div class="flex flex-col gap-2">
<UInput v-maska="'#### #### #### ####'" placeholder="4242 4242 4242 4242" icon="i-lucide-credit-card" />
<div class="flex items-center gap-2">
<UInput v-maska="'##/##'" placeholder="MM/YY" icon="i-lucide-calendar" />
<UInput v-maska="'###'" placeholder="CVC" />
</div>
</div>
</template>

View File

@@ -77,7 +77,7 @@ const text = computed(() => {
v-for="(req, index) in strength"
:key="index"
class="flex items-center gap-0.5"
:class="req.met ? 'text-(--ui-success)' : 'text-(--ui-text-muted)'"
:class="req.met ? 'text-success' : 'text-muted'"
>
<UIcon :name="req.met ? 'i-lucide-circle-check' : 'i-lucide-circle-x'" class="size-4 shrink-0" />

View File

@@ -10,8 +10,8 @@ const open = ref(false)
<Placeholder class="h-48" />
</template>
<template #footer>
<UButton label="Cancel" color="neutral" variant="outline" @click="open = false" />
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<UButton label="Submit" color="neutral" />
</template>
</UModal>

View File

@@ -13,7 +13,9 @@ const modal = overlay.create(LazyModalExample, {
})
async function open() {
const shouldIncrement = await modal.open()
const instance = modal.open()
const shouldIncrement = await instance.result
if (shouldIncrement) {
count.value++

View File

@@ -65,6 +65,7 @@ const items = [
class="w-full justify-center"
:ui="{
viewport: 'sm:w-(--reka-navigation-menu-viewport-width)',
content: 'sm:w-auto',
childList: 'sm:w-96',
childLinkDescription: 'text-balance line-clamp-2'
}"
@@ -76,11 +77,11 @@ const items = [
</li>
<li v-for="child in item.children" :key="child.label">
<ULink class="text-sm text-left rounded-md p-3 transition-colors hover:bg-(--ui-bg-elevated)/50">
<p class="font-medium text-(--ui-text-highlighted)">
<ULink class="text-sm text-left rounded-md p-3 transition-colors hover:bg-elevated/50">
<p class="font-medium text-highlighted">
{{ child.label }}
</p>
<p class="text-(--ui-text-muted) line-clamp-2">
<p class="text-muted line-clamp-2">
{{ child.description }}
</p>
</ULink>

View File

@@ -0,0 +1,19 @@
<script lang="ts" setup>
const open = ref(false)
</script>
<template>
<UPopover
v-model:open="open"
:dismissible="false"
:ui="{ content: 'w-(--reka-popper-anchor-width) p-4' }"
>
<template #anchor>
<UInput placeholder="Focus to open" @focus="open = true" @blur="open = false" />
</template>
<template #content>
<Placeholder class="w-full aspect-square" />
</template>
</UPopover>
</template>

View File

@@ -8,7 +8,7 @@ const open = ref(false)
<template #content>
<div class="flex items-center gap-4 mb-4">
<h2 class="text-(--ui-text-highlighted) font-semibold">
<h2 class="text-highlighted font-semibold">
Popover non-dismissible
</h2>

View File

@@ -36,7 +36,7 @@ const { data: users, status } = await useFetch('https://jsonplaceholder.typicode
<template #item-label="{ item }">
{{ item.label }}
<span class="text-(--ui-text-muted)">
<span class="text-muted">
{{ item.email }}
</span>
</template>

View File

@@ -1,11 +1,11 @@
<script setup lang="ts">
import { refDebounced } from '@vueuse/core'
import type { AvatarProps } from '@nuxt/ui'
const searchTerm = ref('')
const searchTermDebounced = refDebounced(searchTerm, 200)
const { data: users, status } = await useFetch('https://jsonplaceholder.typicode.com/users', {
key: 'typicode-users',
params: { q: searchTermDebounced },
transform: (data: { id: number, name: string }[]) => {
return data?.map(user => ({

View File

@@ -10,8 +10,8 @@ const open = ref(false)
<Placeholder class="h-full" />
</template>
<template #footer>
<UButton label="Cancel" color="neutral" variant="outline" @click="open = false" />
<template #footer="{ close }">
<UButton label="Cancel" color="neutral" variant="outline" @click="close" />
<UButton label="Submit" color="neutral" />
</template>
</USlideover>

View File

@@ -13,7 +13,9 @@ const slideover = overlay.create(LazySlideoverExample, {
})
async function open() {
const shouldIncrement = await slideover.open()
const instance = slideover.open()
const shouldIncrement = await instance.result
if (shouldIncrement) {
count.value++

View File

@@ -100,7 +100,7 @@ const columnFilters = ref([{
<template>
<div class="flex flex-col flex-1 w-full">
<div class="flex px-4 py-3.5 border-b border-(--ui-border-accented)">
<div class="flex px-4 py-3.5 border-b border-accented">
<UInput
:model-value="(table?.tableApi?.getColumn('email')?.getFilterValue() as string)"
class="max-w-sm"

View File

@@ -131,7 +131,7 @@ function getHeader(column: Column<Payment>, label: string) {
'variant': 'ghost',
label,
'icon': isSorted ? (isSorted === 'asc' ? 'i-lucide-arrow-up-narrow-wide' : 'i-lucide-arrow-down-wide-narrow') : 'i-lucide-arrow-up-down',
'class': '-mx-2.5 data-[state=open]:bg-(--ui-bg-elevated)',
'class': '-mx-2.5 data-[state=open]:bg-elevated',
'aria-label': `Sort by ${isSorted === 'asc' ? 'descending' : 'ascending'}`
}))
}

View File

@@ -100,7 +100,7 @@ const columnVisibility = ref({
<template>
<div class="flex flex-col flex-1 w-full">
<div class="flex justify-end px-4 py-3.5 border-b border-(--ui-border-accented)">
<div class="flex justify-end px-4 py-3.5 border-b border-accented">
<UDropdownMenu
:items="table?.tableApi?.getAllColumns().filter(column => column.getCanHide()).map(column => ({
label: upperFirst(column.id),

View File

@@ -0,0 +1,82 @@
<script setup lang="ts">
import type { TableColumn } from '@nuxt/ui'
import { useSortable } from '@vueuse/integrations/useSortable.mjs'
type Payment = {
id: string
date: string
email: string
amount: number
}
const data = ref<Payment[]>([{
id: '4600',
date: '2024-03-11T15:30:00',
email: 'james.anderson@example.com',
amount: 594
}, {
id: '4599',
date: '2024-03-11T10:10:00',
email: 'mia.white@example.com',
amount: 276
}, {
id: '4598',
date: '2024-03-11T08:50:00',
email: 'william.brown@example.com',
amount: 315
}, {
id: '4597',
date: '2024-03-10T19:45:00',
email: 'emma.davis@example.com',
amount: 529
}])
const columns: TableColumn<Payment>[] = [{
accessorKey: 'id',
header: '#',
cell: ({ row }) => `#${row.getValue('id')}`
}, {
accessorKey: 'date',
header: 'Date',
cell: ({ row }) => {
return new Date(row.getValue('date')).toLocaleString('en-US', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
})
}
}, {
accessorKey: 'email',
header: 'Email'
}, {
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
}
}]
useSortable('.my-table-tbody', data, {
animation: 150
})
</script>
<template>
<div class="w-full">
<UTable
ref="table"
:data="data"
:columns="columns"
:ui="{
tbody: 'my-table-tbody'
}"
/>
</div>
</template>

View File

@@ -2,6 +2,7 @@
import { h, resolveComponent } from 'vue'
import { upperFirst } from 'scule'
import type { TableColumn } from '@nuxt/ui'
import { useClipboard } from '@vueuse/core'
const UButton = resolveComponent('UButton')
const UCheckbox = resolveComponent('UCheckbox')
@@ -9,6 +10,7 @@ const UBadge = resolveComponent('UBadge')
const UDropdownMenu = resolveComponent('UDropdownMenu')
const toast = useToast()
const { copy } = useClipboard()
type Payment = {
id: string
@@ -220,7 +222,7 @@ const columns: TableColumn<Payment>[] = [{
}, {
label: 'Copy payment ID',
onSelect() {
navigator.clipboard.writeText(row.original.id)
copy(row.original.id)
toast.add({
title: 'Payment ID copied to clipboard!',
@@ -265,7 +267,7 @@ function randomize() {
</script>
<template>
<div class="flex-1 divide-y divide-(--ui-border-accented) w-full">
<div class="flex-1 divide-y divide-accented w-full">
<div class="flex items-center gap-2 px-4 py-3.5 overflow-x-auto">
<UInput
:model-value="(table?.tableApi?.getColumn('email')?.getFilterValue() as string)"
@@ -313,7 +315,7 @@ function randomize() {
</template>
</UTable>
<div class="px-4 py-3.5 text-sm text-(--ui-text-muted)">
<div class="px-4 py-3.5 text-sm text-muted">
{{ table?.tableApi?.getFilteredSelectedRowModel().rows.length || 0 }} of
{{ table?.tableApi?.getFilteredRowModel().rows.length || 0 }} row(s) selected.
</div>

View File

@@ -36,7 +36,7 @@ const columns: TableColumn<User>[] = [{
size: 'lg'
}),
h('div', undefined, [
h('p', { class: 'font-medium text-(--ui-text-highlighted)' }, row.original.name),
h('p', { class: 'font-medium text-highlighted' }, row.original.name),
h('p', { class: '' }, `@${row.original.username}`)
])
])

View File

@@ -95,7 +95,7 @@ const globalFilter = ref('45')
<template>
<div class="flex flex-col flex-1 w-full">
<div class="flex px-4 py-3.5 border-b border-(--ui-border-accented)">
<div class="flex px-4 py-3.5 border-b border-accented">
<UInput
v-model="globalFilter"
class="max-w-sm"

View File

@@ -0,0 +1,203 @@
<script setup lang="ts">
import { h, resolveComponent } from 'vue'
import type { TableColumn } from '@nuxt/ui'
import { getGroupedRowModel, type GroupingOptions } from '@tanstack/vue-table'
const UBadge = resolveComponent('UBadge')
type Account = {
id: string
name: string
}
type PaymentStatus = 'paid' | 'failed' | 'refunded'
type Payment = {
id: string
date: string
status: PaymentStatus
email: string
amount: number
account: Account
}
const getColorByStatus = (status: PaymentStatus) => {
return {
paid: 'success',
failed: 'error',
refunded: 'neutral'
}[status]
}
const data = ref<Payment[]>([
{
id: '4600',
date: '2024-03-11T15:30:00',
status: 'paid',
email: 'james.anderson@example.com',
amount: 594,
account: {
id: '1',
name: 'Account 1'
}
},
{
id: '4599',
date: '2024-03-11T10:10:00',
status: 'failed',
email: 'mia.white@example.com',
amount: 276,
account: {
id: '2',
name: 'Account 2'
}
},
{
id: '4598',
date: '2024-03-11T08:50:00',
status: 'refunded',
email: 'william.brown@example.com',
amount: 315,
account: {
id: '1',
name: 'Account 1'
}
},
{
id: '4597',
date: '2024-03-10T19:45:00',
status: 'paid',
email: 'emma.davis@example.com',
amount: 529,
account: {
id: '2',
name: 'Account 2'
}
},
{
id: '4596',
date: '2024-03-10T15:55:00',
status: 'paid',
email: 'ethan.harris@example.com',
amount: 639,
account: {
id: '1',
name: 'Account 1'
}
}
])
const columns: TableColumn<Payment>[] = [
{
id: 'title',
header: 'Item'
},
{
id: 'account_id',
accessorKey: 'account.id'
},
{
accessorKey: 'id',
header: '#',
cell: ({ row }) =>
row.getIsGrouped()
? `${row.getValue('id')} records`
: `#${row.getValue('id')}`,
aggregationFn: 'count'
},
{
accessorKey: 'date',
header: 'Date',
cell: ({ row }) => {
return new Date(row.getValue('date')).toLocaleString('en-US', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
hour12: false
})
},
aggregationFn: 'max'
},
{
accessorKey: 'status',
header: 'Status'
},
{
accessorKey: 'email',
header: 'Email',
meta: {
class: {
td: 'w-full'
}
},
cell: ({ row }) =>
row.getIsGrouped()
? `${row.getValue('email')} customers`
: row.getValue('email'),
aggregationFn: 'uniqueCount'
},
{
accessorKey: 'amount',
header: () => h('div', { class: 'text-right' }, 'Amount'),
cell: ({ row }) => {
const amount = Number.parseFloat(row.getValue('amount'))
const formatted = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'EUR'
}).format(amount)
return h('div', { class: 'text-right font-medium' }, formatted)
},
aggregationFn: 'sum'
}
]
const grouping_options = ref<GroupingOptions>({
groupedColumnMode: 'remove',
getGroupedRowModel: getGroupedRowModel()
})
</script>
<template>
<UTable
:data="data"
:columns="columns"
:grouping="['account_id', 'status']"
:grouping-options="grouping_options"
:ui="{
root: 'min-w-full',
td: 'empty:p-0' // helps with the colspaned row added for expand slot
}"
>
<template #title-cell="{ row }">
<div v-if="row.getIsGrouped()" class="flex items-center">
<span
class="inline-block"
:style="{ width: `calc(${row.depth} * 1rem)` }"
/>
<UButton
variant="outline"
color="neutral"
class="mr-2"
size="xs"
:icon="row.getIsExpanded() ? 'i-lucide-minus' : 'i-lucide-plus'"
@click="row.toggleExpanded()"
/>
<strong v-if="row.groupingColumnId === 'account_id'">{{
row.original.account.name
}}</strong>
<UBadge
v-else-if="row.groupingColumnId === 'status'"
:color="getColorByStatus(row.original.status)"
class="capitalize"
variant="subtle"
>
{{ row.original.status }}
</UBadge>
</div>
</template>
</UTable>
</template>

View File

@@ -0,0 +1,88 @@
<script setup lang="ts">
import type { TableColumn } from '@nuxt/ui'
import { useInfiniteScroll } from '@vueuse/core'
const UAvatar = resolveComponent('UAvatar')
type User = {
id: number
firstName: string
username: string
email: string
image: string
}
type UserResponse = {
users: User[]
total: number
skip: number
limit: number
}
const skip = ref(0)
const { data, status, execute } = await useFetch('https://dummyjson.com/users?limit=10&select=firstName,username,email,image', {
key: 'table-users-infinite-scroll',
params: { skip },
transform: (data?: UserResponse) => {
return data?.users
},
lazy: true,
immediate: false
})
const columns: TableColumn<User>[] = [{
accessorKey: 'id',
header: 'ID'
}, {
accessorKey: 'image',
header: 'Avatar',
cell: ({ row }) => h(UAvatar, { src: row.original.image })
}, {
accessorKey: 'firstName',
header: 'First name'
}, {
accessorKey: 'email',
header: 'Email'
}, {
accessorKey: 'username',
header: 'Username'
}]
const users = ref<User[]>([])
watch(data, () => {
users.value = [
...users.value,
...(data.value || [])
]
})
execute()
const table = useTemplateRef<ComponentPublicInstance>('table')
onMounted(() => {
useInfiniteScroll(table.value?.$el, () => {
skip.value += 10
}, {
distance: 200,
canLoadMore: () => {
return status.value !== 'pending'
}
})
})
</script>
<template>
<div class="w-full">
<UTable
ref="table"
:data="users"
:columns="columns"
:loading="status === 'pending'"
sticky
class="flex-1 h-80"
/>
</div>
</template>

View File

@@ -162,7 +162,7 @@ const pagination = ref({
class="flex-1"
/>
<div class="flex justify-center border-t border-(--ui-border) pt-4">
<div class="flex justify-center border-t border-default pt-4">
<UPagination
:default-page="(table?.tableApi?.getState().pagination.pageIndex || 0) + 1"
:items-per-page="table?.tableApi?.getState().pagination.pageSize"

View File

@@ -2,12 +2,14 @@
import { h, resolveComponent } from 'vue'
import type { TableColumn } from '@nuxt/ui'
import type { Row } from '@tanstack/vue-table'
import { useClipboard } from '@vueuse/core'
const UButton = resolveComponent('UButton')
const UBadge = resolveComponent('UBadge')
const UDropdownMenu = resolveComponent('UDropdownMenu')
const toast = useToast()
const { copy } = useClipboard()
type Payment = {
id: string
@@ -119,7 +121,7 @@ function getRowItems(row: Row<Payment>) {
}, {
label: 'Copy payment ID',
onSelect() {
navigator.clipboard.writeText(row.original.id)
copy(row.original.id)
toast.add({
title: 'Payment ID copied to clipboard!',

View File

@@ -112,7 +112,7 @@ const expanded = ref({ 1: true })
v-model:expanded="expanded"
:data="data"
:columns="columns"
:ui="{ tr: 'data-[expanded=true]:bg-(--ui-bg-elevated)/50' }"
:ui="{ tr: 'data-[expanded=true]:bg-elevated/50' }"
class="flex-1"
>
<template #expanded="{ row }">

View File

@@ -122,7 +122,7 @@ function onSelect(row: TableRow<Payment>, e?: Event) {
@select="onSelect"
/>
<div class="px-4 py-3.5 border-t border-[var(--ui-border-accented)] text-sm text-[var(--ui-text-muted)]">
<div class="px-4 py-3.5 border-t border-accented text-sm text-muted">
{{ table?.tableApi?.getFilteredSelectedRowModel().rows.length || 0 }} of
{{ table?.tableApi?.getFilteredRowModel().rows.length || 0 }} row(s) selected.
</div>

View File

@@ -113,7 +113,7 @@ const rowSelection = ref({ 1: true })
:columns="columns"
/>
<div class="px-4 py-3.5 border-t border-(--ui-border-accented) text-sm text-(--ui-text-muted)">
<div class="px-4 py-3.5 border-t border-accented text-sm text-muted">
{{ table?.tableApi?.getFilteredSelectedRowModel().rows.length || 0 }} of
{{ table?.tableApi?.getFilteredRowModel().rows.length || 0 }} row(s) selected.
</div>

View File

@@ -1,5 +1,6 @@
<script setup lang="ts">
import type { TableColumn, DropdownMenuItem } from '@nuxt/ui'
import { useClipboard } from '@vueuse/core'
interface User {
id: number
@@ -10,6 +11,7 @@ interface User {
}
const toast = useToast()
const { copy } = useClipboard()
const data = ref<User[]>([{
id: 1,
@@ -71,7 +73,8 @@ function getDropdownActions(user: User): DropdownMenuItem[][] {
label: 'Copy user Id',
icon: 'i-lucide-copy',
onSelect: () => {
navigator.clipboard.writeText(user.id.toString())
copy(user.id.toString())
toast.add({
title: 'User ID copied to clipboard!',
color: 'success',
@@ -97,7 +100,7 @@ function getDropdownActions(user: User): DropdownMenuItem[][] {
<div class="flex items-center gap-3">
<UAvatar :src="`https://i.pravatar.cc/120?img=${row.original.id}`" size="lg" :alt="`${row.original.name} avatar`" />
<div>
<p class="font-medium text-(--ui-text-highlighted)">
<p class="font-medium text-highlighted">
{{ row.original.name }}
</p>
<p>

View File

@@ -26,9 +26,9 @@ const state = reactive({
</script>
<template>
<UTabs :items="items" variant="link" class="gap-4 w-full" :ui="{ trigger: 'flex-1' }">
<UTabs :items="items" variant="link" class="gap-4 w-full" :ui="{ trigger: 'grow' }">
<template #account="{ item }">
<p class="text-(--ui-text-muted) mb-4">
<p class="text-muted mb-4">
{{ item.description }}
</p>
@@ -45,7 +45,7 @@ const state = reactive({
</template>
<template #password="{ item }">
<p class="text-(--ui-text-muted) mb-4">
<p class="text-muted mb-4">
{{ item.description }}
</p>

View File

@@ -1,22 +1,32 @@
<script setup lang="ts">
import type { TabsItem } from '@nuxt/ui'
const route = useRoute()
const router = useRouter()
const items: TabsItem[] = [
{
label: 'Account'
label: 'Account',
value: 'account'
},
{
label: 'Password'
label: 'Password',
value: 'password'
}
]
const active = ref('0')
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
setInterval(() => {
active.value = String((Number(active.value) + 1) % items.length)
}, 2000)
const active = computed({
get() {
return (route.query.tab as string) || 'account'
},
set(tab) {
// Hash is specified here to prevent the page from scrolling to the top
router.push({
path: '/components/tabs',
query: { tab },
hash: '#control-active-item'
})
}
})
</script>

View File

@@ -0,0 +1,34 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: TimelineItem[] = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
icon: 'i-lucide-code',
value: 'development'
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
icon: 'i-lucide-check-circle',
value: 'deployment'
}]
</script>
<template>
<UTimeline
:items="items"
:ui="{ item: 'even:flex-row-reverse even:-translate-x-[calc(100%-2rem)] even:text-right' }"
:default-value="2"
class="translate-x-[calc(50%-1rem)]"
/>
</template>

View File

@@ -0,0 +1,52 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
subtitle: 'Project Initiation',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide-code',
value: 'development',
slot: 'development' as const,
developers: [
{
src: 'https://github.com/J-Michalek.png'
}, {
src: 'https://github.com/benjamincanac.png'
}
]
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide-check-circle',
value: 'deployment'
}] satisfies TimelineItem[]
</script>
<template>
<UTimeline :items="items" :default-value="2" class="w-96">
<template #development-title="{ item }">
<div class="flex items-center gap-1">
<span>{{ item.title }}</span>
<UAvatarGroup size="2xs">
<UAvatar v-for="(developer, index) of item.developers" :key="index" v-bind="developer" />
</UAvatarGroup>
</div>
</template>
</UTimeline>
</template>

View File

@@ -0,0 +1,42 @@
<script setup lang="ts">
import type { TimelineItem } from '@nuxt/ui'
const items: TimelineItem[] = [{
date: 'Mar 15, 2025',
title: 'Project Kickoff',
description: 'Kicked off the project with team alignment. Set up project milestones and allocated resources.',
icon: 'i-lucide-rocket',
value: 'kickoff'
}, {
date: 'Mar 22, 2025',
title: 'Design Phase',
description: 'User research and design workshops. Created wireframes and prototypes for user testing.',
icon: 'i-lucide-palette',
value: 'design'
}, {
date: 'Mar 29, 2025',
title: 'Development Sprint',
description: 'Frontend and backend development. Implemented core features and integrated with APIs.',
icon: 'i-lucide-code',
value: 'development'
}, {
date: 'Apr 5, 2025',
title: 'Testing & Deployment',
description: 'QA testing and performance optimization. Deployed the application to production.',
icon: 'i-lucide-check-circle',
value: 'deployment'
}]
const active = ref(0)
// Note: This is for demonstration purposes only. Don't do this at home.
onMounted(() => {
setInterval(() => {
active.value = (active.value + 1) % items.length
}, 2000)
})
</script>
<template>
<UTimeline v-model="active" :items="items" class="w-96" />
</template>

View File

@@ -0,0 +1,60 @@
<script lang="ts" setup>
import type { TimelineItem } from '@nuxt/ui'
import { useTimeAgo } from '@vueuse/core'
const items = [{
username: 'J-Michalek',
date: '2025-05-24T14:58:55Z',
action: 'opened this',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
}, {
username: 'J-Michalek',
date: '2025-05-26T19:30:14+02:00',
action: 'marked this pull request as ready for review',
icon: 'i-lucide-check-circle'
}, {
username: 'benjamincanac',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description: 'I\'ve made a few changes, let me know what you think! Basically I updated the design, removed unnecessary divs, used Avatar component for the indicator since it supports icon already.',
avatar: {
src: 'https://github.com/benjamincanac.png'
}
}, {
username: 'J-Michalek',
date: '2025-05-27T11:01:20Z',
action: 'commented on this',
description: 'Looks great! Good job on cleaning it up.',
avatar: {
src: 'https://github.com/J-Michalek.png'
}
}, {
username: 'benjamincanac',
date: '2025-05-27T11:01:20Z',
action: 'merged this',
icon: 'i-lucide-git-merge'
}] satisfies TimelineItem[]
</script>
<template>
<UTimeline
:items="items"
size="xs"
class="w-96"
:ui="{
date: 'float-end ms-1',
description: 'px-3 py-2 ring ring-default mt-2 rounded-md text-default'
}"
>
<template #title="{ item }">
<span>{{ item.username }}</span>
<span class="font-normal text-muted">&nbsp;{{ item.action }}</span>
</template>
<template #date="{ item }">
{{ useTimeAgo(new Date(item.date)) }}
</template>
</UTimeline>
</template>

View File

@@ -7,10 +7,10 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.duration"
size="sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -18,7 +18,7 @@ const appConfig = useAppConfig()
v-model="appConfig.toaster.duration"
color="neutral"
variant="soft"
:ui="{ base: 'rounded-(--ui-radius) rounded-l-none min-w-12' }"
:ui="{ base: 'rounded-sm rounded-l-none min-w-12' }"
/>
</UFormField>
</div>

View File

@@ -7,10 +7,10 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.expand"
size="sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -19,7 +19,7 @@ const appConfig = useAppConfig()
:items="[true, false]"
color="neutral"
variant="soft"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
class="rounded-sm rounded-l-none min-w-12"
:search-input="false"
/>
</UFormField>

View File

@@ -10,10 +10,10 @@ const appConfig = useAppConfig()
<UFormField
label="toaster.position"
size="sm"
class="inline-flex ring ring-(--ui-border-accented) rounded-(--ui-radius)"
class="inline-flex ring ring-accented rounded-sm"
:ui="{
wrapper: 'bg-(--ui-bg-elevated)/50 rounded-l-(--ui-radius) flex border-r border-(--ui-border-accented)',
label: 'text-(--ui-text-muted) px-2 py-1.5',
wrapper: 'bg-elevated/50 rounded-l-sm flex border-r border-accented',
label: 'text-muted px-2 py-1.5',
container: 'mt-0'
}"
>
@@ -22,7 +22,7 @@ const appConfig = useAppConfig()
:items="positions"
color="neutral"
variant="soft"
class="rounded-(--ui-radius) rounded-l-none min-w-12"
class="rounded-sm rounded-l-none min-w-12"
:search-input="false"
/>
</UFormField>

View File

@@ -20,7 +20,7 @@ const { width } = useElementSize(el)
<template>
<div
class="isolate rounded-full relative circle w-full aspect-[1/1] p-8 sm:p-12 md:p-14 lg:p-10 xl:p-16 before:absolute before:inset-px before:bg-(--ui-bg) before:rounded-full z-(--level)"
class="isolate rounded-full relative circle w-full aspect-[1/1] p-8 sm:p-12 md:p-14 lg:p-10 xl:p-16 before:absolute before:inset-px before:bg-default before:rounded-full z-(--level)"
:class="{ 'animation-paused': paused }"
:style="{
'--duration': `${((level + 1) * 8)}s`,
@@ -65,7 +65,7 @@ const { width } = useElementSize(el)
:src="`https://ipx.nuxt.com/s_56x56/gh_avatar/${contributor.username}`"
:srcset="`https://ipx.nuxt.com/s_112x112/gh_avatar/${contributor.username} 2x`"
:alt="contributor.username"
class="ring-2 ring-(--ui-border) lg:hover:ring-(--ui-border-inverted) transition rounded-full size-7"
class="ring-2 ring-default lg:hover:ring-inverted transition rounded-full size-7"
loading="lazy"
>
</NuxtLink>

View File

@@ -69,7 +69,7 @@ function setBlackAsPrimary(value: boolean) {
:variant="open ? 'soft' : 'ghost'"
square
aria-label="Color picker"
:ui="{ leadingIcon: 'text-(--ui-primary)' }"
:ui="{ leadingIcon: 'text-primary' }"
/>
</template>

View File

@@ -18,8 +18,8 @@ const slots = defineSlots<{
variant="outline"
:icon="icon"
:label="label"
class="capitalize ring-(--ui-border) rounded-[calc(var(--ui-radius))] text-[11px]"
:class="[selected ? 'bg-(--ui-bg-elevated)' : 'hover:bg-(--ui-bg-elevated)/50']"
class="capitalize ring-default rounded-sm text-[11px]"
:class="[selected ? 'bg-elevated' : 'hover:bg-elevated/50']"
>
<template v-if="chip || !!slots.leading" #leading>
<slot name="leading">

View File

@@ -0,0 +1,54 @@
import { onMounted, watch } from 'vue'
import FaviconSvg from 'public/icon.svg?raw'
export function useFaviconFromTheme() {
const colorMode = useColorMode()
function generateFaviconSvg(color: string) {
const parser = new DOMParser()
const doc = parser.parseFromString(FaviconSvg, 'image/svg+xml')
const svg = doc.documentElement
svg.querySelectorAll('path').forEach((path) => {
path.setAttribute('fill', color)
})
return new XMLSerializer().serializeToString(svg)
}
function updateFavicon() {
const root = document.documentElement
const color = getComputedStyle(root).getPropertyValue('--ui-primary').trim() || '#00DC82'
const svg = generateFaviconSvg(color)
const encoded = `data:image/svg+xml,${encodeURIComponent(svg)}`
useFavicon(encoded)
}
function setupMutationObserver() {
const styleTag = document.getElementById('nuxt-ui-colors')
if (!styleTag) return
const observer = new MutationObserver(() => {
updateFavicon()
})
observer.observe(styleTag, {
characterData: true,
subtree: true,
childList: true
})
}
onMounted(() => {
watch(colorMode, () => {
updateFavicon()
}, {
immediate: true,
flush: 'post'
})
setupMutationObserver()
})
}

View File

@@ -98,7 +98,7 @@ export function useLinks() {
label: 'Raycast Extension',
description: 'Access Nuxt UI components without leaving your editor.',
icon: 'i-simple-icons-raycast',
to: 'https://www.raycast.com/HugoRCD/nuxt-ui',
to: 'https://www.raycast.com/HugoRCD/nuxt',
target: '_blank'
}, {
label: 'Figma to Code',

View File

@@ -26,7 +26,7 @@ useHead({
{ key: 'theme-color', name: 'theme-color', content: color }
],
link: [
{ rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
// { rel: 'icon', type: 'image/svg+xml', href: '/icon.svg' }
],
style: [
{ innerHTML: radius, id: 'nuxt-ui-radius', tagPriority: -2 },
@@ -47,6 +47,8 @@ useServerSeoMeta({
twitterCard: 'summary_large_image'
})
useFaviconFromTheme()
const { frameworks, modules } = useSharedData()
const { mappedNavigation, filteredNavigation } = useContentNavigation(navigation)
@@ -57,7 +59,7 @@ provide('navigation', mappedNavigation)
<UApp>
<NuxtLoadingIndicator color="#FFF" />
<Banner />
<!-- <Banner /> -->
<Header :links="links" />

View File

@@ -22,7 +22,7 @@ const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
<span class="inline-flex items-center gap-0.5">
{{ link.title }}
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-(--ui-primary)">PRO</sup>
<sup v-if="link.module === 'ui-pro'" class="text-[8px] font-medium text-primary">PRO</sup>
</span>
</template>
</UContentNavigation>

Some files were not shown because too many files have changed in this diff Show More