Skip to content

Update Admin Section types and add Number and EmptyState types - #4666

Merged
kyledurand merged 7 commits into
2026-10-rcfrom
kd/section-header-slots-definitions
Sep 3, 2026
Merged

Update Admin Section types and add Number and EmptyState types#4666
kyledurand merged 7 commits into
2026-10-rcfrom
kd/section-header-slots-definitions

Conversation

@kyledurand

@kyledurand kyledurand commented Sep 1, 2026

Copy link
Copy Markdown
Member

What

Regenerates the Admin Section type definitions from admin-ui-components 2.21.2, picking up the header work that has landed in Polaris since these types were last generated (1.25.0), and adds the missing Number and EmptyState definitions from the same generator run.

Section

New API surface for s-section:

Addition Kind Notes
subheading property Supporting text under the heading. Not a heading: no document-outline entry, doesn't shift child heading levels, not announced as part of the heading.
primaryAction slot Main call-to-action.
secondaryActions slot Alternative/supporting actions. A ButtonGroup holding an action plus an icon-only Menu activator renders as one segmented group.
graphic slot Decorative visual before the heading. Single icon-only Badge with size="large"; not rendered without a heading.
accessory slot Contextual info inline beside the heading text. Badge, Icon, Button, Menu, Text, Avatar, Thumbnail.
supplemental slot Status/metadata for the section as a whole, at the inline-end of the header. Badge, Avatar, Text, Icon, Thumbnail.
<Section heading="Payment" subheading="Captured 2 days ago">
  <Badge slot="graphic" icon="credit-card" size="large" />
  <Badge slot="accessory">Paid</Badge>
  <Text slot="supplemental">$248.00</Text>
  <Button slot="primaryAction">Refund</Button>
  Content
</Section>

Number and EmptyState (net new)

Both are in the Polaris 3P allowlist (UI_EXTENSIONS_COMPONENTS in admin-ui-components/lib/uiExtensionsBundlePlugin.js) but had never been generated onto any definition surface, so an extension author writing s-number or s-empty-state got no types at all.

s-number — no slots:

Property Type Notes
tone 'auto' | 'neutral' | 'info' | 'success' | 'warning' | 'caution' | 'critical' Default 'auto'.
color 'base' | 'subdued' Default 'base'.
fontSize 'auto' | 'small-200' | 'small-100' | 'small' | 'base' | 'large' | 'large-100' Default 'auto'; also applies matching line-height and letter-spacing.
fontWeight 'auto' | 'base' | 'medium' | 'semibold' | 'bold' Default 'auto'.
dir, accessibilityVisibility inherited from TextProps Required<Pick<TextProps, …>>.
id, lang, children inherited from TextProps The component styles the value passed in and renders it as given — format and localize it yourself.

s-empty-state:

Addition Kind Notes
heading property Required on the element; optional in JSX props.
graphic slot A single Image or Icon, directly or as the only child of a wrapper.
subheading slot Supporting text below the heading. Text and Link.
primaryAction slot A single Button with variant="primary".
secondaryActions slot A single Button with variant="secondary" or "auto" — despite the plural name, only one renders.
<EmptyState heading="No orders yet">
  <Icon slot="graphic" type="orders" />
  <Text slot="subheading">Orders will show up here once customers start buying.</Text>
  <Button slot="primaryAction" variant="primary">Create order</Button>
</EmptyState>

How

# in libraries/javascript/polaris (shop/world)
pnpm build:definitions --configComponents=Section
pnpm build:definitions --configComponents=Number,EmptyState

Note for anyone reproducing this: there is no -- before --configComponents. Under pnpm 11 the extra -- makes rollup treat the flag as a positional path. documentation/extensions-architecture.md in the Polaris zone is stale on this.

Scope note

The generator also rewrites surfaces/admin/components.d.ts and surfaces/admin/components/shared.d.ts in full. Both are still generated from 1.25.0 and have since accumulated hand-written docs polish (Description improvements, Use 'web components' terminology, Fix broken web-components doc links). Regenerating them here would be +7.9k/-2.5k and +4.2k/-1.3k and would revert all of that, so this PR is scoped to the per-component files — the same shape as 6ed2ff9, which exposed Popover.

