Skip to content

v0.1.2

Latest

Choose a tag to compare

@cixzhang cixzhang released this 29 Jun 22:38
6c533c7

@astryxdesign/core

Breaking Changes

  • Text, Heading, Link, and Timestamp rename the color="active" value to color="accent", now mapping to the dedicated --color-text-accent token (legible accent text ink) instead of --color-accent. Run astryx upgrade to migrate call sites automatically. (#2863)

New Features

  • Button: add isInterruptible to keep the button clickable while a clickAction is pending — the spinner and aria-busy still show, but the button is not disabled or deduped, so a re-click interrupts the in-flight action. ToggleButton's async toggle now runs through this path, staying interruptible.
  • Add a prebuilt UMD bundle (dist/astryx.umd.js, global Astryx) plus unpkg/jsdelivr fields, so the library works directly from a CDN via a <script> tag with no bundler. React/ReactDOM stay as peer globals; the StyleX runtime is bundled in.
  • Add useTableStickyColumns — pin a contiguous run of Table columns to
    the start and/or end edge with cumulative offsets and scroll-aware drop shadows.
    Configure with { startKeys, endKeys }; an empty config is a valid no-op.

Fixes

  • AvatarGroupOverflow now forwards rest props (data-, aria-, event handlers, id, role, tabIndex) to the rendered element, matching the behavior of Avatar and AvatarGroup.
  • Fix HoverCard SSR hydration mismatch when used inside an SSR Client Component (#3107). The floating layer now renders inline instead of portaling to document.body, so server and client markup match. No API change.
  • Kbd: use the --color-border-emphasized token for its bottom border instead of --color-border (#2850)
  • useLayer now treats anchor-name as a comma-separated list, so multiple layers can anchor to the same element (e.g. two TopNavMegaMenus in one nav) without clobbering each other's anchor. Previously the second menu lost its anchor and rendered over the nav.
  • Fix mobile nav drawer not re-opening after it is closed (#3091)
    The AppShell mobile drawer mounts MobileNav inside an <Activity> that
    switches to mode="hidden" when the drawer closes. On close, React runs the
    drawer effect's cleanup (with a stale isOpen) instead of re-running the
    effect with isOpen=false, so the deferred dialog.close() never fired and
    the native <dialog> was left open in the hidden subtree. The next open then
    skipped showModal() (the dialog was already open), so the drawer could be
    opened and closed once but never re-opened. The effect cleanup now closes the
    dialog if it is still open, keeping the native dialog state in sync so a
    subsequent open cleanly calls showModal() again.
  • Core components (Banner, EmptyState, Markdown) no longer render a <p> by default — they render <div> (appearance unchanged). This avoids hydration mismatches when block content lands in a <p>. Markdown paragraphs use role="paragraph"; pass components={{paragraph: 'p'}} to opt back into <p>.
  • Pagination's changeAction is now interruptible — page changes run in a transition with optimistic page state, so rapid prev/next clicks advance through pages instead of being dropped. Button's clickAction keeps its single-fire guard.
  • make the Slider default track color visible on muted backgrounds
    The background track painted with --color-background-muted — the same token
    used for muted surface fills — so the track disappeared on muted backgrounds.
    The track now uses the dedicated --color-track channel token, which is
    designed to stay legible against body/muted surfaces.
  • Polish useTableStickyColumns pinned-cell backgrounds so they match the
    rest of the row:
  • Table: the header row no longer picks up the hasHover row highlight — hover (and striped) styling now applies to body rows only. Adds an internal isHeaderRow flag on the row component so the header row in <thead> opts out (#2734)
  • Timestamp now renders the current time (and small clock skew up to ~30s in the future) as "now" instead of "in a few seconds" (#3099).
  • ToggleButton onPressedChange receives the click event for preventDefault opt-out
    onPressedChange now receives the originating click event as a second
    argument. Calling event.preventDefault() skips pressedChangeAction, so a
    consumer can handle the toggle entirely in onPressedChange without firing the
    action — matching how Switch's onChange and Button's onClick already
    gate their action props. Existing (isPressed) => void handlers keep working;
    the event is an added trailing argument.
  • Tokenizer/PowerSearch: align end content (clear button, resultCount) with the field's inline padding instead of hugging the border (~3px). It now uses spacing-2 (8px) to match the text/start-icon inset (#2849)
  • Tooltip and HoverCard: add ARIA roles to the floating layers — role="tooltip" on Tooltip (completing the ARIA tooltip pattern; the trigger already links via aria-describedby) and role="dialog" on HoverCard. Plumbed via a new optional role on the layer render props. (#3240; Popover already exposes role="dialog".)

Documentation

  • Document Banner's defaultIsExpanded prop, which controls whether the collapsible content area starts expanded but was missing from the docsite properties tab
  • Rename the ClickableCard and SelectableCard examples to follow the "Component — Variant" title convention (Clickable Card — Nested Button, Selectable Card — Multi-select), and add playground defaults to both card docs so their docsite previews show realistic card content (#2877)
  • Declare playground scaffolds for the Chat sub-components so they preview at a realistic width (ChatComposer and ChatComposerDrawer wrap in a sized container, and the drawer seeds default content), and drop the redundant visible value label from the ChatComposerDrawer "With Progress" example while keeping the accessible label (#2877)
  • Document two public props missing from the docsite properties tab: List's start (ordered-list counter start) and CheckboxInput's isReadOnly
  • Restore the Icon and Skeleton properties-tab previews on the docsite. Icon now seeds a default icon (it was a required, non-generatable prop), and Skeleton renders with concrete preview dimensions instead of collapsing at 100% (#2848, #2875)
  • Document Heading's justify prop, which was supported by the component but missing from the docsite properties tab (#2847)
  • OverflowList: seed example items via playground defaults so the docsite properties-tab preview renders a real list instead of an empty container (#2872)
  • Document Section's paddingBlock prop (block-axis padding override), which was supported by the component but missing from the docsite properties tab
  • Give the Skeleton properties-tab example explicit dimensions so it is visible
    The Skeleton doc had no playground config, so the interactive
    properties-tab preview fell back to the prop defaults of width: '100%' /
    height: '100%'. With no sized parent, the skeleton collapsed to a zero-size
    (invisible) element. The doc now sets a playground.defaults of
    width: 320 / height: 80 so the shimmer placeholder renders visibly.
  • Update stale facebookexperimental/xds doc/JSDoc links to the current facebook/astryx namespace in source comments (theme/syntax @see references). The old org 301-redirects, so these weren't broken — just stale — and this matches the canonical org used elsewhere
  • Document Table's verticalAlign and textOverflow props, which were supported by the component but missing from the docsite properties tab
  • Document TabList's layout prop ('hug' | 'fill') for tab sizing, which was supported by the component but missing from the docsite properties tab
  • Document Text's justify prop, which was supported by the component but missing from the docsite properties tab (same omission previously fixed for Heading) (#2847-adjacent)
  • Restore the Timestamp properties-tab preview on the docsite. value is a required prop with no semantic default, so the preview rendered "Invalid time value"; it now seeds a valid ISO 8601 date (#2877)
  • Document ToggleButton's isIconOnly prop, which was a supported public prop but missing from the docsite properties tab
  • Make the Toolbar "Table Filter" example use real Selector controls for its Status and Priority filters instead of buttons styled to look like dropdowns, and add meaningful playground defaults plus richer slot options (buttons, icon buttons, tabs, segmented controls, selectors) to the Toolbar docs (#2877).

Other Changes

  • Pinned cells paint an opaque base via the overridable
    --table-sticky-background variable (defaults to --color-background-card),
    fixing a grey mismatch in themes/modes where surface !== card (e.g. neutral
    dark). Consumers on a different backdrop override the variable.
  • The row's overlay (striping and/or hover) is replayed on the pinned cell via
    a background-image gradient. TableRow publishes its current overlay color as
    the inheritable --table-row-overlay variable, so pinned columns mirror the
    row exactly — striped when the table is striped, hover when enabled, nothing
    otherwise (no phantom stripes) — transitioning in lockstep with the row.
  • background-clip: padding-box keeps the row divider visible on pinned cells.
  • New transformScrollWrapper hook (+ ScrollWrapperRenderProps) lets plugins attach a ref
    to the horizontal scroll container and inject before/after chrome.
  • transformHeaderCell / transformBodyCell now receive columnIndex and the
    full ordered columns list (also surfaced on the render props), enabling
    position-aware plugins such as sticky columns. Existing plugins are unaffected
    — the new args and methods are additive and optional.

@astryxdesign/cli

Breaking Changes

  • Text, Heading, Link, and Timestamp rename the color="active" value to color="accent", now mapping to the dedicated --color-text-accent token (legible accent text ink) instead of --color-accent. Run astryx upgrade to migrate call sites automatically. (#2863)

New Features

  • Let astryx.config.mjs integrations contribute package docs, gap-report hooks, template fetching hooks, upgrade codemods, and post-codemod hooks.
  • Add astryx theme add <slug> [path] (and astryx theme list) to scaffold a theme's source into your project as editable files you own, with theme sources bundled into the CLI

Fixes

  • align astryx init theme instructions with the runtime built-theme recommendation (#3080)
    astryx init now points users at the pre-built theme path (@astryxdesign/theme-neutral/built + theme.css) and the base CSS imports, matching the runtime <Theme> console guidance, instead of the slower runtime style-injection import that left apps unstyled.
  • astryx theme build now derives every output file (.css/.js/.d.ts) from the theme name so they share one naming scheme, shows import paths as bare ./<name> specifiers (instead of a cwd-rooted ./src/... path that was wrong when your file already lives under src/), and no longer warns about the variant prop on card

Documentation

  • Rename the ClickableCard and SelectableCard examples to follow the "Component — Variant" title convention (Clickable Card — Nested Button, Selectable Card — Multi-select), and add playground defaults to both card docs so their docsite previews show realistic card content (#2877)
  • Declare playground scaffolds for the Chat sub-components so they preview at a realistic width (ChatComposer and ChatComposerDrawer wrap in a sized container, and the drawer seeds default content), and drop the redundant visible value label from the ChatComposerDrawer "With Progress" example while keeping the accessible label (#2877)
  • Rename the DateInput "Date Range" example to "Min/Max Constraints" — it demos a single input constrained to a min/max window, not a date-range picker (#2692)
  • Wire local state into more showcase examples that were frozen (static value + no-op onChange): TextInput, TextArea, NumberInput, SegmentedControl, RadioList, Tab, TabList, and TabMenu. Follows the same fix as the Slider/Selector/MultiSelector showcases so the docsite previews are actually interactive
  • Wire local state into the Typeahead, Tokenizer, and FileInput showcase examples (static value + no-op onChange → frozen previews). Completes the interactive-showcase fixes started for Slider/Selector/MultiSelector (#3187-#3189) and the input/tab batch
  • Wire local state into the Slider, Selector, and MultiSelector showcase examples so they are interactive — they were controlled components with a static value and a no-op/missing onChange, so the docsite previews appeared frozen (#3187, #3188, #3189)
  • Add a LinkProvider example block showing how to swap in a framework router link (e.g. Next.js Link) for client-side routing (#2733)
  • Add a showcase block for Outline so its docs page has a hero preview, alongside the existing example blocks (#2871)
  • Remove the "MoreMenu — In Toolbar" example block — it rendered incorrectly and was redundant with the other MoreMenu examples (#2870)
  • Add rendered example blocks for the two column-axis Table plugin hooks,
    shown on their own subcomponent pages:
  • Move the "ToggleButton — Group" example to the ToggleButtonGroup page, where it belongs (it demonstrates grouped toggle behavior) (#2842)
  • Make the Toolbar "Table Filter" example use real Selector controls for its Status and Priority filters instead of buttons styled to look like dropdowns, and add meaningful playground defaults plus richer slot options (buttons, icon buttons, tabs, segmented controls, selectors) to the Toolbar docs (#2877).

Other Changes

  • useTableStickyColumns — Pinned Columns (on /components/useTableStickyColumns)
  • useTableColumnResize — Draggable Columns (on /components/useTableColumnResize)

@astryxdesign/build

Fixes

  • ship TypeScript declarations for the @astryxdesign/build/vite export

Contributors

@benjipeng @cixzhang @durvesh1992 @ejhammond @ernesttien @humbertovirtudes @rubyycheung

Full Changelog: v0.1.1...v0.1.2