Skip to content

Releases: primer/react

@primer/react@38.27.0

05 Jun 17:16
d829b12

Choose a tag to compare

Minor Changes

  • #7900 49a546f Thanks @mattcosta7! - PageLayout.Sidebar (and SplitPageLayout.Sidebar): add controlled-width support via currentWidth + onResizeEnd, matching the discriminated-union API already on PageLayout.Pane. The underlying usePaneWidth hook already supported these options; this wires them through the component's prop surface. Existing usage is unchanged — the props are opt-in and the uncontrolled (default or widthStorageKey-backed) behavior is preserved exactly.

  • #7906 adc5299 Thanks @jonrohan! - Text: Add whiteSpace prop to control the CSS white-space property

Patch Changes

  • #7915 f58e448 Thanks @jonrohan! - Dialog: Fix Escape key not closing the dialog on the first keypress when the close button is focused

  • #7908 e9a2254 Thanks @jonrohan! - KeybindingHint: display the Meta key correctly on platforms other than macOS and Windows. The Meta, Alt, and Mod keys are now resolved based on the detected platform: Apple platforms (macOS and iOS) show /, Windows shows Win, and all other platforms show Meta/Alt.

  • #7894 af4541d Thanks @mattcosta7! - ActionList: Replace :has(...) selectors on ActionList.Item, InactiveButtonWrap, and TrailingActionButton with JS-derived data attributes (data-has-trailing-action, data-trailing-action-loading, data-position, data-has-label). Reduces style-recalculation cost on lists that render many items. No visual or behavioral changes.

  • #7899 9659ce7 Thanks @mattcosta7! - TreeView: make rows safer to use with contain: paint / content-visibility: auto and reduce style-recalc cost on hover/focus in large trees. No visual or layout changes; all changes are either invisible at the default rendering or behind an opt-in CSS containment property the consumer sets.

    • The current-item indicator (positioned at left: -8px of the row container) was being clipped when a consumer applied contain: paint to the <li> or when the documented containIntrinsicSize prop on TreeView.Item triggered content-visibility: auto on the row container — including for current items. Both .TreeViewItem and .TreeViewItemContainer now declare overflow-clip-margin: var(--base-size-8), which extends the paint-clip edge by 8px on the side the indicator paints. The property is a no-op when no paint containment is active, so default rendering is byte-identical.
    • Skeleton-row hover suppression no longer relies on :has(.TreeViewItemSkeleton), which forced subtree invalidation on every row. LoadingItem now communicates with the placeholder Item via a module-private context that emits a positive data-loading attribute on the <li>, and the CSS selector targets that directly. No new public prop.
    • Nesting indicator lines no longer use a root-scope :hover/:focus-within descendant selector. Color is driven by an inherited --tree-line-color custom property set on the root <ul>, so a hover or focus change inside the tree updates one property on one element instead of re-matching .TreeViewItemLevelLine selectors against every level line in the tree.
    • Fixed a unitless outline-offset: -2 in the forced-colors focus-ring fallback that browsers were silently dropping (so forced-colors users now actually get a focus indicator on tree items).
    • .TreeViewItemContainer's grid-template-columns now declares the trailingAction column explicitly (auto) so it matches the 5-area grid-template-areas declaration (previously the trailing column was implicit auto).

@primer/react@38.26.0

29 May 20:13
df9fd9b

Choose a tag to compare

