Skip to content

Revise the heading size scale to follow a documented typographic convention #369

Description

@HMarzban

Related

#367 tracks the defect that leaves moved headings unsized. This issue is about the scale itself. #367 sets its minimum step and title rule from the convention chosen here.

What happened

Edward Saperia sent these reports on 2026-09-26.

  • Labels look like body text. Under a heading "Team 13", the lines "Members:", "Problem Idea:", "Approach:" and "Datasets:" are H3 headings. Edward wrote: "This is an H3 - way too small, I can't tell it apart from normal text!" He added: "I like big fat headings".
  • Same level, two sizes. "4. The Constitution" renders large. "5. The Agent" renders much smaller, close to body text. We do not know the levels of these two headings.

What we expect

Every heading stands out from body text at a glance. A higher level is clearly larger than a lower one. Two headings of the same level have the same size. A named typographic convention sets the scale, and we can say why each size is what it is.

Findings

Read from code. Nobody has measured these in a browser yet.

  • The smallest rank in a section is always 12pt (MIN_SIZE). The largest is 20pt (MAX_SIZE).
  • We found no rule that sets a size for body paragraphs in the pad. Body text then follows the root size, which is 16px by default, or 12pt. The smallest heading would have the same size as body text, and bold would be the only difference.
  • Every heading level has weight 700 and line height 1.15. Size is the only signal between levels.
  • Sizes spread evenly between 12pt and 20pt. With three levels, the ratio between neighbours is 1.25 to 1.33. With six levels, it is 1.09 to 1.13.
  • The CSS fallbacks, used when a heading has no size, are 20, 16, 14, 12, 11 and 11pt for h1 to h6. With a 12pt body, h4 equals body text, and h5 and h6 are smaller.

Reference points

The review compares at least these, then picks one.

  • The HTML default sizes: 2em, 1.5em, 1.17em, 1em, 0.83em and 0.67em for h1 to h6 (Sections and headings). Its h4 to h6 are at or below body size, so this default is a weak target for skimming.
  • A modular scale: a fixed ratio between neighbouring levels, such as 1.2 or 1.25, built from the body size.
  • The current rule: sizes spread evenly between 12pt and 20pt by rank in a section.

Acceptance criteria

  • The review names one convention and records it, with the reason, in apps/webapp/src/components/TipTap/CLAUDE.md §HeadingScale.
  • The smallest heading is larger than body text by a ratio the review states.
  • In a section that uses all six levels, neighbouring levels differ by at least a ratio the review states.
  • Two headings of the same level in one section have the same size.
  • Edward's examples pass: an H3 label beside body text, "Team 13" above its labels, and "4. The Constitution" against "5. The Agent".
  • A test pins the scale rule.
  • The result is checked in light and dark themes, on desktop and on a phone.

Needs from Edward

The links to the two pads, or the level of each heading in the "4. The Constitution" screenshot. We need them to tell a scale problem from a defect.

Blocked by

None — can start now.

Agent brief

Type: HITL. The maintainer picks the convention, the body ratio and the step ratio. An agent then implements and tests it.

Category: enhancement

Current behavior: See Findings.

Desired behavior: Headings stand out from body text and from each other, and the scale follows one named convention that the spec records.

Where to start: apps/webapp/src/components/TipTap/extensions/heading-scale/heading-scale.ts (MAX_SIZE, MIN_SIZE, buildDecorations). apps/webapp/src/styles/editor/_heading-node.scss (--hd-size and the per-level fallbacks). apps/webapp/src/components/TipTap/CLAUDE.md §HeadingScale. Search by symbol. File names are hints as of 2026-09-29.

Rules that apply: §HeadingScale is a mandatory spec. It ranks levels inside a section, uses decorations only, writes no sizes into the document, and forbids fixed per-level point maps. A convention that sets a size per level changes that spec. Get a maintainer ruling, then update the section in the same change. AGENTS.md §Test Policy allows a test here, because it pins reported behavior. CONTEXT.md §Pad outline holds the names.

Verify: Start make dev-local and confirm the webapp port. Open a pad that has all six levels and body text. In the console, run [...document.querySelectorAll('.ProseMirror h1, .ProseMirror h2, .ProseMirror h3, .ProseMirror p')].map(n => [n.tagName, getComputedStyle(n).fontSize]) and compare the values. Check light and dark themes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    EditorTiptap & ProsemirrorUIenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions