Skip to content

Releases: Mini-Sylar/vael-ui

vael-ui@0.2.5

Choose a tag to compare

@github-actions github-actions released this 11 Aug 23:05
ba00ce3

Patch Changes

  • #28 0f41be0 Thanks @Mini-Sylar! - Fixes an external class passed to a component (e.g. <Message class="my-class">) silently replacing the component's own internal styling classes instead of merging with them, under vael-ui/vapor. 36 components (Accordion, Card, Checkbox, DataTable, Tag, Toolbar, and others) now explicitly merge fallthrough attrs instead of relying on Vapor's implicit fallthrough, which doesn't reliably merge class on a component that already binds its own.

    Components whose root wraps content in <Transition> (Dialog, Popover, Message, Tooltip, and others) are not covered by this fix — that's a separate, upstream Vue 3.6 Vapor limitation in how <Transition> itself handles fallthrough attrs, tracked separately.

    Also bumps the vue dependency to 3.6.0-rc.3, which fixes AnimatePresence/<Transition> deferring exit removal through a <Teleport> nested inside a component (e.g. a force-mounted Dialog) — the imperative beforeClose fallback is no longer required for that case, though it remains supported.

vael-ui@0.2.4

Choose a tag to compare

@github-actions github-actions released this 11 Aug 00:00
c49a8fa

Patch Changes

  • #26 32a8b7b Thanks @Mini-Sylar! - Fixes inconsistent internal spacing in Dialog, Card, Tour, and confirmAction's popover surface, where the gap on one side of a header/body/footer-style transition was silently double-counted against the other, making the two sides unequal (e.g. Dialog's body→footer gap was exactly double its header→body gap). Also fixes Tour rendering with doubled outer padding — its own header/actions padding was stacking on top of Popover's shared body padding.

vael-ui@0.2.3

Choose a tag to compare

@github-actions github-actions released this 10 Aug 22:14
be2f047

Patch Changes

  • #24 0a7d018 Thanks @Mini-Sylar! - Fixes vael-ui/vapor shipping with no CSS at all — the vapor build's generator was stripping every component's CSS import under the (incorrect) assumption a consumer would already have styles loaded some other way. It now copies each component's CSS alongside its generated source and keeps the import, the same way the main build already does.

    packages/vapor-ui's build also moved from Vite library mode to tsdown, matching the main package's build exactly, so vapor gets the same real per-component CSS code-splitting — importing a single component only downloads that component's CSS, whether via vael-ui/vapor or the vapor export condition added in 0.2.1.

vael-ui@0.2.2

Choose a tag to compare

@github-actions github-actions released this 10 Aug 20:40
16a6b8f

Patch Changes

  • c33d874 Thanks @Mini-Sylar! - Fixes a build failure (CIRCULAR_REEXPORT, MISSING_EXPORT) in vael-ui/vapor for any consumer using the vapor export condition added in 0.2.1 — several composable/utility re-exports were pure passthroughs that resolved back to themselves once vael-ui's root pointed at the same file. They now import from their real source files directly instead of through the package specifier.

    Also fixes confirmAction, which was excluded from the Vapor build in 0.2.1 (it rendered the real VDOM Button component internally) — it now composes real Vapor-compiled components, so it's available from vael-ui/vapor like every other composable.

vael-ui@0.2.1

Choose a tag to compare

@github-actions github-actions released this 10 Aug 19:14
ac4b5f2

Patch Changes

  • #21 a78a3a9 Thanks @Mini-Sylar! - vael-ui/vapor now also re-exports composables and utilities, not just components. This also enables a vapor export condition on the package root — set it in your bundler and tsconfig.json to use vael-ui everywhere with no /vapor subpath needed. See the Auto Import guide for setup; see the 0.2.0 release notes for the original Vapor/resolver docs.

vael-ui@0.2.0

Choose a tag to compare

@github-actions github-actions released this 10 Aug 07:55
b248bb2

