Skip to content

#235 — given column-header tooltips restored + model-badge tooltip styling aligned - #236

Merged
cmbays merged 1 commit into
mainfrom
adapters-235-given-tooltips
Jun 11, 2026
Merged

cmbays merged 1 commit into
mainfrom
adapters-235-given-tooltips

Conversation

@cmbays

@cmbays cmbays commented Jun 11, 2026 •

Copy link
Copy Markdown
Contributor

Root cause

The JS binder never regressed — the given-side payload never carried column metadata for non-model given sources. Bisecting the suspects (#201/#217 layout rework, #230, #234) against live DOM probes of the goldens at #166 (cba790f), #230 (f86b68e), and main (65cac5f) shows identical behavior at every commit: the decorateColHeader/#col-tooltip binder fires correctly for any given whose payload carries column_meta. What was broken is the (b) arm — the payload side, since the feature shipped in #165/#166: build_test_payload's given arm resolved only ref()-to-model (via resolve_target_model, which filters resource_type == "model") and this. Two whole classes of given input therefore never received column metadata:

  • seed-ref givens — the committed jaffle-shop fixture's ref('raw_customers') is exactly this wire shape; dbt's ref() resolves over the refable set (models, seeds, snapshots)
  • source('a','b') givens — the domain SourceNode didn't even ingest the source columns block, although both engines emit it (fusion ManifestSource.columns via serialize_dbt_columns, dbt-schemas manifest/manifest_nodes.rs @ 9977b6cb; verified on the committed playground fixture's synthea_raw.patients.Id description)

The review surfaces for PR #230 happened to consist entirely of such givens (jaffle's seed given; diff-showcase's only changed test, whose given fixture columns are undeclared on the input model) — so every given header was bare while every expected header tooltipped, reading as a one-sided regression.

RED evidence (unmodified main, 65cac5f):

  • 2 new render payload tests fail: build_test_payload_attaches_seed_column_meta_for_a_seed_ref_given, build_test_payload_attaches_source_column_meta_for_a_source_given (assertion left == right failed — column_meta empty)
  • DOM probe of a main-built report (seed + source + model givens): seed given 0/2 decorated headers, source given 0/2; expected headers decorated. Model tip anatomy: .dt-row/.dt-key ×2, .ct-test/.ct-key/.ct-val ×0
  • New headless guards assert exactly these facts and pass only with the fix

Before / after

