Skip to content
HomePagesHomePages template kit

unit-collection-item-marker

"A collection edited as one unit must not render data-slot-item row markers."

Venue: check — A collection edited as one unit must not render data-slot-item row markers.

A list edited as one unit must render no data-slot-item markers. check renders every fixture and reads the markers that reached the DOM; this is reported when a list whose editing granularity is "unit" emits an item marker on any row, in any fixture.

The granularity comes from the declared ITEM, and nothing declares it. A record item — list.of({ … }, { … }) — is edited per row. Every single-slot item is edited as one card, so its rows are not individually selectable and a row marker on one is a contradiction between the schema and the markup.

The editor trusts the item. A unit-edited list gets one sidebar card and no per-row selection: nothing ever reads its item markers, so a marker there is not extra coverage — it is a claim the editor will never honor. A user clicks the marked row, nothing selects, and the row looks broken; an author reads the markup, sees row markers, and reasonably expects per-row editing the item never asked for.

Before this check, that mismatch was invisible: the marker was simply ignored. Making it an error keeps the schema and the markup telling the same story, whichever one is wrong — either the item should be a record, or its rows should stop claiming identity.

Decide which side is right. If the rows really are individually editable, they have per-row content — declare the item as the record it is:

import { defineSchema, list, text } from "@homepages/template-kit";
export const schema = defineSchema({
label: "Amenities",
slots: {
features: list.of(
{
label: text.short({ label: "Name" }),
detail: text.medium({ label: "Detail" }),
},
{ label: "Features", title: "label" },
),
},
});

If the list really is one editing unit, render its rows as plain elements — the container keeps the list’s own marker, the rows carry none:

import { bindItems, bindSlots, Section, Slot } from "@homepages/template-kit";
import { schema } from "./schema.js";
import type { Props } from "./schema.js";
export function Renderer({ slots }: Props) {
const slot = bindSlots(schema, slots);
return (
<Section>
<Slot.List slot={slot.features} as="ul">
{bindItems(slot.features).map((feature) => (
// template-kit/unit-collection-item-marker: a row marker on a unit-edited list
<Slot.Group slot={feature} as="li" key={feature.index}>
{feature.value}
</Slot.Group>
))}
</Slot.List>
</Section>
);
}
import { bindItems, bindSlots, defineSchema, list, Section, Slot, text } from "@homepages/template-kit";
import type { SectionProps } from "@homepages/template-kit";
const schema = defineSchema({
label: "Amenities",
slots: {
features: list.of(text.short({ label: "Text" }), { label: "Features" }),
},
});
type Props = SectionProps<typeof schema>;
export function Renderer({ slots }: Props) {
const slot = bindSlots(schema, slots);
return (
<Section>
<Slot.List slot={slot.features} as="ul">
{bindItems(slot.features).map((feature) => (
<li key={feature.index}>{feature.value}</li>
))}
</Slot.List>
</Section>
);
}
  • missing-slot-marker — the opposite direction: a record-item list must mark every row, in every rendered copy.
  • Schema reference — the list grammar the granularity is read from.
  • Slot primitivesSlot.List, Slot.Group, and which marker each emits.