Minor Changes

  • #7869 23fba52 Thanks @adierkens! - Slot system consistency improvements:

    • Remove orphan __SLOT__ markers from root components that no parent scans for: ActionMenu (root Menu), UnderlinePanels (root), Autocomplete is unchanged (still used as a FormControl child), PageLayout (root), SegmentedControl (root), RadioGroup (root), CheckboxGroup (root), and Dialog (root). Sub-component markers are intentionally retained so consumers can keep wrapping them.
    • Standardize Symbol(...) descriptions used as slot markers to the Parent.Slot convention: CheckboxOrRadioGroupLabelCheckboxOrRadioGroup.Label, CheckboxOrRadioGroupCaptionCheckboxOrRadioGroup.Caption, CheckboxOrRadioGroupValidationCheckboxOrRadioGroup.Validation, DEPRECATED_TooltipTooltip, and TableDataTable.Table.
    • Migrate PageHeader, NavList.Item, and the internal CheckboxOrRadioGroup to use the useSlots hook instead of hand-rolling React.Children traversal with isSlot. The CheckboxOrRadioGroup migration also removes duplicated work where useSlots was already called but slots were re-extracted by hand immediately after.
    • Export useSlots, isSlot, asSlot, and the WithSlotMarker/FCWithSlotMarker types publicly from @primer/react so downstream consumers can build their own slot-aware compound components.
    • Add asSlot(component, slotSource) helper: a typed utility that copies a __SLOT__ marker from a source slot component onto a wrapper component, replacing the cast-heavy (Wrapper as typeof Wrapper & {__SLOT__?: symbol}).__SLOT__ = Source.__SLOT__ pattern.
    • Add a dev-mode warning in useSlots when a child's displayName matches a slot component's displayName but the child is missing the __SLOT__ marker — a common footgun when wrapping slot components.
  • #7898 da27739 Thanks @francinelucca! - ThemeProvider: Add contextOnly prop to opt out of rendering the wrapping <div> with data-* theme attributes

  • #7886 64dfbd3 Thanks @janmaarten-a11y! - Add Timeline.Actions sub-component for rendering action buttons, links, SHAs, status labels, and similar right-aligned content on a Timeline.Item. Renders as a horizontal flex row pushed to the right edge of the item with gap: 8px between children and min-height matching the badge so contents vertically center against it.

  • #7885 9d2cb53 Thanks @janmaarten-a11y! - Add Timeline.Avatar sub-component for rendering an actor avatar in the left gutter of a Timeline.Item. Accepts any React children and is absolutely positioned so it does not affect badge or body layout. Consumers must reserve roughly 72px of left padding around the Timeline for the avatar to be visible.

Patch Changes

  • #7864 e7205ea Thanks @mattcosta7! - Eliminate nested-update cascades in useFocus, PageLayout.Pane, and
    AnchoredOverlay:

    • useFocus no longer produces a second re-render after focusing; one
      focus() call now results in exactly one render instead of two.
    • PageLayout.Pane (resizable) no longer triggers a forced re-render
      before paint on mount. The CSS variable and ARIA attributes are still
      updated synchronously in the layout effect; the React state sync is
      wrapped in startTransition so it runs in the transition lane rather
      than as part of the layout-effect commit.
    • AnchoredOverlay no longer keeps useAnchoredPosition's scroll
      listeners and ResizeObserver attached while it is closed. After an
      open→close cycle, the first scroll/resize event no longer fires a
      spurious setPosition(undefined) that re-renders the closed overlay.

    Also adds a profiler-based test harness at
    src/utils/testing/profiler.tsx so future regressions can be pinned with
    counter.updateCount and counter.nestedUpdateCount assertions.

  • #7892 4dd08af Thanks @TylerJDev! - AnchoredOverlay: Disable CSS anchor positioning if related CSS rules are not supported

  • #7878 8c468fd Thanks @mattcosta7! - FilteredActionList: Guard against undefined items in the virtualizer's getItemKey callback to prevent a crash when @tanstack/react-virtual invokes it with an index whose item was just removed (e.g. when filtering shrinks the items list).

  • #7893 0eef204 Thanks @mattcosta7! - Button: Replace the icon-only-with-counter :has(...):not(:has(...)) selector with a data-icon-only-counter attribute computed from props. Reduces style-recalculation cost on pages that render many Buttons. No visual or behavioral changes.

  • #7896 673514b Thanks @mattcosta7! - TextInput / TextInputWithTokens / Select / Autocomplete: Replace chained :not([data-leading-visual]), :not([data-trailing-visual]), and :not([data-trailing-action]) attribute negations in TextInputWrapper styles with positive data-no-leading-visual, data-no-trailing-visual, and data-no-trailing-action markers emitted by the wrapper components. Eliminates the 2- and 3-deep :not() chains that previously evaluated against every input on every state change. No visual or behavioral changes.

  • #7876 980e94c Thanks @mattcosta7! - UnderlinePanels: Eliminate the empty-tablist frame on mount and the cascading
    re-render when icons toggle. Tabs and panels are now derived in render
    (previously stored in state synced via useEffect), the list width is kept
    in a ref instead of state, and iconsVisible / loadingCounters flow to
    each tab via context — combined with React.memo(Tab), that makes
    resize-driven icon toggles update only the part of each tab that depends on
    the change, not the whole tablist subtree. Behavior is unchanged.

  • #7874 8cc7e99 Thanks @mattcosta7! - Dev-only effects (the if (__DEV__) { useEffect(...) } pattern with an
    eslint-disable react-hooks/rules-of-hooks comment at every call site) are
    now expressed via a new internal useDevOnlyEffect hook. The lint
    suppression lives in the wrapper, the effect is dropped from production by
    the consumer's process.env.NODE_ENV replacement, and call sites get
    react-hooks/exhaustive-deps lint via additionalEffectHooks. No public
    API changes.

