Category group

The section that opens with a head and holds what belongs under it: four subscriptions under "Streaming (4)", two alerts under "Needs you", three switches under "What Tendd tells you about". It is what turns fourteen rows into five readable groups, and it is the reason Home has no heavy heading anywhere.

Organism12 grey pagesno axisno states, not interactivedraws exactly one line

Anatomy

A head, a list, and a hairline between two items. That is the whole component. Everything below is drawn by design/system/components/category-group.css and by the files of the components inside it, through the same entry point a product screen loads, so this page cannot drift from the screens: there is no second copy of the CSS here to drift from.

Streaming (4)

$54.96 a month

Behaviour at width

From --bp-desktop, 56.25rem: break-inside: avoid. One declaration, and outside a multicolumn container it does nothing at all, which is why it is written here rather than on the column set: the subject of the rule is the group, and the subject owns it.

What it prevents is a rendering fault on the screen whose job is calm: without it a category's four subscriptions split across the fold and the group heading is left alone at the bottom of column one. See Width.

No fill, no edge, no corner, and that is the decision the component is. Five groups stack on Home with only their heads and their hairlines to tell them apart. Five bordered boxes down a phone screen is the compartmented look the visual language was chosen against, and DESIGN.md says so in one line: rows stack inside one bordered container so a list reads as one object rather than as a stack of cards. Where a group does want paper and a corner, the container around it is the Panel and the group is still this.

Variants and sizes

One form, so there is no matrix. A margin, a list reset and a hairline, and they are the same on all 32 occurrences across the 12 pages. There is no dense group and no bordered group, and a group never changes size: what changes between one group and the next is what is inside it, and everything inside it is a component with a page of its own.

The name is narrower than the job, and the count is where you see it. Five of the twelve pages group subscriptions by category, which is the screen the component was named on. The other seven group alerts by urgency (alerts, 2 groups), settings by subject (settings, 3), promises by topic (data-privacy, 3). The class is .group on all twelve and the component is one component: a titled section with an optional divided list inside it. The name comes from where it was found, which is how docs/inventory.md names everything, and step 9 may widen it.

What it holdsPagesAnd what draws the hairline
Subscription rows, in a bare ul5this file, and only this file: the list has no class to hook
Alert items, in ul.divlist3this file and Divided list, with the same declaration and the same token, so nothing renders twice
Form fields and switch rows, no list at all4nothing. The rule matches no element, and the group is a margin and a head

The overlap in the middle row is deliberate and it is recorded. docs/inventory.md settled it at step 2 in one line: there were three identical li + li divider rules in kit.css, two of them merged into .divlist, and "the third belongs to .group and stays a usage". It stays because the bare list on Home has nothing else to draw it, and it is harmless where the two meet because both read --line-divider at 1px.

One responsive rule, and it is not a variant. Past a 900px container the group takes break-inside: avoid, because the Groups column set around it runs in columns from there, as many 300px columns as its container holds and never more than three. The column count belongs to that wrapper; what belongs here is the group's own refusal to be cut in half. kit.css also re-declared the margin in that block at 26px, and that half is deleted: 26 lands on --space-24 under the founder's grid, which is what the base rule already sets, so the override became byte-identical to the rule it was overriding. Measured either side of the step: 24px at an 892px container and 24px at 908px. It goes for the same reason .btn.compact went, which is that a declaration changing nothing costs the next reader a minute.

When to use it

A group is for a set of things that share a reason, with a head that names the reason. J-MAIN reads "I want to see all my recurring charges in one calm view", and the calm comes from the grouping: fourteen rows in one undifferentiated column is a list a person has to read, and five groups of two to four is a list a person can scan. The head carries the count and the subtotal so the group answers its own question before any row is read.

On the path a person meets it first on Home, which is the screen the product exists for, and then everywhere a screen has more than one subject: Alerts splits into "Needs you" and "Just so you know", Settings into "Your details", "Your plan" and "What Tendd tells you about", Data and privacy into three plain answers. Every head comes from voice/docs/microcopy.md and every one of them is a phrase rather than a category word: "What Tendd tells you about", not "Notifications".

