Skip to content

Releases: lablup/ui-common

v0.2.0-alpha.15

v0.2.0-alpha.15 Pre-release
Pre-release

Choose a tag to compare

@yomybaby yomybaby released this 02 Oct 04:59
9c67581

First published 0.2 prerelease: @lablup/ui-common rebuilt on Astryx 0.6.2, plus the new @lablup/ui-common-cli. Published under the next dist-tag; latest/alpha stay on the 0.1 line.

Breaking for 0.1 consumers. Read CHANGELOG.md — Upgrading from 0.1 and docs/migrating-to-0.2.md, then:

pnpm dlx @lablup/ui-common-cli@next upgrade --from 0.1 --dry-run
pnpm dlx @lablup/ui-common-cli@next upgrade --from 0.1

Highlights:

  • Generated 1:1 mirror of @astryxdesign/core under @lablup/ui-common/*; Lablup brand theme (theme/lablup); Modal/AlertModal replace Astryx dialogs; 30+ components moved in from backend.ai-ui; Form engine and DataGrid.
  • React 19.2 or later and @stylexjs/stylex ^0.19 are required peers. pnpm 10+ consumers need allowBuilds for @astryxdesign/core / @astryxdesign/cli (see README).
  • Every shipped stylesheet declares the cascade layer order, so ui-common's rules rank above Astryx's in any bundle.
  • The CLI is its own package (@lablup/ui-common-cli, bin ui-common), so the library's production install no longer carries the codemod toolchain (196 MB → 31 MB for a library-only app).

Full notes: CHANGELOG.md (0.2.0-alpha.0 – alpha.15). PRs: #53, #54.

v0.1.0-alpha.23

v0.1.0-alpha.23 Pre-release
Pre-release

Choose a tag to compare

@YEONFEEL96 YEONFEEL96 released this 23 Sep 16:40
f5300fd

Added

  • DigitPopIn: renders formatted text one character at a time, each rising into place from a light blur, and replays when the text changes. Screen readers get the plain text; reduced motion gets plain text with no animation.
  • StatCard takes animate="digits". animate also accepts "count"; true is still the count-up.

v0.1.0-alpha.22

v0.1.0-alpha.22 Pre-release
Pre-release

Choose a tag to compare

@inureyes inureyes released this 23 Sep 09:05
b779c9c

Fixed

  • DataTable now preserves declared, restored, and resized column widths in the rendered browser layout.
  • Tables whose columns fit still fill their container, while wider tables keep horizontal overflow inside the existing local scroll region.

v0.1.0-alpha.21

v0.1.0-alpha.21 Pre-release
Pre-release

Choose a tag to compare

@inureyes inureyes released this 23 Sep 08:40
9cfd909

Added

  • DataTable resize handles now support pointer and keyboard input, expose measured widths and finite ARIA ranges, and accept localized accessible labels and value text.
  • Columns can define an optional maximum resize width while fixed columns keep their prior unbounded behavior unless they opt into a maximum.

Fixed

  • Resize pointer cleanup is pointer-specific and safe across cancellation, lost capture, and reentrant release.
  • Resize grips reserve a 32px target and meet the 3:1 non-text contrast floor in the shipped light and dark themes.

v0.1.0-alpha.20

v0.1.0-alpha.20 Pre-release
Pre-release

Choose a tag to compare

@inureyes inureyes released this 22 Sep 10:33
8239ed7

New Features

None.

Improvements

None.

Bug Fixes

  • Applied declared DataTable minimum widths to initial, restored, and resized columns and both header and body cells (#43).
  • Aligned table headers and values consistently by default while preserving explicit physical left, right, and center alignment (#43).
  • Moved Drawer focus after visible opening, preserved focus when close callbacks change, and assigned distinct accessible IDs to coexisting drawers (#43).

CI/CD Improvements

None.

Technical Details

Added regression coverage for table sizing and Drawer focus, dismissal, and accessible identity. Existing component APIs and React peer ranges were preserved.

Dependencies

None.

Breaking Changes

None.

Known Issues

None identified in this release's changed behavior.

v0.1.0-alpha.19

Choose a tag to compare

@inureyes inureyes released this 08 Sep 14:33
59699de

One new component and one accessibility fix.

Added

Select (#37, proposed in #16). A single-select listbox with an optional search filter, icons, descriptions, a disabled-but-visible option state, a field label, and the invalid and aria-describedby props a form needs. The listbox is portalled, so a select near the bottom of a scrolling panel is not clipped by it.

It is here because rule 2 passed, which is the test that usually fails: backend.ai-go and continuum-hub both ship this component with the same option shape and the same core props. The superset came, not the intersection, so a consumer does not have to wrap the package to get the label and the filter back.

Two things changed on the way in. The empty-search line resolved a product locale key and is now noOptionsLabel with an English default. The focus border was painted from the bare accent, which measures 2.61:1 against white in one shipped family, under the 3:1 WCAG 2.2 SC 1.4.11 asks of a focus indicator; it mixes the accent with the text colour now.

Fifteen tests, where both products had none.

Skeleton takes decorative, and styles/base.css gains --token-colorTextDisabled, --token-colorTextPlaceholder and --token-colorPrimaryBgHover.

Fixed

A skeleton placeholder announces itself once, not once per shape (#36). role="status" is an implicit polite live region, and every composite filled its own region with primitives that each carried one: seven regions for a SkeletonCard, ten for a pie SkeletonChart. SkeletonCard, SkeletonRow and SkeletonText also left their container unnamed while forwarding loadingLabel to every decorative child, so the region that should have been announced was anonymous.

Before you upgrade

Nothing breaks. Select is new. The skeleton change alters what a screen reader hears rather than what the DOM looks like, and a consumer that worked around the old behaviour with getAllByRole can go back to a plain getByRole.

Full changelog: v0.1.0-alpha.18...v0.1.0-alpha.19

v0.1.0-alpha.18

Choose a tag to compare

@inureyes inureyes released this 08 Sep 07:16
0da7ee8

One Tooltip fix. No API change.

Fixed

The tooltip is placed in the same commit that opens it (#33). Placement was measured in a frame scheduled after mount, and until that frame ran the content sat in the DOM with visibility: hidden: painted nowhere, out of the accessibility tree, and unfindable by any query that respects that tree.

It measures in a layout effect now, so the position is set before the browser paints and the content is never exposed unplaced.

This surfaced as a flaky consumer test that focused a glossary term and looked for its tooltip. The package's own tests could not catch it: every one of them stubbed requestAnimationFrame to run synchronously, which is exactly the frame in question. The stubs are gone and one test now asserts the tooltip is in the accessibility tree in the same tick it opens.

Before you upgrade

A patch. Nothing renders differently; the tooltip simply reaches its position one frame earlier. If you stub requestAnimationFrame in tests around this component, you no longer need to.

Full changelog: v0.1.0-alpha.17...v0.1.0-alpha.18

v0.1.0-alpha.17

Choose a tag to compare

@inureyes inureyes released this 08 Sep 07:05
2f59850

One new StatCard prop. Nothing renders differently unless you pass it.

Added

labelNode lets a stat label be a node (#31). It renders in place of the label text. label stays required and stays the card's accessible name, because a name derived from a node is whatever text falls out of it rather than something you wrote; pass the same words in both.

A stat label is not always plain text. The case this comes from is a glossary term whose definition appears on hover and focus, which is a node, and which no consumer could put here. The consumer that needed it kept a 339-line copy of this component to change one element, through an entire migration onto this package.

It follows TabItem's labelExtra: the same problem, solved the same way.

Before you upgrade

A minor addition. labelNode defaults to undefined and the label renders exactly as it did in 0.1.0-alpha.16.

Full changelog: v0.1.0-alpha.16...v0.1.0-alpha.17

v0.1.0-alpha.16

Choose a tag to compare

@inureyes inureyes released this 08 Sep 06:48
4c3c90c

One new Tooltip prop. Nothing renders differently unless you pass it.

Added

toggleable makes the trigger a control (#29). With it, the trigger carries role="button" and an aria-expanded that tracks the content, and Enter and Space toggle it. Both keys are prevented from their defaults, since Space scrolls the page and Enter submits an enclosing form.

It is opt-in because a trigger whose content only supplements what is already on screen is not a control and should not announce itself as one. A glossary term is the opposite case: the definition is something a reader summons deliberately, and where there is no hover at all, activation is the only route to it.

Both continuum-hub and backend.ai-go have a glossary Term, both written before this package existed, and both built the same trigger contract around it: tabIndex={0}, role="button", aria-describedby, aria-expanded bound to the open state, Enter and Space toggling, Escape closing. The first of them lost that contract when it moved onto this component, which is what this prop is for.

Before you upgrade

A minor addition. toggleable defaults to false, and with it off the component behaves exactly as 0.1.0-alpha.15 did.

Full changelog: v0.1.0-alpha.15...v0.1.0-alpha.16

v0.1.0-alpha.15

Choose a tag to compare

@inureyes inureyes released this 08 Sep 06:30
7d05a70

Three Tooltip fixes. The component's docblock cites WCAG 2.1 SC 1.4.13; it now satisfies all three parts of that criterion, and it stays with its trigger when the page scrolls.

Fixed

Escape dismisses the tooltip (#26). Nothing did before, so a tooltip opened by hover could only be closed by moving the pointer off the trigger, even when it covered the thing being read. The listener is on the document, because a hover-opened tooltip leaves focus wherever it was.

The pointer can reach the content (#26). Leaving the trigger hid the tooltip at once. The content sits 8px away, so crossing to it put the pointer over the body in between, which closed it before it arrived: anything longer than a glance, or that a reader wanted to select, was unreachable. The hide is now deferred by 120ms, which covers the crossing.

The content takes pointer events (#26). .tooltip__content carried pointer-events: none, which made the previous fix meaningless in a browser: the element was never the target of a pointer event, so arriving on it fired nothing and selecting the text was impossible. Every behaviour test passed with it in place, because jsdom does not implement the property, so a stylesheet guard covers it now.

The tooltip stays anchored to its trigger (#27). Placement was measured once, when the tooltip opened. The content is position: fixed in a portal, so scrolling with the pointer or focus still on the trigger left the tooltip where the trigger had been, describing whatever scrolled into that spot; a resize left it off the edge. It re-measures on scroll and on resize now, listening in the capture phase since a scroll inside a container does not bubble.

All four were found while continuum-hub adopted this component in place of its own glossary tooltip, which handled Escape and tracked scrolling.

Before you upgrade

A patch. No API change, and nothing is laid out differently.

Two behaviours a consumer may notice: leaving the trigger now hides the tooltip 120ms later rather than instantly, and an open tooltip can take a pointer event that previously passed through to whatever sits under it.

Full changelog: v0.1.0-alpha.14...v0.1.0-alpha.15