@primer/react@38.25.0

26 May 17:01
bb7a95a

Choose a tag to compare

Minor Changes

  • #7852 5504680 Thanks @liuliu-dev! - Card: Add data-component attributes to Card and its subcomponents (Icon, Image, Heading, Description, Metadata, Menu). Add an as prop ('div' | 'section') so standalone Cards can render as a labelled region landmark; as="section" requires aria-label or aria-labelledby. Card now requires children. Also improves docs and stories.

Patch Changes

@primer/react@38.24.0

20 May 15:52
509f46d

Choose a tag to compare

Minor Changes

  • #7829 228019c Thanks @adierkens! - ActionList: Add ActionList.GroupHeading.TrailingAction for header-level actions on grouped lists. Closes #2043.

    When the primer_react_action_list_group_heading_trailing_action feature flag is enabled, you can place an ActionList.GroupHeading.TrailingAction (a small invisible IconButton) inside ActionList.GroupHeading to render a uniform square action target next to the group's heading. Only supported inside an ActionList with the default list role — using it inside ActionMenu or with role="listbox" will throw.

    <ActionList>
      <ActionList.Group>
        <ActionList.GroupHeading as="h3">
          Custom fields
          <ActionList.GroupHeading.TrailingAction label="New field" icon={PlusIcon} />
        </ActionList.GroupHeading>
        <ActionList.Item>...</ActionList.Item>
      </ActionList.Group>
    </ActionList>
  • #7838 8ddf1b0 Thanks @llastflowers! - Add data-component attributes and associated tests for Hidden, InlineMessage, KeybindingHint, Label, and LabelGroup

  • #7776 d6f61c1 Thanks @llastflowers! - Add data-component attributes for Blankslate, BranchName, Breadcrumbs, ButtonGroup, Checkbox, CheckboxGroup, CircleBadge, ConfirmationDialog, CounterLabel, and Dialog to provide stable selectors.

  • #7816 aef8548 Thanks @iansan5653! - Replace ActionBar overflow calculations with CSS wrapping approach to improve performance and stability

  • #7831 0de97c2 Thanks @liuliu-dev! - Dialog: Support custom width values.

  • #7819 8ed6149 Thanks @llastflowers! - Add data-component attributes for Details, Flash, FormControl (+ update InputValidation to forward from FormControl.Validation), Header, and Heading.

Patch Changes

@primer/styled-react@1.0.8

12 May 14:29
de0186b

Choose a tag to compare

Patch Changes

@primer/react@38.23.0

12 May 14:29
de0186b

Choose a tag to compare

