Pular para o conteúdo

Dividers

components specs/components/dividers.kmd

Thin line separating content groups within a single surface. Material parity (`/components/dividers`). Covers full-width, inset, middle (with text), and sub-header dividers. Defines when to use vs whitespace alone.

Quando esta spec se aplica

Triggers primários

Todos os triggers

Corpo da especificação

Spec — Dividers

Facet Visual of Koder Design. Material parity: https://m3.material.io/components/dividers.

When to use a divider vs whitespace

NeedUse
Visually group ungrouped rowsDivider
Already grouped by indent / card / surfaceWhitespace only
Separate sections with titleSubheader divider
Inline content split (mid-paragraph)Inline divider with text
Compact list with many rowsDivider (otherwise hard to scan)
Spacious layout, few itemsWhitespace

Rule: divider answers "where does one group end and the next begin". If whitespace already makes that clear, skip the divider.

4 variants

VariantWidthPaddingUse
Full-bleed100% of container0Separates major sections at surface edge
InsetIndented from left16 px (matches list inset)List rows with leading icon/avatar
Middle (with content)Two segments around centered text/iconn/aSection heading inline
SubheaderFull-bleed + label above0Labeled section break

Anatomy

Full-bleed:
────────────────────────────────────────

Inset:
   ─────────────────────────────────────   (← 16 px left padding)

Middle with text:
   ──────────────  OR  ──────────────────

Subheader:
   Section title
   ────────────────────────────────────
  • Line thickness: 1 px (logical pixel)
  • Color: outline-variant (low-emphasis surface line)
  • Subheader label: label-large (14/20, weight 500), text-muted
  • Inline text: label-medium, 8-12 px padding around text

R1 — Color and emphasis

EmphasisColorUse
Low (default)outline-variantMost dividers
HighoutlineRare — only when divider is the primary visual structure
Decorativeprimary 12%Highlight a section break (e.g., onboarding)

Never use full saturation (primary solid) — divider should be subtle background, not foreground.

R2 — Orientation

OrientationUse
Horizontal (default)Between rows / sections in a vertical layout
VerticalBetween items in a horizontal layout (toolbar, segmented controls)

Vertical divider:

  • Height: 24 px (matches surrounding control height OR set explicitly)
  • Width: 1 px
  • Margin: 8 px horizontal

R3 — Inset rules

Inset divider's left edge aligns with the START of meaningful content in the row above. Common alignments:

Inset distanceAligns with
16 pxFirst text character (list item with no leading element)
56 pxAfter a 24 px icon + 16 px gap
72 pxAfter a 40 px avatar + 16 px gap

Goal: divider visually splits the content into discrete rows without crossing into the leading-element column. The leading column reads as "continuous" while the text column reads as "discrete rows".

R4 — Middle (with content) divider

Inline text divider for section breaks within text content:

   ──────────────  OR  ──────────────
   ──────────  CONTINUED  ──────────
   ─────────  • • •  ─────────
  • Text padded 8-12 px on either side
  • Text is label-medium, text-muted (subtle)
  • Line on each side, equal length
  • Used for: onboarding step breaks, "Show more" pagination, modal alternate-action separator ("OR sign in with…")

R5 — Subheader divider

Pairs a label-large heading with a full-bleed divider below:

   System
   ────────────────────────────────────
   Notifications      ⌄
   Privacy            ⌄
   Storage            ⌄

   Account
   ────────────────────────────────────
   Profile            ⌄
   Sign out
  • Used for grouped list sections (Settings is the canonical example)
  • Label sits at standard list left-padding (16 px); divider is full-bleed below
  • Label is text-muted weight 500 — secondary emphasis vs row labels

R6 — Spacing

Standard vertical spacing around a divider:

DensityAboveBelow
Compact4 px4 px
Default8 px8 px
Comfortable12 px12 px

If dividers are between list rows of fixed height, NO extra spacing — divider sits at the row boundary. Spacing applies for free-form dividers (between cards, sections, etc.).

R7 — Accessibility

  • Decorative divider: role="separator" + aria-orientation if vertical (default horizontal); no extra label needed
  • Subheader: heading semantics drive the divider's meaning — divider itself remains role="separator"; heading is a real <h2> / <h3> element
  • Middle-text divider: same — text inside is the meaning; divider is decorative
  • DO NOT add aria-label to a divider with descriptive text — it's visual scaffolding, not content

R8 — Per-preset variation

PresetColorThickness
material3outline-variant (1 px low-emphasis)1 px
material212% on-surface alpha (sharper)1 px
ios_cupertinoHairline .separator (0.5 px on retina)0.5 px
gnomeSubtle 1 px gray1 px
windows_11Mica-aware subtle 1 px1 px
brutalistSolid black, thick2-3 px
terminal_classicASCII ────────────────n/a