The subtotal is a fact and never a verdict. "$54.96 a month" sits at the far end of the head in the muted tier at the same size as the heading, because it is context for the group and not a second heading. It never carries a colour, an arrow or a comparison: the one number allowed to be loud in this product is the monthly total, and a group subtotal competing with it would break the One Number Rule five times on one screen.

The rule, and the anti-rule

The group separates, the row does not

One hairline, between the two rows, and none under the second. The row itself draws border: 0, which is why the last row needs no rule to undo one. Hover either row: the fill changes and the line does not move, because a border appearing under the pointer would shift every row below it by a pixel.

Never let the group set the row's type
.group .row .name { font-size: 14px }

The row is written and it is correct: the census measured 47 of them across six coloured pages and found one value on every one of twelve properties, which no other component in the sweep managed. A rule here that changed a name's size would end that, and it would end it invisibly, because the group and the row are never on screen apart. Measured on this page: the merchant name inside the group is 16px at weight 600, which is exactly what it is on its own page.

Use a group

Your plan

Free

Unlimited subscriptions and unlimited bank connections. History, trends and advanced alerts are part of Tendd Pro.

A section of a screen that has more than one subject, named by its head. It holds no list at all here, and that is a third of its occurrences: the divider rule simply matches nothing, and what is left is a margin and a head, which is exactly what this block needs.

Use a card instead
One subject with its own boundary, standing beside other subjects a person is not acting on.

When the section is one thing a person acts on rather than a set of things they scan, the container is the Card: paper, a hairline all the way round and a 14px corner. A source on Your sources is a card because each connection is a separate decision; "Streaming (4)" is a group because the four rows under it are four decisions and the head is only telling you what they have in common. The test is the head: a group's head describes what is below it, a card's title is the subject.

States

None, and the reason is one line: a group is not interactive. It is a <section> on all 32 occurrences, it holds no anchor, no button and no summary of its own, it carries no tabindex and no role, and it does not collapse: the one disclosure in the app shell is a details.panel summary and that is the Panel. kit.css gave it no hover, no active and no focus rule, and adding one would be inventing behaviour the product does not have.

Everything inside a group that answers a pointer answers it as itself, and each is live on its own page: the Subscription row has hover and focus-visible, the Alert item has hover and focus-visible, the Nav row has both as well. The specimens above are real anchors with real hrefs, so hover one and the hover you see is the row's own, read off the real thing rather than off a photograph of it.

The technical half

ReadsWhich tokenGrowing from
the line between two items--line-divider--hairline-soft, and --hairline-soft-dark in the dark theme. Decorative, so it owes no threshold: 1.23:1 light is what keeps a list of fourteen from reading as a table
the space under the block--space-24primitive, straight
the list reset--space-0primitive, straight. Zero is a real value here and not the absence of one
no fill, no edge, no radius, no paddingnoneby decision. The group is a grouping, not a container
no colour and no type of any kindnonethe head owns its type, the rows own theirs. This file reads two tokens in total

It hosts three molecules and paints none of them. Group head, Subscription row and Alert item get no rule here at all, not even a margin: the head spaces itself, the rows are separated by the one hairline above, and the whole file is four declarations long. It is the shortest organism in the system and that is the point of it.

The container query is measured on both sides, because a query that never fires looks calm. break-inside: avoid arrives at a 900px container. It needs an ancestor with container-type: inline-size, which base.css declares once on body; nothing in this file declares a second one, because a container between the body and these rules would re-point the query at a different box with no error and no symptom.

Lives in design/system/components/category-group.css. Stands on 13 grey pages and 13 coloured ones, 36 groups on each side. Coloured screens carrying it: Home, Home, could not refresh, Home, save focus, Home, loading, History and trends, Settings, Settings, no account, Alerts and its empty and loading states.

<section class="group" aria-label="Streaming"> <div class="group-head"> <h2>Streaming (4)</h2> <span class="subtotal">$54.96 a month</span> </div> <ul> <li><a class="row" href="subscription-detail.html" aria-label="...">...</a></li> <li><a class="row" href="subscription-detail.html" aria-label="...">...</a></li> </ul> </section>

The specimens above stand in .kit-stage app full wide, 620px, because that is a width the product gives them: measured at a 1440 viewport, a group renders 620px on Settings and 424.5px on Home, where two column groups share the screen. The stand's default 440px would be right for Home alone and would crush the Settings form.