Minor Changes

  • #7817 51a7a28 Thanks @francinelucca! - - ActionList: Expand selectableRoles and listRoleTypes to include treeitem and tree.
    • Export ActionListContainerContext as ActionList.ContainerContext.
    • Export useRovingTabIndex from the public API with additional configuration options (preventScroll and dependencies).

Patch Changes

  • #7805 8f8844e Thanks @TylerJDev! - AnchoredOverlay: Disables CSS anchor positioning if portalContainerName is true. (behind primer_react_css_anchor_positioning feature flag)

  • #7800 ce88bdf Thanks @francinelucca! - chore: add primer_react_styled_react_use_primer_theme_providers feature flag to DefaultFeatureFlags

  • #7802 872bf46 Thanks @TylerJDev! - AnchoredOverlay: Ensure overlay fits within viewport by calculating viewport height + width (behind primer_react_css_anchor_positioning feature flag)

@primer/react@38.22.0

06 May 20:01
1aba004

Choose a tag to compare

Minor Changes

  • #7755 0e868f9 Thanks @francinelucca! - feat: add ActionList, SelectPanel primitives exports and new FilteredActionList.Input components

Patch Changes

  • #7797 3e05935 Thanks @liuliu-dev! - Breadcrumbs overflow menu no longer appears when there are only two crumb items.

  • #7511 eb73dee Thanks @RSoeborg! - Fix NavList parent item flicker during static-to-interactive transitions when navigating between current sub-items in a SubNav.

  • #7619 68aaf61 Thanks @hectahertz! - Memoize ActionMenu context values to prevent unnecessary re-renders of menu items

  • #7708 d0fa0ff Thanks @hectahertz! - perf(css): audit :has() selectors and add stylelint guard for Safari

  • #7775 4b7e4ca Thanks @TylerJDev! - AnchoredOverlay: Ensure styles persist on anchors even when re-mounted (behind feature flag)

  • #7780 8330aad Thanks @francinelucca! - fix: Checkbox indeterminate state now persists on click if the state didn't change

@primer/react@38.21.1

28 Apr 17:39
a543de6

Choose a tag to compare

Patch Changes

  • #7770 619175c Thanks @LisaKr! - Defer useAnchoredPosition initial mount setState from useLayoutEffect to useEffect when overlay is closed, eliminating unnecessary cascading re-renders that block paint.

@primer/react@38.21.0

27 Apr 17:38
a217832

Choose a tag to compare

Minor Changes

  • #7760 b2e0efd Thanks @siddharthkp! - Deprecate the useResponsiveValue hook.

  • #7724 d813099 Thanks @francinelucca! - Add stable data-component selectors to multiple components following ADR-023:

    • ActionBar
    • ActionList and friends
    • Button
    • FilteredActionList and friends
    • Link
    • LinkButton
    • Pagination
    • SelectPanel and friends
    • Table and friends
    • TextInput
    • TextInputWithTokens
    • TooltipV2

    This enables consumers to query and test components using stable selectors like [data-component="Table.Row"].

  • #7766 b3f06f1 Thanks @TylerJDev! - AnchoredOverlay: (Behind feature flag) Make popover API usage opt-in

  • #7763 b288d6e Thanks @liuliu-dev! - Add borderRadius prop to Card component.

Patch Changes

  • #7714 e974d9f Thanks @hectahertz! - perf(ActionList): replace :has() selector with JS-computed attribute

  • #7754 9e3fe4b Thanks @liuliu-dev! - Breadcrumbs: On narrow viewports, only show the current page breadcrumb and the overflow menu when overflow="menu" is set.

  • #7757 ed82a1e Thanks @liuliu-dev! - SelectPanel: Lock body scroll when modal variant is on.

  • #7734 421ebf0 Thanks @llastflowers! - add data-component attributes for Avatar, AvatarStack, Banner, & BaseStyles

@primer/styled-react@1.0.6

15 Apr 14:33
aeffb84

Choose a tag to compare

Patch Changes