R9 — Forbidden patterns

  • ❌ Multiple consecutive dividers (no double / triple lines)
  • ❌ Divider thicker than 2 px (becomes a border / rule)
  • ❌ Saturated primary color as divider (visual noise)
  • ❌ Divider where whitespace alone would do (over-decoration)
  • ❌ Divider between EVERY card in a card list (cards are already self-grouped)
  • ❌ Divider crossing into the leading-element column (icon / avatar) of inset list rows
  • ❌ Vertical divider taller than its surrounding controls (looks detached)
  • ❌ Decorative divider with aria-label (clutters screen reader output)
  • themes/color-roles.kmdoutline-variant / outline token
  • themes/typography.kmdlabel-large for subheader label
  • components/lists.kmd — most common host context
  • foundations/elements.kmd — Container family (divider is a sub-class of structural element)

Requirements (testable)

Requirement: Color and emphasis default {#req-divider-color-emphasis}

A divider SHALL render at low emphasis using the outline-variant color token by default, and SHALL NOT use a fully saturated foreground color (solid primary) as its line color; higher-emphasis (outline) or decorative (primary 12%) colors MAY be applied only for the documented exceptional cases.

Scenario: Default divider uses outline-variant

  • GIVEN a horizontal divider added with no explicit emphasis override
  • WHEN the divider is rendered
  • THEN its line color resolves to the outline-variant token
  • AND its line thickness is 1 logical pixel

Scenario: Saturated primary is rejected

  • GIVEN a divider configured with a solid saturated primary line color
  • WHEN the component validates its styling
  • THEN the configuration is rejected as a forbidden pattern
  • AND the divider does not render with the solid primary color

Requirement: Orientation {#req-divider-orientation}

A divider SHALL default to horizontal orientation for separating rows or sections in a vertical layout, and SHALL support an explicit vertical orientation for separating items in a horizontal layout, where the vertical divider is 1 px wide with 8 px horizontal margin and a height not exceeding its surrounding controls.

Scenario: Default orientation is horizontal

  • GIVEN a divider created without an orientation argument
  • WHEN it is rendered between two stacked rows
  • THEN its computed orientation is horizontal

Scenario: Vertical divider matches control height

  • GIVEN a vertical divider placed inside a toolbar of 24 px control height
  • WHEN it is rendered
  • THEN its width is 1 px
  • AND its horizontal margin is 8 px on each side
  • AND its height does not exceed the surrounding control height

Requirement: Inset alignment {#req-divider-inset-alignment}

An inset divider SHALL align its left edge with the START of the meaningful content in the row above (16 px with no leading element, 56 px after a 24 px icon, 72 px after a 40 px avatar), and SHALL NOT extend into the leading-element (icon/avatar) column.

Scenario: Inset aligns after a leading avatar

  • GIVEN an inset divider under a list row with a 40 px leading avatar and a 16 px gap
  • WHEN the divider is rendered
  • THEN its left edge starts at 72 px from the row's left edge
  • AND no part of the line crosses into the leading avatar column

Requirement: Spacing at fixed-height row boundaries {#req-divider-spacing}

A divider placed between list rows of fixed height SHALL sit exactly at the row boundary with NO extra vertical spacing added; a free-form divider between cards or sections SHALL apply the density-appropriate spacing above and below (4 px compact, 8 px default, 12 px comfortable).

Scenario: No extra spacing between fixed-height rows

  • GIVEN a divider between two fixed-height list rows
  • WHEN the divider is rendered
  • THEN it sits at the shared row boundary
  • AND no additional vertical spacing is inserted above or below it

Scenario: Free-form divider uses default density spacing

  • GIVEN a free-form divider between two cards at default density
  • WHEN the divider is rendered
  • THEN 8 px of spacing is applied above the line
  • AND 8 px of spacing is applied below the line

Requirement: Accessibility semantics {#req-divider-a11y}

A divider SHALL expose role="separator", SHALL set aria-orientation when it is vertical (horizontal being the implicit default), and SHALL NOT carry an aria-label even when it displays descriptive middle text, because the divider is visual scaffolding rather than content.

Scenario: Vertical divider exposes orientation

  • GIVEN a vertical decorative divider
  • WHEN its accessibility tree is inspected
  • THEN it exposes role="separator"
  • AND it exposes aria-orientation="vertical"

Scenario: Middle-text divider carries no aria-label

  • GIVEN a middle divider showing the inline text "OR"
  • WHEN its accessibility tree is inspected
  • THEN the separator element has role="separator"
  • AND the separator element has no aria-label attribute

Requirement: Forbidden structural patterns {#req-divider-forbidden}

A divider SHALL NOT be rendered as two or more consecutive lines, and SHALL NOT exceed 2 px thickness (beyond which it reads as a border/rule rather than a divider).

Scenario: Consecutive dividers are rejected

  • GIVEN two dividers placed directly adjacent with no content between them
  • WHEN the layout is validated
  • THEN the doubled divider is flagged as a forbidden pattern
  • AND only a single divider line is emitted

Scenario: Over-thick divider is rejected

  • GIVEN a divider configured with a 4 px line thickness
  • WHEN the component validates its styling
  • THEN the thickness is rejected for exceeding the 2 px maximum

Referências