Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .changeset/7580-responsive-vocabulary-rehome.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
'@object-ui/types': minor
'@object-ui/layout': minor
'@object-ui/mobile': minor
'@object-ui/core': minor
---

Re-home the breakpoint layout vocabulary and delete the two dead responsive
implementations (objectui#7580, maintainer ruling 2026-09-04, option A).

**Breaking, deliberately, in one direction only.** `@objectstack/spec` retired its whole
`ui/responsive` vocabulary in objectstack#11027 — `ResponsiveConfigSchema`,
`BreakpointName`, `BreakpointColumnMapSchema` and `BreakpointOrderMapSchema` — on the
stated ground that the four types "had no other authorable carrier". That ground is
measurably false on the renderer side: `responsive-grid` is a REGISTERED SDUI component
whose authorable `columns` input is typed by `BreakpointColumnMap` and applied by
`resolveColumnClasses` on the render path, and `BreakpointName` types four live readers in
`@object-ui/mobile`. The tombstone's own return condition — the vocabulary "returns if and
when a renderer implements it" — is already met here, so the two types a renderer reads
are re-homed rather than retired.

What survives, under the same names and the same members:

- `BreakpointName` (`xs`…`2xl`) is now declared in `@object-ui/types` (`mobile.ts`) instead
of re-exported from the spec. **No consumer change**: same name, same six members, same
export sites on `@object-ui/types` and `@object-ui/mobile`. Only its provenance moved.
- `BreakpointColumnMap` is now declared in `@object-ui/layout` (`ResponsiveGrid.tsx`),
verbatim from the retired `$strict` schema: six optional column counts, no index
signature. `responsive-grid`'s `columns` input and its resolver are unchanged.

What is removed:

- `BreakpointOrderMap` (`@object-ui/layout`) — retired with the key, not re-homed. It had
no read point in the package; it was published only because the retired
`ResponsiveConfigSchema` paired it with the column map, so an author configuring `order`
needed the type. With the schema gone there is no order vocabulary for it to be the type
of, and re-declaring it would be the declare-without-enforce shape ADR-0049 removes.
- `useResponsiveConfig` (`@object-ui/mobile`), with its `SpecResponsiveConfig` and
`ResolvedResponsiveState` exports, and `ResponsiveProtocol` (`@object-ui/core`), with
`resolveResponsiveConfig` / `getVisibilityClasses` / `getColumnClasses` /
`getOrderClasses` / `shouldHideAtBreakpoint`. Both read the retired
`ResponsiveConfigSchema` and both were measured at zero callers (objectui#4773).
- `SpecResponsiveConfig` / `SpecBreakpointName` (`@object-ui/types`) — dead re-exports once
the two implementations above went, dropped rather than re-declared locally, the same
disposition the retired i18n names in that file already carry.

No behaviour is retired. The live per-breakpoint readers — `useBreakpoint`,
`ResponsiveContainer`, `BREAKPOINTS` / `BREAKPOINT_ORDER` / `getCurrentBreakpoint`, and
`responsive-grid` itself — are untouched.

**Sequencing.** objectui's next `@objectstack/spec` pin bump must carry `Blocked-by:`
objectui#7580: the retirement is merged upstream and unreleased, so this must land first.
210 changes: 0 additions & 210 deletions packages/core/src/protocols/ResponsiveProtocol.ts

This file was deleted.

10 changes: 9 additions & 1 deletion packages/core/src/protocols/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,13 @@ export * from './KeyboardProtocol.js';
// which declares its own `NotificationSystemConfig` and is what every surface
// reads. Re-typing the bridge would have meant re-declaring a vocabulary the
// spec had just retired (AGENTS.md #0.1).
export * from './ResponsiveProtocol.js';
// `ResponsiveProtocol` removed in the objectstack#11027 uptake (objectui#7580):
// it bridged `@objectstack/spec/ui`'s `ResponsiveConfig`, which that retirement
// deleted with no successor, and it had zero importers in this repo (measured on
// objectui#4773; `docs/audits/2901-spec-enum-renderer-coverage.md` had already
// recorded it as one of the zero-importer protocols). Re-typing the bridge would
// have meant re-declaring a vocabulary the spec had just retired, for a reader
// that does not exist — AGENTS.md #0.1, and the same disposition
// `NotificationProtocol` got above. The layout vocabulary that DOES have a
// renderer is re-homed instead, in `@object-ui/types` and `@object-ui/layout`.
export * from './SharingProtocol.js';
58 changes: 43 additions & 15 deletions packages/layout/src/ResponsiveGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,56 @@

import React from 'react';
import { cn } from '@object-ui/components';
import type { BreakpointColumnMap, BreakpointOrderMap } from '@objectstack/spec/ui';

/**
* Breakpoint column map (`BreakpointColumnMapSchema`) and breakpoint order map
* (`BreakpointOrderMapSchema`), both re-exported from `@objectstack/spec/ui`.
* Breakpoint column map — grid column counts per Tailwind-style breakpoint,
* owned by this package since objectui#7580 (maintainer ruling 2026-09-04,
* option A).
*
* These were hand copies until objectui#4167, each carrying the word "mirrors"
* — the doc-comment shape objectstack#4115 catalogues, where the claim is what
* the next agent reads as canonical and the code is what actually decides. rc.6
* publishes both names, and both copies happened to still be exact: six
* optional numbers keyed `xs`…`2xl`, on a `$strict` schema. "Still exact" is
* the argument FOR binding them, not against — the copies had nothing to
* protect, so the only thing they could do from here was drift, and a
* breakpoint the spec adds now arrives instead of silently not existing.
* the next agent reads as canonical and the code is what actually decides. They
* were then bound by reference to `@objectstack/spec/ui`, which was right for
* as long as the spec published them.
*
* `BreakpointOrderMap` has no read point in this package (`ResponsiveGrid`
* resolves columns only); it is published because `ResponsiveConfigSchema`
* pairs the two and an author configuring order needs the type. Bound rather
* than deleted for that reason — deleting a published type is a separate
* decision from stopping it being a fork.
* objectstack#11027 retired the whole `ui/responsive` vocabulary upstream, so
* there is no longer anything to bind to — and, unlike the four types that left
* with the key, this one has an authorable carrier that survives the
* retirement. `responsive-grid` is a REGISTERED SDUI component (`./index.ts`),
* its `columns` input is authorable, and {@link resolveColumnClasses} applies
* it on the render path. The tombstone's own return condition — the vocabulary
* "returns if and when a renderer implements it" — is met here, which is why
* the type is re-homed rather than deleted.
*
* ⚠️ Members are the retired `BreakpointColumnMapSchema`'s, verbatim: six
* optional column counts keyed `xs`…`2xl`. The schema was `$strict`, so no
* index signature is restored here either — an unknown breakpoint key was a
* parse error upstream and stays a type error here.
*
* `BreakpointOrderMap` RETIRED with the key (same ruling, item 3) and is NOT
* re-homed. Its own comment in this file already recorded the reason: it had no
* read point in this package — `ResponsiveGrid` resolves columns only — and it
* was published solely because the spec's `ResponsiveConfigSchema` paired the
* two, so an author configuring `order` needed the type. That pairing is what
* objectstack#11027 deleted; with the schema gone there is no order vocabulary
* left for it to be the type OF, and re-homing it would have re-declared a key
* nothing reads on either side of the boundary — the declare-without-enforce
* shape ADR-0049 removes.
*
* ⏳ Interim, and it self-expires: the pin is still `@objectstack/spec` 17.2.0,
* which PRE-dates the retirement and still exports this name, so the collision
* is real today and carries a reasoned entry in
* `scripts/check-spec-symbol-derivation.mjs`. The guard's ratchet 3 fails an
* ALLOW entry that excuses nothing, so the pin bump is forced to delete it.
*/
export type { BreakpointColumnMap, BreakpointOrderMap };
export interface BreakpointColumnMap {
xs?: number;
sm?: number;
md?: number;
lg?: number;
xl?: number;
'2xl'?: number;
}

export interface ResponsiveGridProps {
/** Grid column map per breakpoint */
Expand Down
Loading
Loading