Bringing those two files back in sync with Polaris is real work that deserves its own PR.

Follow-ups

  • shopify.dev docs are not affected by this PR. docs/surfaces/admin/build-docs.mjs:51 generates from src/surfaces/admin/components.d.ts, not from the per-component file. That aggregate still has SectionSlots (@publicDocs) declaring only children, and RequiredSectionProps listing primaryAction/secondaryActions but not subheading, graphic, accessory, or supplemental — so the docs continue to describe Section at 1.25.0 until components.d.ts is regenerated. Number and EmptyState are absent from that aggregate entirely, so they get no docs page from this PR either.
  • Number and EmptyState are not in admin/components/StandardComponents.ts. This PR ships their types; it does not add either to the standard admin extension component set. Section was already there, so it needs no component-set change. Exposing the two new ones is a deliberate separate decision, the shape 6ed2ff9 used for Popover.
  • Note that Section.d.ts, Number.d.ts, and EmptyState.d.ts import PreactCustomElement and RenderImpl from ./shared.d.ts, which does not export them; Number.d.ts and EmptyState.d.ts additionally import TextProps and EmptyStateProps$1, which shared.d.ts only has as unexported TextProps$1 / EmptyStateProps$1. None of this errors because skipLibCheck: true (@shopify/typescript-configs/base.json), and Popover.d.ts already ships the identical dangling imports. It resolves when shared.d.ts is regenerated.
  • shop/world: the admin-web remote definitions for s-section, s-number, and s-empty-state need the matching properties and slots. That change can only land after this merges and admin-web bumps @shopify/ui-extensions-next past 2026.10.0-rc.8.

Testing

  • prettier --check clean on the changed files.
  • Section is already in StandardComponents.ts, so no component-set change is needed.

Regenerated from admin-ui-components 2.21.2 with
`pnpm build:definitions --configComponents=Section`.

Adds the `subheading` property and the `primaryAction`,
`secondaryActions`, `graphic`, `accessory`, and `supplemental` slots.

Scoped to the per-component file, matching how Popover was exposed in
6ed2ff9: the generator also rewrites `components.d.ts` and
`shared.d.ts` wholesale, and both still carry hand-written docs polish on
top of output generated from 1.25.0, so regenerating them here would
revert it.

Assisted-By: devx/796ee9a4-a314-4344-89e7-0d9abf6b59d9
@kyledurand
kyledurand requested a review from a team as a code owner September 1, 2026 13:48
@kyledurand

Copy link
Copy Markdown
Member Author

/snapit

@shopify-github-actions-access

Copy link
Copy Markdown
Contributor

🫰✨ Thanks @kyledurand! Your snapshots have been published to npm.

Test the snapshots by updating your package.json with the newly published versions:

"@shopify/ui-extensions": "0.0.0-snapshot-20260902134640",
"@shopify/ui-extensions-tester": "0.0.0-snapshot-20260902134640"

Regenerated from admin-ui-components 2.21.2 with
`pnpm build:definitions --configComponents=Number,EmptyState`.

Both components are already in the Polaris 3P allowlist
(`UI_EXTENSIONS_COMPONENTS` in `uiExtensionsBundlePlugin.js`) but had no
type definitions on any surface, so extension authors writing
`s-number` or `s-empty-state` got nothing.

`Number` declares `tone`, `color`, `fontSize`, and `fontWeight`, plus the
`dir`, `accessibilityVisibility`, `id`, `lang`, and `children` it takes
from `TextProps`. It has no slots. `EmptyState` declares the `heading`
property and the `graphic`, `subheading`, `primaryAction`, and
`secondaryActions` slots.

Scoped to the per-component files, matching Section in 96cf66d: the
generator also rewrites `components.d.ts` and `shared.d.ts` wholesale,
and both still carry hand-written docs polish on top of output generated
from 1.25.0, so regenerating them here would revert it.

Neither component is listed in `admin/components/StandardComponents.ts`,
so this ships the types without adding either to the standard admin
extension component set. Exposing them is a separate change, the shape
6ed2ff9 used for Popover.

