Repository navigation
Releases: cattr-app/ui-kit
Release list
v2.1.0
New features
- AtSkeleton — animated loading placeholders with configurable dimensions, count, circular shapes, and theme variables. Automatically displays a placeholder when its default slot is empty.
- AtAvatar — user pictures with initials as a fallback, configurable colors and sizes, custom initials generation, and accessible names through alt.
- AtSelect: remote search and pagination.
- remote and remote-method(query, { signal }) for server-side search with configurable debounce (300 ms by default).
- AbortSignal support for cancelling superseded requests.
- on-load-more for pagination triggered by scrolling, keyboard navigation, or a page that does not fill the dropdown.
- Loading indicators through loading and loading-text, plus on-remote-error for search failures.
- fallback-label and cached labels for selected values whose options are not currently loaded.
- empty and footer slots, also available outside remote mode.
- Search queries and results remain available after a selection in remote multiple mode.
- Added Select loading translations for all six bundled locales.
- Added English and Chinese documentation and demos for the new components and remote Select.
Testing
- Added Playwright browser tests covering documentation pages, component interactions, and visual regressions.
- Added unit tests for Skeleton, Avatar, and remote Select, including request cancellation, error handling, keyboard navigation, clearing, dropdown positioning, and pagination.
Upgrading from 2.0.1
No breaking API changes or required migration steps.
The new components provide migration paths from vue-loading-skeleton and vue-avatar. Remote Select supports server-side search and pagination scenarios previously handled with vue-select. Replacing these dependencies requires changes in the consuming application.
v2.0.1
Bug-fix release: no public API changes. Every fix ships with a regression test. Details in CHANGELOG.md.
Patches
Table
- Sorting with
paginationonly sorted the current page; the whole data set is sorted and then paginated. The active sort is kept acrossdatachanges,normalrestores the original order, and a column's initialsortTypeno longer sticks forever. - A
datachange showed page 1 while the pager still highlighted the old page; the current page is kept while it exists, otherwise page 1. columnsandpageSizeprop changes are followed (header rebuilt, rows re-sliced); the pager uses the same page size as the body.- The selection column (
optional) gets its own<col>, so column widths no longer shift one column to the left; resize measurement skips the selection cell. - Sorting a column clears the arrow of the previously sorted column.
CheckboxGroup — a v-model bound to null crashed the render; a non-array value is treated as an empty selection.
Message, Notification — closing in the same tick as opening (e.g. Message('x')() or an immediate closeAll()) left a hidden element in document.body forever.
CollapseTransition (Collapse, inline Submenu) — re-opening while still closing saved the zeroed padding/overflow as the element's own styles and restored them permanently.
Rate — with allow-half, a null v-model threw on render and on mouseleave; an integer initial value rendered half a star less.
InputNumber — readonly is honoured by the +/- buttons and ArrowUp/ArrowDown; decimal steps no longer produce float artifacts (0.14 + 0.01 → 0.15).
Slider — values were rounded to integers; fractional step/min/max now work (values snap to the min + k·step grid and stay within [min, max]).
Select — a disabled clearable select no longer shows a working clear icon; the filter input is disabled with the select; a numeric label of 0 renders as 0; keys typed into another field while the dropdown is open are no longer captured (the dropdown closes).
Menu — with router, each click navigated twice, replace was ignored and a disabled item with to still navigated; router mode without vue-router threw. The item navigates once, honouring replace/disabled. With inline-collapsed, clicking a nested submenu title no longer closes its ancestor.
Steps, Timeline, Collapse, Submenu — children re-ordered by a keyed v-for kept stale indexes; parents re-sort on update.
useChildren — children deactivated by <keep-alive> are unregistered (and re-added on activate); sort() only orders nodes sharing a root, so it is idempotent.
Progress — a status change without a percent change had no effect.
Modal, $Modal — a throwing user callback left the promise pending forever (settled first, error reported); Dialog() without options threw; an AtModal mounted already open with showInput did not focus the input; Escape closed every open modal at once — now only the topmost one (if it has close-on-press-esc="false", Escape does not reach the modal underneath).
Popover, Tooltip, Dropdown — trigger="focus" did not react to inner inputs (now focusin/focusout); a trigger prop change after mount is applied.
Pagination — current is clamped when total/pageSize shrink (emits update:current and page-change); the page inputs no longer block Tab, Delete, Home/End and Ctrl/Cmd shortcuts.
Docs — select.md: update:modelValue carries the plain value even with valueWithLabel; only on-change carries { value, label }.
Tooling — repository field in the object form; pnpm 12.15.0.
v2.0.0
The library has been migrated from Vue 2 / webpack 3 to Vue 3.5 and Vite 8. Backward compatibility with 1.x is not preserved; the full migration guide with a step-by-step checklist and ready-made grep commands is in CHANGELOG.md.
Breaking changes
Environment and packaging
- Peer dependency
vue ^3.5; Node ≥ 24 to build. Vue 2 is no longer supported. - ESM-only package with an
exportsmap. UMD buildsdist/at.js/dist/at.min.jsand the globalatare removed. - Locales moved to
@amazingcat/cattr-ui/locale/<lang>(ESM) fromdist/locale/<lang>.js(UMD). - Internal
at-ui/src/...imports are gone; theat-uibundler alias is no longer needed. - The
at-ui-styleworkspace package is renamed tocattr-ui-style(private). Theme customization via$var: …; @importno longer works — use@use '@amazingcat/cattr-ui/src/stylesheet/src/index.scss' with (…).
Installation API
Vue.use(CattrUI, opts)→createApp(App).use(CattrUI, opts). Auto-registration throughwindow.Vueis removed.- Components are exported under
At*names (AtButton,AtSelect, …); the default export is{ install, version }only. Services are available asapp.config.globalProperties.$Message/$Modal/$Notify/$Loadingand as named exportsMessage,Dialog,Notification,LoadingBar. - i18n hook:
app.use(CattrUI, { i18n: (key, values) => … }); the implicitVue.locale/$tprototype detection is removed.
Template API
v-modelon every component now usesmodelValue/update:modelValue(Input, InputNumber, Textarea, Checkbox, CheckboxGroup, Radio, RadioGroup, RadioButton, Select, Switch, Slider, Rate, Modal, Tabs, Collapse, Dropdown, Tooltip, Popover). Manual:value+@inputbindings must become:model-value+@update:model-value.- The
.nativemodifier is gone:@click.native→@click. Button no longer emits its ownclick; consumer listeners fall through to the native<button>. - Input and InputNumber use
inheritAttrs: false:class/stylestay on the wrapper, all other attributes and listeners (@keyup.enter,id,aria-*,data-*) go to the native<input>.@inputon these components is now the native event, not the component's. - Slot syntax
slot="name"→<template #name>(#menuon Dropdown,#titleon Submenu,#header/#footeron Modal,#title/#contenton Popover,#title/#extra/#loadingon Card). - Table column
rendersignature:render: (h, params)→render: ({ item, column, index })withhimported fromvueand Vue 3 VNode format.indexis now the row index (it was the column index due to a shadowed variable). - Select no longer inherits the popover mixin: props
title,content,headerand thetoggleevent are removed;placementsupportstop*/bottom*only. - Event semantics:
on-changeon Select, Rate, Tabs, Textarea andradio-group-changeon RadioGroup fire only on user interaction, not on programmatic value changes. Menuon-selectfires once per click (was once per nesting level). Modal OK emits a singleon-confirm(it used to emiton-cancelafterwards too). - Services:
$Notify(...)returns a close function instead of a component instance. Services must be called afterapp.use(CattrUI)(or afterapp.use(<Service>)).$Modalstatus dialogs default to English titles (Info,Success,Warning,Error). - Removed:
AtForm,AtFormItem(never exported in 1.x) and theirdispatch('AtFormItem', …)plumbing in Input/InputNumber/Textarea. - Styles: Vue 3 transition classes (
-enter-from/-leave-frominstead of-enter/-leave) for custom animations; the grid no longer overrides the global$screen-*variables after import ($screen-sm-maxis 767px, not 991px).
Minor changes
- Prebuilt CSS in the package:
@amazingcat/cattr-ui/style.css,style.min.cssand fonts underdist/css/fonts; Sass is only needed for custom themes. - Styles compile with
sass-embedded; SCSS sources migrated to Sass modules (@use/@forward), theme variables are overridable through@use … with (…), no Dart Sass deprecation warnings. - Named
At*exports enable tree-shaking and per-componentapp.use(AtButton). - Pagination emits
update:currentandupdate:pageSize, enablingv-model:current/v-model:page-size. - Tabs, Collapse and Dropdown now have a two-way
v-model(in 1.x they never emittedinput). - Notification gains
closeAll(); the close functions returned by$Message(...)and$Notify(...)expose.id;close(id)now hides the item and calls itsonClose. $Modal: dialogs are queued and shown one after another;callbackand the returned promise work together; Escape, the close icon and the mask resolve as'cancel';closeOnPressEscis honoured; new propsshowCancelButton,showConfirmButton,inputValue,inputPlaceholder, new eventafter-leave.- Services can be installed standalone (
app.use(Dialog)): Modal registers its own Button/Input dependencies. - Button/ButtonGroup, Radio/RadioGroup, Checkbox/CheckboxGroup, Tabs, Steps, Timeline, Collapse, Menu, Select, Breadcrumb and Dropdown use provide/inject: children work at any depth and react to parent prop changes.
- Keyboard handling uses
event.key(Select, Pagination, Modal); Pagination accepts numpad digits. - LoadingBar:
config({ width })applies to the visible bar;destroy()added. - Documentation site on Vite + vue-router 5 + vue-i18n 11, deployed to GitHub Pages; CI workflow with lint (
--max-warnings 0), Prettier, Vitest with coverage thresholds and a PR coverage comment. - Tooling: ESLint 10 flat config, eslint-plugin-vue 10, Prettier 3, Vitest 5 — 42 spec files, 222 tests.
Patches
- Message:
closeAll()closed only every other message;close(id)removed the message from the stack without hiding it; a message opened fromonClosewas shifted above the viewport. - Notification: same
close/stacking fixes; customiconnow works withouttype. - Modal/Dialog: the dialog queue never worked (every call opened a new dialog); promises hung when the dialog was closed by Escape, the close icon or the mask;
close()in the same tick asalert()/confirm()still showed the dialog; thekeydownlistener was never removed (beforeDestorytypo). - Table: row selection checkbox toggled the wrong row after sorting or on later pages; the "select all" checkbox in fixed-height mode toggled twice per click; the
resizelistener was never removed (beforeDestorytypo);rendercell received the column index instead of the row index. - Tabs: closing an active unnamed pane selected a pane that no longer existed after removal; closing a pane before an active unnamed pane broke the selection;
on-changefired on mount and on programmatic changes. - Select: keyboard navigation only scrolled the list downwards; scroll-into-view depended on
offsetParent; clearing a filterable select left the stale filter applied; thekeydownlistener was never removed. - Collapse: in-place mutations of the bound array (
push,splice) did not update the panes. - InputNumber: external
modelValuechanges were ignored; typed values were discarded;changefired twice per click; emits atmin/maxboundaries preserved. - Rate:
on-changefired twice per click; Textarea: emitted on external value changes. - Popover/Tooltip: not positioned when opened through
v-modelor mounted withmodelValue: true; mixin listeners are now removed on unmount. - Pagination: the upper clamp of the page number was dead code (quickjump accepted
999); root HTML comments made the component a fragment and dropped consumer attributes. - LoadingBar:
start()right afterfinish()/error()was cancelled by the previous hide timer;height: 4px !importantignoredconfig({ width }). - Timeline: the
pendingclass was not removed whenpendingturned off. Steps/Collapse: first render no longer flashes withindex = -1. - Breadcrumb:
separatoris reactive and the first render is no longer empty; clicking without a router no longer throws. - Slider: track width is measured on each event (stale cached width on resize); handle moves immediately on drag.