Surface Before After
Seed-ref given header (described + tested column) no trigger, no tooltip hover and keyboard focus reveal description + test chips (the #146/#161 contract the th trigger already carries)
source(...) given header no trigger ever (source columns not even ingested) source column descriptions + source-attached column tests tooltip; visible in the regenerated playground golden (synthea_raw.patients → Id — "Unique patient identifier (UUID)")
Model-ref given header worked unchanged
Model-name badge tip (given gt-model pill + expected badge) model tests rendered in the shelf card's .dt-row/.dt-key/.dt-val dress — metrics/spacing diverged from the column tooltip test rows ride the column tooltip's own .ct-tests/.ct-test/.ct-key/.ct-vals/.ct-val anatomy via a shared ctTestHtml builder (no parallel chip system); test names keep the readable-on-dark color-mix(in oklab, var(--accent) 60%, white) accent treatment

Honest degrade

A given column whose source genuinely lacks per-column metadata (undeclared column, metadata-less seed, csv/sql given without declarations) renders no trigger at all — no has-col-meta class, and no empty bubble can open. Pinned by given_header_honest_degrade_metadata_less_given_has_no_triggers plus inline assertions on the undocumented/undescribed columns in the seed/source test. (DataTables still gives orderable headers keyboard focus for sorting — the degrade contract is no-tooltip-affordance, not non-focusability.)

Scope guard (#233)

.col-tooltip rules untouched — the .col-tooltip .ct-key pass-1→pass-2 color fix and the .ct-test gap value remain #233's lane. This PR only adds the model-scoped .model-tooltip .ct-key color-mix override (same specificity, later in file) and retires the now-dead .model-tooltip .mt-mtests/.dt-key/.dt-val rules. The shelf card keeps its light-surface .dt-* chips.

Changes

  • src/domain/manifest.rs — SourceNode gains column_descriptions (tolerant #[serde(default)], with_column_descriptions builder — the Node precedent; POD-only, std+serde)
  • src/adapters/manifest.rs — WireSource parses the columns map (reusing WireColumn); empty-string unset descriptions dropped (the feature: column-header tooltips on unit-test tables — authored descriptions + column-level data tests #165 rule)
  • src/adapters/render.rs — resolve_given_ref_node (givens resolve over model | seed | snapshot, deterministic under leaf-name collision), column_meta_for_source, shared attached_column_tests; build_test_payload given arm wires this → ref → source
  • templates/interaction.js — shared ctTestHtml builder (column tooltip markup byte-identical); showModelTip model tests render .ct-tests/.ct-test rows
  • templates/report.css — .model-tooltip .ct-key accent override; dead .model-tooltip .mt-mtests/.dt-* rules retired
  • tests/headless_toggle.rs — 3 new guards + the feature: design-2 integration PR-5 — rich hover cards: ref()/Expected model pills, format-badge fixture reconstruction, overrides badge, info tips #202 model-tip pin updated to the new anatomy
  • Goldens regenerated with the exact CI commands (jaffle-shop, playground, diff-showcase, explore); git diff --text -- examples/ audited — only this lane's engine deltas (the shared CSS/JS blocks + the playground/explore payload gaining the source-given column_meta)
  • tests/snapshots/render_integration__rendered_chrome_jaffle_shop.snap rebaselined (embeds the engine CSS/JS blocks)

Guards

Gates (direct, by exit code)

cargo fmt --check 0 · cargo clippy --all-targets --locked -- -D warnings 0 · cargo nextest run 1228 passed · cargo test --test bdd 160 scenarios / 1032 steps passed · cargo test --test headless_zero_egress --locked -- --ignored 10 passed · cargo test --test headless_toggle --locked -- --ignored 53 passed · RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --locked 0 · cargo deny check ok

Closes #235

🤖 Generated with Claude Code


Open in Stage

Summary by CodeRabbit

  • New Features

    • Source and seed column descriptions now display in tooltips
    • Column tests for seed and source references are now properly surfaced
  • Improvements

    • Test styling unified across model and column tooltips for consistent visual presentation

…ge tooltip anatomy (#235)

Concern 1 — given column-header tooltips: the JS binder never regressed;
the given-side column_meta payload (#165/#166) only ever resolved
ref()-to-MODEL and 'this' inputs. A seed-ref given (the committed
jaffle-shop ref('raw_customers') wire shape) and a source('a','b') given
carried NO column metadata, so their headers offered no tooltip while
the expected table's did — the symptom found reviewing PR #230. Fix:

- domain: SourceNode ingests authored per-column descriptions
  (with_column_descriptions builder, the Node precedent; fusion
  ManifestSource.columns via serialize_dbt_columns, dbt-schemas
  manifest_nodes.rs @ 9977b6cb, verified on the committed playground
  fixture's synthea_raw.patients.Id)
- adapter: WireSource parses the columns map (empty-string unset
  descriptions dropped, the #165 rule)
- render: resolve_given_ref_node resolves givens over dbt's refable set
  (model | seed | snapshot); column_meta_for_source merges source column
  descriptions + column-scoped tests attached to the source node; shared
  attached_column_tests keeps both arms deterministic
- honest degrade preserved: a metadata-less given column renders NO
  trigger — never an empty bubble

Concern 2 — model-badge tooltip anatomy: the model-ref tip's test rows
now ride the COLUMN tooltip's own .ct-test/.ct-key/.ct-vals anatomy via
the shared ctTestHtml builder (never a parallel chip system); test names
keep the readable-on-dark color-mix accent treatment; the
.mt-mtests/.dt-* dress is retired inside the tip (the shelf card keeps
its light-surface .dt-* chips). The .col-tooltip .ct-key color stays
#233's lane — untouched.

Guards: 3 new headless tests (seed+source given tooltips on hover AND
focus per the #146/#161 contract, honest-degrade no-empty-bubble, model
tip chip anatomy + computed accent color), 3 new render payload tests,
domain/adapter ingestion tests; the #202 model-tip pin updated to the
new anatomy. Goldens regenerated (the playground source given now ships
a real Id tooltip); insta chrome snapshot rebaselined.

Closes #235

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ghost

ghost commented Jun 11, 2026

Copy link
Copy Markdown

Ready to review this PR? Stage has broken it down into 6 individual chapters for you:

Title
1 Ingest source column descriptions into domain
2 Resolve column metadata for all given types
3 Unify model and column tooltip anatomy
4 Verify tooltip fixes with headless tests
5 Regenerate example reports with fixes
6 Other changes
Open in Stage

Chapters generated by Stage for commit 92c4cb6 on Jun 11, 2026 5:57pm UTC.

@github-actions

Copy link
Copy Markdown
Contributor

📄 Rendered report preview

All golden examples regenerated cleanly.

🟡 Golden examples

Committed to examples/ and byte-identity gated — the canonical reports contributors and consumers browse. Stable across PRs.

Report View Download
playground-report.html ▶ Open ↗ ⬇ Download
diff-showcase-report.html ▶ Open ↗ ⬇ Download
jaffle-shop-report.html ▶ Open ↗ ⬇ Download

🐶 Live dogfood preview

This PR doesn't touch dbt-project/, so there's no live dogfood preview.

▶ Open ↗ opens the report in your browser in one click —
published to this repo's GitHub Pages under /pr-236/.
⬇ Download fetches the same self-contained HTML as a workflow
artifact (auth-gated; works fully offline). Either way the report
makes zero external resource requests.

The Pages preview may take ~1 min to update after this comment
posts. On PRs from forks the Open link is unavailable (read-only
token) — use Download.

Alternative: GitHub CLI
# gh CLI >= 2.63 extracts into ./report-preview-playground/.
gh run download 27366841747 -R breezy-bays-labs/cute-dbt -n report-preview-playground
open report-preview-playground/playground-report.html

Posted by report-preview.yml for 92c4cb6397787cf77be445e8d208258e3cec0d64. Affordance only — never blocks merge.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request implements support for displaying column-header tooltips (descriptions and attached data tests) for seed and source inputs in unit-test given tables (addressing cute-dbt#235). It updates the manifest parser to extract source column descriptions, refactors the test payload builder to resolve column metadata for seeds, snapshots, and sources, and unifies the visual anatomy of model-level tests in tooltips with column-level tests using a shared JS builder. Comprehensive unit and headless integration tests have been added to verify these changes. No review comments were provided, so there is no feedback to address.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

PR #236 fixes given-table column-header tooltip regression (dropped in a prior change) and unifies model-badge tooltip styling with the column tooltip anatomy. It adds source column description support to the domain, extracts descriptions from the dbt manifest, refactors given metadata resolution to handle seeds and sources alongside models, and replaces scattered test-chip rendering with a shared ctTestHtml helper using consistent .ct-* CSS anatomy.

Changes

Feature #235: Given Column Tooltips and Unified Tooltip Styling

Layer / File(s) Summary
Source column descriptions domain contract
src/domain/manifest.rs
SourceNode gains a column_descriptions: BTreeMap<String, String> field with builder (with_column_descriptions) and accessor (column_descriptions()) methods; unit tests verify empty default, builder attachment, and backward-compatible deserialization.
Source column description ingestion from manifest
src/adapters/manifest.rs
WireSource deserializes a columns map; into_domain filters each column's description to non-empty strings and passes them to SourceNode via with_column_descriptions; unit test validates extraction and omission of empty/missing descriptions.
Given column metadata resolution for models, seeds, and sources
src/adapters/render.rs
Introduces attached_column_tests helper to deterministically collect column-scoped generic tests (reused for both models and sources); adds resolve_given_ref_node to resolve ref('NAME') across full refable set (models, seeds, snapshots) by matching leaf segment and breaking ties via smallest node id; refactors build_test_payload to branch on given type (this/ref/source) and merge descriptions + tests for column metadata; unit tests cover seed-ref and source-given resolution, including honest degrade for metadata-less sources.
Unified test-chip rendering with shared ctTestHtml helper
templates/interaction.js, templates/report.css, examples/diff-showcase-report.html, examples/jaffle-shop-report.html
Introduces shared ctTestHtml(t) helper that renders one test row as .ct-test with .ct-key name and .ct-vals chips (from t.values or comma-split t.detail); updates model-ref and column tooltips to use the helper; replaces model-tooltip CSS to override .model-tooltip .ct-key color (accent treatment), removing retired .mt-mtests/.dt-key styling. Applied identically in both template files and example reports.
Headless test coverage for given-side and model-badge tooltips
tests/headless_toggle.rs
Adds helpers to render reports with sources and construct seed nodes; comprehensive headless tests verify given-column header tooltips for seed-ref and source givens (presence, content, keyboard focus, honest degrade for metadata-less columns); validates model-badge tooltip anatomy (.ct-tests .ct-test rows, .ct-key/.ct-vals .ct-val content, accent color via computed styles, no legacy .dt-*/.mt-mtests remnants).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

The PR spans domain, adapter, template, and test layers with moderate logic density. The core logic changes (given metadata resolution, manifest ingestion) are straightforward but require understanding the new field threading and reference resolution strategy. The refactoring of test-chip rendering is mostly mechanical duplication removal. The headless tests are comprehensive but repetitive assertions. Low risk of unintended side effects due to structured test coverage.

Possibly related PRs

  • breezy-bays-labs/cute-dbt#188: Introduced the client-side tooltip contract update in templates/interaction.js and templates/report.css; this PR (#236) aligns the model-badge tooltip styling to the column tooltip's .ct-* anatomy established in #188.

🐰 Hop, hop! The givens now have tales to tell,
Their column tips shine in a unified spell,
Badges and chips dance in accent-hued grace,
While tooltips degrade with honest-faced space. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly references issue #235 and clearly summarizes the two main changes: restoring given column-header tooltips and aligning model-badge tooltip styling with column tooltip anatomy.
Linked Issues check ✅ Passed All four acceptance criteria from #235 are met: given-header tooltips restored with proper styling, model-badge tooltip anatomy aligned to column tooltip, root cause identified (payload missing column metadata for non-model givens), headless guards added, and goldens regenerated.
Out of Scope Changes check ✅ Passed All changes are tightly scoped to #235: domain/adapter updates for source column descriptions, render layer resolution for seeds/sources, template unification of test rendering via ctTestHtml, and CSS styling fixes. No unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch adapters-235-given-tooltips

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ast-grep (0.43.0)
examples/diff-showcase-report.html
examples/jaffle-shop-report.html

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cmbays
cmbays merged commit 74adbad into main Jun 11, 2026
32 of 33 checks passed
@cmbays
cmbays deleted the adapters-235-given-tooltips branch June 11, 2026 18:01
github-actions Bot added a commit that referenced this pull request Jun 11, 2026
cmbays added a commit that referenced this pull request Jun 11, 2026
…ps, covered-by contrast, overrides-badge clip, baseline banner (#244)

* fix(adapters): #240 — review-2 render defects: tooltip overflow, given-header tooltips, covered-by contrast, overrides-badge clip, baseline banner

Five founder-reported defects from the PR #239 review (issue #240):

A — long mono tokens (dbt_expectations.expect_table_row_count_to_be_between)
    painted 55px past the model tip's painted background: overflow-wrap
    on the .col-tooltip shell + wrapping .ct-val chips.
B — given column headers with no manifest metadata were silently
    hover-dead (third report): EVERY fixture header is a trigger now;
    metadata-less ones reveal a truthful fallback naming the owning node
    (never an empty bubble — the honesty invariant strengthens).
C — .finding-covered-by code rode Sakura's light #f1f1f1 code bg at
    ~1.2:1 on dark themes: themed var(--bg-alt)/var(--text) re-skin
    (5.9–14.8:1 measured across all 8 themes).
D — .ov-tooltip nowrap rows painted long override values past the bubble
    and the viewport edge: rows flex-wrap + overflow-wrap, singleton
    width capped at calc(100vw - 16px), positionTipNear clamps against
    documentElement.clientWidth (scrollbar-safe).
E — code.diff-scope-baseline same root cause as C, same fix.

Goldens regenerated (jaffle-shop, playground, diff-showcase) — every
hunk is the embedded template change; snapshot updated likewise.

Closes #240

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test: #240 — universal hover-parity guard + containment + AA pins (the guard-methodology fix)

Why #166/#236 validations passed while the founder's experience stayed
broken: they asserted tooltip reveal on columns KNOWN to carry manifest
metadata (existential), while the founder hovered undeclared columns —
hover-dead by the old design, outside every assertion universe. The new
guards quantify universally and pin geometry:

- fixture_header_tooltips_universal_after_view_toggle_and_sort: EVERY
  visible given/expected header must reveal a non-empty bubble on a real
  mouseover — initial render, after a real Diff→File toggle, after a
  real column sort, and after the round-trip (the #145/#146 wipe class).
- model_tip_long_test_name_wraps_inside_bubble: content containment
  (scrollWidth ≤ clientWidth + 1; no descendant past the bubble edge).
- ov_tip_long_value_contained_in_bubble_and_viewport_at_right_edge:
  long-override containment + viewport containment at a true right-edge
  trigger geometry.
- covered_by_test_ids_meet_aa_contrast_on_every_theme +
  baseline_banner_path_meets_aa_contrast_on_every_theme: the #206/#227/
  #231/#233 effective-backdrop AA family extended to defects C/E,
  all 8 themes (RED at 1.2:1 pre-fix).

Three #235-era pins are deliberately rewritten to the new contract
(metadata-less headers are fallback triggers, never dead): the no-EMPTY-
bubble honesty invariant is preserved and strengthened.

All five new guards captured RED against the unfixed templates (stash-
verified) and GREEN after the fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs: dbt-project README touch — render the live dbt-project preview row for #240 validation

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(adapters): #240 — givenOwnerLabel accepts double-quoted ref()/source() inputs (PR #244 review)

dbt accepts both quote styles in a given's input:, and dbt-fusion ships
the authored string VERBATIM — a ref("stg_payments") given compiles
onto the manifest wire double-quoted, unnormalized (verified against a
real fusion 2.0.0-preview.177 compile of the dogfood project). The
owner-label regexes behind the metadata-less fallback bubble were
single-quote-only, degrading double-quoted inputs to the raw-string
fallback. Quote-class + backreference now accepts both styles (mixed
quotes stay unparsed -> truthful raw-input fallback).

New headless guard given_owner_label_accepts_double_quoted_ref_and_source
(RED without the regex fix, stash-verified). Goldens + chrome snapshot
regenerated; every hunk is the embedded regex/comment change.

The repo's Rust-side parsers (parse_ref_name / parse_source_ref) share
the single-quote-only gap pre-dating this PR; tracked separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(adapters): #240 — latte 'Covered by' label AA (4.37 -> 5.53) + sweep transition hazard (PR #244 verification residual)

The covered-by CODE pills pass AA on all 8 themes, but the 'Covered by '
prefix label (.finding-covered-by .f-label, 11.88px weight-400 so the
4.5 floor applies) rode the verbatim latte --text-muted: #6c6f85 on the
finding row's #eff1f5 fill = 4.37:1. The established #227/#231 deepened
stand-in extends to this label via the narrowest token override
(:root[data-theme=latte] .finding-covered-by .f-label
{ --text-muted: #5c5f77 }) — re-measured empirically on the actual
finding-row backdrop: 5.53:1. rosepine (4.56) stays verbatim; the latte
theme block stays pinned.

Guard changes (the existential-vs-universal lesson applied to AA sweeps):
- the covered-by sweep now measures EVERY text run in the quoted line
  (code pills AND the f-label prefix), tags entries by element kind, and
  asserts the label run is present — stash-verified RED at latte 4.37
  without the override, GREEN at 5.53 with it;
- both #240 sweeps (covered-by + baseline path) inject
  '* { transition: none !important }' for the sweep's duration: body
  transitions background/color over 120ms, so an instant setAttribute +
  getComputedStyle read can land mid-transition (verifier-observed false
  readings).

Goldens + chrome snapshot regenerated; every hunk is the embedded CSS
override/comment.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(adapters): #240 — trim whitespace-only column descriptions + post-flip top clamp (PR #244 CodeRabbit threads)

Thread 1 (applied): a whitespace-only authored description ('   ')
passed the hasMeta gate untrimmed, suppressing the cute-dbt#240
truthful fallback and opening an effectively-empty bubble on a
description-only column — the exact state the never-empty-bubble
contract forbids. decorateColHeader (the single writer of
data-col-desc) now trims once; aria-label, the fallback arm, and the
bubble all read the trimmed value. New headless guard
whitespace_only_description_degrades_to_truthful_fallback
(stash-verified RED untrimmed, GREEN trimmed).

Thread 2 (applied): positionTipNear gains the post-flip top clamp
(top < 8 -> 8) — at pathological viewport heights the flipped position
(trigger top - bubble height) goes negative, pushing the bubble above
the screen. Mirrors the horizontal clamp; resolves the clamp half of
cute-dbt#246 (the fmt-tooltip overflow half stays there). The existing
right-edge containment guard now also pins top >= 0.

Goldens + chrome snapshot regenerated; every hunk is the embedded
trim/clamp change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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.

bug: given column-header tooltips regressed + model-badge tooltip styling diverges from column tooltip

1 participant