Assisted-By: devx/d40aa885-861c-43ba-a99a-f234ceba6551
@kyledurand kyledurand changed the title Update Admin Section types with subheading and header slots Update Admin Section types and add Number and EmptyState types Sep 2, 2026
The per-component `.d.ts` files under `surfaces/admin/components/` are what
3P developers actually import (`./admin/components/*` maps to
`build/ts/surfaces/admin/components/*.d.ts` in package.json exports), and they
had drifted a long way from the Polaris implementation.

Roughly 35 components gain properties that already existed at runtime but were
absent from the types. The worst case was `DatePicker`, which was missing its
entire prop surface -- `allow`, `allowDays`, `defaultValue`, `defaultView`,
`disallow`, `disallowDays`, `value`, `view` and `visibleMonths` were all
untyped. Others include typography on `Text` / `Paragraph` / `Heading`,
`Banner`'s `heading` and `dismissible`, `Button`'s `variant`, `ColorPicker`'s
`alpha` / `value` / `defaultValue`, and `Modal`'s `heading` and `padding`.

Two things in this diff are worth a reviewer's attention:

1. `click({sourceEvent}?: ClickOptions)` is removed from 55 components, along
   with the `ClickOptions` and `ActivationEventEsque` interfaces. This is not
   accidental: the method is tagged `@private` in `PreactCustomElement.tsx`,
   and the definitions generator strips `@private` members
   (`mergeExternalDtsPlugin.js`). The checked-in files predate that behavior,
   so they have been advertising a private API. The standard DOM
   `element.click()` is untouched; only the single-argument overload goes.

2. `Thumbnail` and `Image` look like they lose `alt`, `src` and the border
   properties. They do not -- those are still supplied by
   `extends Required<Pick<...>>`; the regeneration just stops redeclaring them
   inline.

`components.d.ts` and `components/shared.d.ts` are deliberately left alone.
`components.d.ts` feeds the shopify.dev docs build rather than the published
types, and no per-component file imports from `shared.d.ts`, so neither is
needed for this change and regenerating them would revert hand-written
documentation.

Generated with the fixed definitions generator (shop/world#2034910 and
shop/world#2035692) and formatted with the repo's prettier config.
`yarn type-check` passes.

Assisted-By: devx/796ee9a4-a314-4344-89e7-0d9abf6b59d9
Comment thread .changeset/admin-section-header-slots.md Outdated
Comment thread .changeset/admin-component-type-drift.md Outdated
kyledurand and others added 4 commits September 2, 2026 14:43
Fixes the `lint` and `test` failures on the previous commit. Both came from
the same mistake: I ran the generator against a scratch clone that had no
`node_modules`, so its final `yarn lint --fix` step died with exit 127 and I
treated that as harmless. It is not harmless -- it is part of the pipeline.

`test`: 65 of the 66 per-component files import `PreactCustomElement` from
`./shared.d.ts`, and I had deliberately excluded `shared.d.ts` from the
previous commit. Without it the element classes no longer resolve a base that
extends `HTMLElement`, so every DOM member disappeared from them:

  SelectionAction.test.ts: Property 'textContent' does not exist on type 'Text'
  SelectionAction.test.ts: Property 'getAttribute' does not exist on type 'AdminAction'

I had "verified" that no file imported it with a grep for `from './shared'`,
which cannot match the real specifier `from './shared.d.ts'`. `yarn type-check`
did not catch it either -- the breakage only shows up at a use site, which is
why the example extension's `tsc --noEmit` was the thing that failed.

`lint`: the generator emits a fixed block of `eslint-disable` comments in every
file regardless of whether each rule is triggered there, and the repo treats
unused disables as errors (`eslint-comments/no-unused-disable`), plus some
emitted `type` aliases that should be `interface`. 577 errors. The generator's
own `yarn lint --fix` step resolves all of them; this commit is that step,
run in a checkout that actually has dependencies installed.

Verified locally against every step the `test` and `lint` jobs run:
yarn lint (clean cache), yarn type-check, yarn build,
examples/testing/admin-testing-example npm run typecheck && npm test,
packages/ui-extensions-tester typecheck and tests, and package:publint.

Assisted-By: devx/796ee9a4-a314-4344-89e7-0d9abf6b59d9
@kyledurand
kyledurand merged commit 622d5ae into 2026-10-rc Sep 3, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants