Skip to content

feat: add preferences.density preset to scale spacing tokens uniformly#87

Closed
smur89 wants to merge 3 commits into
mainfrom
feat/issue-50-density-preset
Closed

feat: add preferences.density preset to scale spacing tokens uniformly#87
smur89 wants to merge 3 commits into
mainfrom
feat/issue-50-density-preset

Conversation

@smur89

@smur89 smur89 commented Jun 12, 2026

Copy link
Copy Markdown
Owner

Summary

Adds preferences.density — a single coherent knob that scales every spacing em-token uniformly, replacing the need for users to hand-tune bodySize, margin, and individual em-multipliers when they want a tighter (one-page fit) or roomier (print presentation) layout. Three presets: "compact" (× 0.85), "comfortable" (× 1.0, default), "spacious" (× 1.15). Closes #50.

The multiplier is threaded through a new _spacing_scale_state and applied at every block above / below, every v(), par.spacing / leading, and list.spacing. Text sizes, icon dimensions, and rating-dot geometry are intentionally left alone — density is purely about vertical whitespace, so font-size scaling stays under bodySize.

Rendered output

Default ("comfortable") is byte-identical to main — verified via typst compile --format png on examples/example.typ before/after. The new tests/density.typ fixture renders all three presets side-by-side over three pages; CI will upload the artifact.

Test plan

  • typst compile --root . examples/example.typ examples/example.pdf succeeds
  • Each tests/*.typ fixture compiles (including the new tests/density.typ)
  • Added tests/density.typ exercising compact / comfortable / spacious
  • Updated README's Preferences table with the new key
  • Default render verified byte-identical to main (PNG cmp on examples/example.typ)

Notes for the reviewer

  • Validation panics with the list of supported values on unknown input, matching the existing _strict_merge style.
  • The negative v(-0.7 * scale * body-size) inside the L2 heading show-rule is scaled along with everything else; visual check confirms the accent-rule anchoring stays clean at both 0.85 and 1.15 (no overlap, no excessive gap).
  • The set par(leading: 0.55 * scale * 1em, ...) form was chosen over 0.55em * scale purely to mirror the K * scale * body-size pattern used elsewhere; numerically identical.

Summary by CodeRabbit

  • New Features

    • Added a preferences.density setting with presets: compact, comfortable, and spacious.
    • Documents now scale vertical spacing consistently across multiple layout sections (e.g., dividers, headings, paragraphs, lists) while keeping text/icon sizing and rating geometry unchanged.
  • Documentation

    • Updated the Preferences configuration table to include density, its default (comfortable), and supported values.
  • Tests

    • Added regression tests rendering the template with all three density presets to verify spacing behavior.

@smur89 smur89 force-pushed the feat/issue-50-density-preset branch 5 times, most recently from 9fb0935 to 2b0b958 Compare June 14, 2026 10:57
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f978eec6-8b71-46e5-a3a6-8fdc5431a8cb

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0b958 and 2d7a59b.

⛔ Files ignored due to path filters (2)
  • examples/preview.png is excluded by !**/*.png
  • examples/tests/density.pdf is excluded by !**/*.pdf
📒 Files selected for processing (3)
  • README.md
  • lib.typ
  • tests/density.typ

📝 Walkthrough

Walkthrough

Introduces a preferences.density option ("compact", "comfortable", "spacious") to the alta-typst CV template. A new render-time state (_spacing_scale_state) holds a scale multiplier derived from the density preset; alta() validates and initializes it. All vertical em-token spacing callsites across layout helpers and heading rules now multiply by this scale. A three-page visual regression test and README entry are also added.

Changes

Density Preference Feature

Layer / File(s) Summary
Spacing state, density map, default, and alta() wiring
lib.typ
Declares _spacing_scale_state and a compact/comfortable/spacious → multiplier map, adds density: "comfortable" to _default_preferences, and extends alta() to validate the density key, compute the scale, and push it into the state before rendering.
Layout helper spacing callsites updated to use scale
lib.typ
Updates name(), term(), divider(), header text block, _summary(), _name_keywords_section(), global set par/set list, and heading levels 2–4 to multiply vertical spacing values by the density-derived scale.
Visual regression test and README documentation
tests/density.typ, README.md
Adds a three-page test file rendering the template at all three density values separated by page breaks for visual comparison, and documents the new preference in the README configuration table.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐇 Hop, hop — the spacing flows,
compact squeezes, spacious grows,
one knob to rule the whitespace spread,
em-tokens scale where density's led.
"comfortable" sits right in between —
the neatest CV you've ever seen! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main change: adding a preferences.density preset that scales spacing tokens uniformly. It matches the primary objective and is clear without being verbose.
Description check ✅ Passed The description covers all required sections: Summary (with issue reference), Rendered output (comparison to main), Test plan (all checkboxes ticked), and Notes for reviewer. It provides clear implementation details and rationale.
Linked Issues check ✅ Passed The PR implementation fully satisfies issue #50: it introduces preferences.density with compact/comfortable/spacious presets (0.85/1.0/1.15 multipliers) that uniformly scale spacing tokens as specified, including validation and documentation.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the density preference feature: README documentation, core spacing scale state and multiplier logic, validation, and comprehensive test coverage. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-50-density-preset

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib.typ`:
- Around line 327-334: The _labelled_divider() function at lines 346 and 359
uses unscaled vertical spacing v(0.3 * body-size), while the divider() function
shown in the diff now uses scaled spacing v(0.3 * scale * body-size). To
maintain consistency within the same section, update _labelled_divider() to
retrieve the scale factor using _spacing_scale_state.get() and apply it to both
vertical spacing calls, matching the pattern used in divider() where the
vertical spacing is multiplied by both the scale factor and body-size.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b54662c8-d827-4400-92dc-17a864e7b82e

📥 Commits

Reviewing files that changed from the base of the PR and between bb65c26 and 2b0b958.

⛔ Files ignored due to path filters (1)
  • examples/tests/density.pdf is excluded by !**/*.pdf