Minor Changes

  • #17 35d6fe3 Thanks @Mini-Sylar! - Per-component CSS code-splitting, six new components (including Tour), large-data support for DataTable, a vael-ui/resolver for auto-importing components plus a vael-ui/nuxt module, container-scoped overlays, real link rows for MenuList/Menu, and broader generics across the item-based components.

    Per-component CSS code-splitting

    Every component now ships and imports its own CSS file instead of one bundled style.css.

    • Importing a component only pulls in the styles it actually uses — bundlers that tree-shake unused component imports drop their CSS along with them.
    • import 'vael-ui/style.css' still works unchanged (now resolving to a multi-entry build's combined output), for anyone who wants everything loaded up front or is on a pre-0.2.0 workflow. No import changes required either way.
    • Shared design tokens live in their own components/shared/tokens.css, pulled in once regardless of which components you use.

    New components

    • ScrollArea — custom scrollbar styling and edge fade over real native scrolling (orientation: 'vertical' | 'horizontal' | 'both')
    • AvatarGroup — overlapping avatar stack with a "+N" overflow indicator and optional hover-lift
    • Breadcrumb / BreadcrumbItem / BreadcrumbSeparator — data-driven items, or compose the parts yourself. Each item's as/attrs renders it as a plain link, a RouterLink, or anything else your router provides
    • Stepper — linear or free-jump numbered step flow, horizontal or vertical
    • CommandPalette — ⌘K-style fuzzy-filtered command list, built on Dialog
    • Tour + useTour() — step-by-step spotlight walkthrough with grouped steps, a headless composable for a fully custom UI, and the same container-scoping and animation-agnostic contract as the rest of the overlay components

    DataTable: built for large data

    Server-driven sort/pagination, virtualization, and infinite-scroll wiring — designed to compose with useInfiniteQuery-style patterns rather than replicate them.

    • manualSortdata is already sorted server-side; DataTable stops sorting it locally and just reflects v-model:sort, so a header click tells you what to refetch instead of re-sorting what you gave it.
    • lazy + totaldata is already just the current page; DataTable stops slicing it locally and uses total (the real across-all-pages count) for #footer/pagination math.
    • virtualize — windows rendering to only the visible rows + overscan, for tables with tens of thousands of rows. Row height is measured per-row by default (rows can wrap, or vary under stackedBreakpoint), not assumed uniform.
    • reach-end/reach-start events fire as the virtualized window nears either edge — wire them straight to useInfiniteQuery's fetchNextPage/fetchPreviousPage.
    • v-model:sort — sort state ({ field, dir }) is now a real two-way binding instead of purely internal.
    • scrollHeight tables now split the header into its own non-scrolling row above a separately scrollable body, so the browser's scrollbar starts at the body instead of overlapping the header.
    • selectionMode="row" now shows a pointer cursor on every row, matching the click-to-select affordance.

    vael-ui/resolver: auto-import components

    A resolver for unplugin-vue-components — register it once and every vael-ui component becomes usable in a template with no manual import at all:

    // vite.config.ts
    import Components from "unplugin-vue-components/vite";
    import { VaelUiResolver } from "vael-ui/resolver";
    
    export default {
      plugins: [Components({ resolvers: [VaelUiResolver()] })],
    };

    Pass { variant: 'vapor' } to resolve from vael-ui/vapor instead of the default VDOM build. No CSS side-effect wiring needed — every component already imports its own CSS internally, so resolving the component pulls its styles in for free. Zero dependency on unplugin-vue-components itself; the resolver is a plain, hand-typed function that structurally matches its contract.

    vael-ui/nuxt: a Nuxt module

    Same idea as the resolver, for Nuxt apps — register the module once and every component is usable with no manual import, using Nuxt's own built-in component registration instead of unplugin-vue-components:

    // nuxt.config.ts
    export default defineNuxtConfig({
      modules: ["vael-ui/nuxt"],
    });

    exclude: ['Button'] skips specific component names, e.g. to register your own <Button> under that tag instead. VDOM only, no variant option — Vue 3.6 supports Vapor SSR hydration, but the stable Nuxt release has no Vapor configuration yet (it's landing behind specific upstream PRs). Verified against a real Nuxt app: SSR markup, client hydration, and CSS all confirmed working in both nuxt dev and a production nuxt build.

    Container-scoped overlays

    Dialog, Drawer, CommandPalette, Popover, and Tour all gained a container prop that scopes the overlay to one element instead of the whole viewport — the scrim only dims that element, the panel teleports there instead of body, and scroll-lock/inert apply only inside it, leaving the rest of the page interactive. Useful for embedding a live overlay demo (a dashboard preview, a docs example) without it taking over the whole screen.

    BottomSheet doesn't support container yet — its drag mechanics still assume the full viewport.

    New composables back this:

    • useScrollLock — ref-counted, per-element locks so nested overlays compose correctly
    • useInert — scopes inertness to a container instead of the whole document
    • useLayerStack additions — scope Escape-key/layer ownership to an element

    Original contained/scoped Dialog implementation from @arkida39 (#16), extended here to Drawer, CommandPalette, Popover, and Tour.

    MenuList/Menu rows can now be real links

    A row's as/attrs (default 'button', so nothing existing changes) renders it as <a> or RouterLink instead — native cmd/ctrl/middle-click and "open in new tab" work, which a <button>-only row never could. A row with nested items (a submenu trigger) always stays a button.

    Broader generics

    SelectButton, SpeedDial, Tour (and useTour), Tree, TreeSelect, and CascadeSelect join Select, Combobox, DataTable, Menu, MenuList, CommandPalette, Breadcrumb, and Stepper in being generic over their item type (T extends XItem = XItem) — extend an item with your own fields and get them back fully typed through slots and events instead of casting.

    Deeply nested items (a Tree node's children, a Menu row's nested items) stay base-typed — same documented limitation as before.

    Fixes

    • Page-wide scroll locks now consistently target document.body (Tour was still locking documentElement directly)
    • BottomSheet content is scrollable at any drag/snap position instead of only once mostly open, and a nested sheet's parent now un-recedes in sync with the child's own close animation instead of waiting for it to fully finish
    • Dialog's teleportTo now correctly wins over container when both are set
    • v-scroll-mask accepts orientation: 'x' | 'y' | 'both' (previously vertical-only, so binding it on a horizontally-scrolling row was a silent no-op), and its edge fade is more visible
    • Message's dismiss button hit target is larger

vael-ui@0.1.6

Choose a tag to compare

@github-actions github-actions released this 02 Aug 13:03
7308da5

Patch Changes

  • 6f27012 Thanks @Mini-Sylar! - Breaking: replace confirmDialog() and useConfirmAction() (added in the previous release) with a single confirmAction(). The old pair required either hand-rolling your own overlay wiring (useConfirmAction) or being locked into a centered Dialog (confirmDialog); confirmAction() picks its presentation with a discriminated union on surface, 'dialog' (default, centered) or 'popover' (anchored to a triggerEl, required in that branch). Both branches pass every other prop straight through to the underlying Dialog/Popover (position, size, side, align, closeOnOutside, ui, etc.), so per-call customization (a taller dialog, a wider popover) needs no new API surface. onConfirm is awaited before closing: the confirm button stays in its loading state until it settles, closing only on success; a rejection leaves the surface open and fires onError instead of closing out from under a failed action. useConfirmAction and confirmDialog are removed with no compatibility shim, since the API was flagged unstable in the release that introduced it.

    Add usePopoverService (openPopover, usePopoverRef, usePopoverQueue) and PopoverHost, the anchored-surface counterpart to the existing useDialogService/DialogHost. openPopover(Component, options) mounts any component inside a Popover anchored to options.triggerEl, returning { result, close, panelEl } the same shape openDialog returns — result settles with whatever the opened component's usePopoverRef().close(result) passes. confirmAction({ surface: 'popover' }) is built on this primitive; reach for openPopover directly for anything beyond a plain confirm (a custom form in a popover, for example). Requires mounting <PopoverHost/> once at the app root, alongside <DialogHost/>.

    Fix confirm-flow popovers being permanently stuck invisible (visibility: hidden, positioning never computed). The shared useFloatingPosition composable only recomputes on a false-to-true transition of its active flag, not on an initial truthy value; an imperatively-opened popover's open state starts true before the surface even mounts, so the transition never happened and positioning silently never ran.

vael-ui@0.1.5

Choose a tag to compare

@github-actions github-actions released this 02 Aug 11:06
ebe4a05

Patch Changes

  • 6e9f93b Thanks @Mini-Sylar! - Add confirmDialog() and useConfirmAction() for building async-aware confirm flows (delete confirmations, destructive-action gates) without a dedicated AlertDialog component. useConfirmAction() is presentation-agnostic — bind its open ref to any overlay's own v-model:open (Popover, Dialog, or a fully custom surface), anchored however that overlay already supports (Popover's existing #trigger slot or triggerEl prop, unchanged). confirmDialog() is a thin convenience wrapper over the existing openDialog() service for the common "title + description + Cancel/Confirm" shape, still accepting a custom body/footer component for full control. Both share the same core behavior: confirm(action) keeps the surface open and pending true until action settles, closing only on success — a rejected action clears pending, sets error, and leaves the surface open instead of closing out from under a failed action.

    Fix Dock's pointer-proximity magnification visibly juddering in Safari. The live per-item transform was written every pointermove frame while a CSS transition was still active on that property, so Safari was continuously retargeting an in-flight transition — Chromium mostly masked it, Safari didn't. Replaced with a small requestAnimationFrame spring loop (exponential decay toward each item's target scale/offset) that owns the live tracking entirely; the CSS transition now only ever governs the discrete press-shrink feedback.

    Fix Accordion's motionCss={false} being unable to close. useCollapse's settle logic was forcing the resting style to {} (visually open) whenever motion was disabled, regardless of the target open/closed state — so disabling the built-in transition also silently disabled closing. motionCss={false} now still snaps instantly to the correct open/closed resting style, just without the animated transition.

    Fix Calendar's month-change slide briefly bleeding into the weekday header row — the leaving month's grid was position: absolute against the wrong containing block (the whole calendar body, which the weekday row also shares), landing it on top of the header text for one frame instead of at the grid's own top edge.

    Fix SelectButton's sliding indicator popping in instantly with no transition on the very first selection (starting from nothing selected). The indicator's first-measurement guard was only tracking whether the component had ever measured at all, not whether it had ever shown a real selection — so the first real pick was mistaken for the initial-mount case and had its transition suppressed.

    Fix OtpInput's blinking caret drawing through an already-typed digit instead of only appearing in the next empty cell, and fix a one-frame focus flash on the wrong cell when clicking back into a completed code — the browser's own default caret placement (based on the invisible input's unstyled text metrics) was landing and painting before the click handler's correction ran; both are now resolved before any paint by handling pointerdown with preventDefault() instead of click.

    Fix Toolbar's vertical orientation not being vertically centered when only one of its three internal slot groups (start/center/end) had content — the two empty groups were still full flex participants contributing gap spacing. Toolbar now only renders a slot group when it actually has content.

    Fix Toast alignment (action button text centering, close-icon sizing) and Radio's icon being misaligned with its label text.

    Fix BottomSheet's swipe-to-dismiss being inconsistent on mobile — dragging down past the lowest snap point wasn't always registering as a dismiss gesture.

    Fix Badge's count text rendering visibly offset from center.

vael-ui@0.1.4

Choose a tag to compare

@github-actions github-actions released this 30 Jul 03:17
6d34cf1

Patch Changes

  • 2871350 Thanks @Mini-Sylar! - Fix Combobox, Select, TreeSelect, and DatePicker silently dropping a plain class/style passed by a consumer. Each sets inheritAttrs: false but never forwarded those attrs onto its own visible trigger element (only onto the teleported dropdown panel, where one existed), so <Combobox class="my-class"> (and the same on the other three) never reached the rendered DOM — any consumer relying on ordinary class-based styling (width, layout, display: none in a media query, etc.) had no effect. Audited every other component using inheritAttrs: false; the remaining ones (Popover, Tooltip, Menu, Dialog, Drawer, BottomSheet, ContextMenu) take a consumer-provided trigger via slot and have no component-owned trigger element, so they were unaffected by design, not by accident.

vael-ui@0.1.3

Choose a tag to compare

@github-actions github-actions released this 29 Jul 08:55

Patch Changes

  • d752420 Thanks @Mini-Sylar! - Fix Field's context (disabled, required, invalid, label for wiring, focus/filled tracking) not reaching wrapped controls under Vapor. fieldKey was defined as a fresh Symbol() inside Field.vue itself, so the Vapor build's copy of that file created a second, different Symbol instance than the one useFieldControl (shared, not duplicated) always injected with — the two never matched, so every control wrapped in <Field> silently ignored the wrapper's state under Vapor. fieldKey now lives in its own module that the Vapor build correctly imports instead of redefining.