📒 Files selected for processing (3)
  • README.md
  • lib.typ
  • tests/density.typ

Comment thread lib.typ
Comment on lines +327 to 334
let scale = _spacing_scale_state.get()
v(0.3 * scale * body-size)
line(
length: 100%,
stroke: (paint: _divider_colour, thickness: 0.6pt, dash: "dashed"),
)
v(0.3 * body-size)
v(0.3 * scale * body-size)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Scale consistency gap: _labelled_divider() vertical spacing is still unscaled.

You scaled divider() here, but grouped-certificate separators still keep fixed density because _labelled_divider() uses v(0.3 * body-size) at Line 346 and Line 359. This makes density behavior inconsistent within the same section.

Suggested patch
 `#let` _labelled_divider(label) = context {
   let body-size = _body_size_state.get()
+  let scale = _spacing_scale_state.get()
   let stroke = (paint: _divider_colour, thickness: 0.6pt, dash: "dashed")
-  v(0.3 * body-size)
+  v(0.3 * scale * body-size)
   pad(left: 0.6 * body-size, grid(
     columns: (1.3em, auto, 1fr),
     column-gutter: 0.5 * body-size,
     align: horizon,
@@
     line(length: 100%, stroke: stroke),
   ))
-  v(0.3 * body-size)
+  v(0.3 * scale * body-size)
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib.typ` around lines 327 - 334, The _labelled_divider() function at lines
346 and 359 uses unscaled vertical spacing v(0.3 * body-size), while the
divider() function shown in the diff now uses scaled spacing v(0.3 * scale *
body-size). To maintain consistency within the same section, update
_labelled_divider() to retrieve the scale factor using
_spacing_scale_state.get() and apply it to both vertical spacing calls, matching
the pattern used in divider() where the vertical spacing is multiplied by both
the scale factor and body-size.

@smur89 smur89 force-pushed the feat/issue-50-density-preset branch from 2b0b958 to 1108dcb Compare June 14, 2026 11:09
@smur89 smur89 force-pushed the feat/issue-50-density-preset branch from b1e3979 to 2d7a59b Compare June 14, 2026 13:14

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib.typ`:
- Around line 1153-1158: The block element wrapping the project description uses
a hardcoded `0.6em` value for the below spacing, which ignores the density-aware
spacing model used in other parts of the code like the `_experience` and
`_education` functions. Replace the fixed `0.6em` value in the `block(below:
0.6em, emph(description))` call with a variable or expression that respects the
compact/spacious density settings, matching the spacing approach used
consistently throughout the document for similar layout elements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f978eec6-8b71-46e5-a3a6-8fdc5431a8cb

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0b958 and 2d7a59b.

⛔ Files ignored due to path filters (2)
  • examples/preview.png is excluded by !**/*.png
  • examples/tests/density.pdf is excluded by !**/*.pdf
📒 Files selected for processing (3)
  • README.md
  • lib.typ
  • tests/density.typ

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib.typ`:
- Around line 1153-1158: The block element wrapping the project description uses
a hardcoded `0.6em` value for the below spacing, which ignores the density-aware
spacing model used in other parts of the code like the `_experience` and
`_education` functions. Replace the fixed `0.6em` value in the `block(below:
0.6em, emph(description))` call with a variable or expression that respects the
compact/spacious density settings, matching the spacing approach used
consistently throughout the document for similar layout elements.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f978eec6-8b71-46e5-a3a6-8fdc5431a8cb

📥 Commits

Reviewing files that changed from the base of the PR and between 2b0b958 and 2d7a59b.

⛔ Files ignored due to path filters (2)
  • examples/preview.png is excluded by !**/*.png
  • examples/tests/density.pdf is excluded by !**/*.pdf
📒 Files selected for processing (3)
  • README.md
  • lib.typ
  • tests/density.typ
🛑 Comments failed to post (1)
lib.typ (1)

1153-1158: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Scale the project description gap.

Line 1157 still uses a fixed 0.6em, so compact/spacious density won't affect project descriptions. This is a small but visible gap in the new spacing model.

♻️ Proposed fix
-      block(below: 0.6em, emph(description))
+      context {
+        let scale = _spacing_scale_state.get()
+        block(below: 0.6 * scale * 1em, emph(description))
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

      // Wrapped in a block so the gap to the term row below matches
      // the institution-line → term spacing in `_experience` /
      // `_education`; using a bare `linebreak()` here leaves no
      // paragraph spacing.
      context {
        let scale = _spacing_scale_state.get()
        block(below: 0.6 * scale * 1em, emph(description))
      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib.typ` around lines 1153 - 1158, The block element wrapping the project
description uses a hardcoded `0.6em` value for the below spacing, which ignores
the density-aware spacing model used in other parts of the code like the
`_experience` and `_education` functions. Replace the fixed `0.6em` value in the
`block(below: 0.6em, emph(description))` call with a variable or expression that
respects the compact/spacious density settings, matching the spacing approach
used consistently throughout the document for similar layout elements.

@smur89

smur89 commented Jun 14, 2026

Copy link
Copy Markdown
Owner Author

Superseded by #127 — rebuilt against the post-refactor module layout, plus a latent fix in sections/projects.typ surfaced during the /review pass (unscaled 0.6em that would have broken the density contract). Leaving open for your review/close.

@smur89 smur89 closed this Jun 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: density preset (compact / comfortable / spacious)

1 participant