Skip to content

feat(cards,modals): Chart, Table options, tooltips, Card width, DateInput/NumberInput, dispatch_action (#202) - #253

Merged
patrick-chinchill merged 2 commits into
mainfrom
sync/4.41-c10
Sep 30, 2026
Merged

patrick-chinchill merged 2 commits into
mainfrom
sync/4.41-c10

Conversation

@patrick-chinchill

@patrick-chinchill patrick-chinchill commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This PR ports the platform-neutral card and modal builder additions from chat@4.34–4.41. It covers only the builders, TypedDicts, fallback text and exports. Adapters render the new fields in #212 (Slack) and #220 (Teams).

  • cards.py
    • Chart(title=, chart=) builder and chart alias.
    • New types: ChartSegment, ChartDataPoint, ChartSeries, PieChartDefinition, SeriesChartDefinition (x_label / y_label), ChartDefinition and ChartElement. ChartElement is added to CardChild.
    • chart_element_to_fallback_text() renders the title followed by an ASCII table.
      • Pie charts get Label / Value rows.
      • Series charts get one row per category and one column per series. Each point is looked up by category label, and a missing point is an empty cell.
    • The fallback text is wired into card_child_to_fallback_text and shared/card_utils.py::_child_to_fallback_text.
    • Table() gains caption, page_size, widths, vertical_align and grid_lines, plus grid_style, with the new TableVerticalAlignment and TableGridStyle types.
    • Button() / LinkButton() gain tooltip. Card() gains width (CardWidth).
  • modals.py
    • New DateInput() / NumberInput() builders, their TypedDicts and the date_input / number_input aliases. Both types are added to VALID_MODAL_CHILD_TYPES and ModalChild.
    • dispatch_action on Select() / RadioSelect().
  • chat_sdk/__init__.py: every new builder, alias and type is exported and listed in __all__.

Upstream commits mapped

Upstream Release Ported here
4717a384 (#696) chat@4.34.0 Core slice: Chart* types, Chart(), chartElementToFallbackText, Table caption / pageSize
0153a39f (#757) chat@4.36.0 DateInput / NumberInput elements and builders, valid modal children
4a0b5c0c (#895) chat@4.40.0 CardWidth, Card.width, tooltip on Button / LinkButton (the callback-URL half belongs to #194)
84219537 (#906) chat@4.41.0 Core slice: TableVerticalAlignment, TableGridStyle, widths / verticalAlign / gridLines / gridStyle
ad904325 (#952) chat@4.41.0 Core slice: dispatchAction on Select / RadioSelect
929878b5 (#838) chat@4.39.0 N/A (JSX only). LinkButton(id=...) already exists. Recorded in the jsx-runtime row of docs/UPSTREAM_SYNC.md

Tests ported

Every upstream test name listed in the issue now exists:

  • tests/test_cards.py (11 tests)
    • Card: "creates a card with a width hint"
    • Button: "creates a button with a tooltip"
    • LinkButton: "creates a link button with a tooltip"
    • Table (4): "creates a table with caption and pageSize", "leaves caption and pageSize undefined when omitted", "carries the Teams-only rendering options", "leaves the rendering options undefined when omitted"
    • Chart (2): "creates a pie chart", "creates a line chart with series and categories"
    • Chart fallback text (2): "renders pie chart data as a labelled ASCII table", "renders series chart data with one column per series". These assert the exact output string, not just containment.
  • tests/test_modals.py
    • "preserves dispatchAction=%s", parametrized over [Select, RadioSelect] × [True, False, None]
    • DateInput (2 tests)
    • NumberInput (3 tests), including "should keep a zero initial value", which also checks min=0, max=0 and decimal=False
    • "should keep valid child types": the existing Python filter test was renamed and extended with DateInput / NumberInput, matching upstream's updated test.
  • Python-specific tests
    • Number formatting is parametrized over 13 cases: 45.0→45, 1.5, -0.0→0, 0.00001, 1e-7, 1e21→1e+21, 10**21, NaN, Infinity, and others.
    • A missing series point and a missing x_label render as empty cells.
    • card_to_fallback_text and the adapter-shared card_to_fallback_text both include the chart.
    • Root re-exports (tests/test_root_reexports.py).
  • Skipped (JSX only, documented): "should convert a DateInput/NumberInput react element", the fromReactModalElement copy of "preserves dispatchAction=%s", and the jsx-runtime tooltip/width cases.

Fidelity (--report-target at chat@4.41.1, scripts/fidelity_target.json regenerated):

Delta vs committed report (HEAD): missing 282 -> 265 (-17)
  packages/chat/src/cards.test.ts: 31 -> 20 (-11)
  packages/chat/src/modals.test.ts: 34 -> 28 (-6)

Two notes on the modals numbers:

  • They show -6 rather than -7 because the renamed test_valid_children_pass_through used to be fuzzy-matched to the unrelated JSX test "should pass through plain modal children", which now correctly reports as missing.
  • The report still lists [DateInput] / [NumberInput] "should create with required fields" / "should include optional fields" as missing. Those names are shared with TextInput / ExternalSelect, and the matcher counts names without regard to which describe block they belong to. The DateInput and NumberInput tests are ported; the remaining misses are the TextInput / ExternalSelect gaps tracked in Extend verify_test_fidelity.py MAPPING to cover all packages/chat/src/*.test.ts #78.

Strict at the pin: 733/733 (unchanged).

Validation

  • ruff check and ruff format: pass
  • audit_test_quality: 0 hard failures
  • --check-docs: pass
  • --strict at chat@4.31.0: pass
  • pytest: 5604 passed, 13 skipped (main baseline: 5561 passed)
  • pyrefly: 0 errors

Divergences

None are added to the non-parity table. Notes:

  • Number formatting in the chart fallback. Values go through _js_number_to_string, which implements ECMAScript Number::toString. The goal is to match upstream String(v) output ("Kit Kat | 45" for 45.0). I checked it against Node String() on 80,000 random doubles and found no mismatches. The only differences are that int values below 1e21 render exactly (JS rounds them above 2**53) and a None value renders as "". Other numeric types (Decimal from Postgres NUMERIC, Fraction, NumPy scalars) are converted to int / float first, so Decimal("45.00") renders "45". This is recorded in docs/UPSTREAM_SYNC.md under "Card and modal builders".
  • Omitted keys. Builders omit keys whose argument is None, where upstream sets them to undefined. This is the repo's standard convention (hazard fix: launch must-fix items — security, perf, docs #7), not a new divergence.

Consumer impact

The change is additive. With the new options unset, the output of Card(), Table(), Button(), LinkButton(), Select() and RadioSelect() is byte-identical to before; tests assert this for Table, Card, the tooltips and dispatch_action.

Closes #202
Part of #184

Merge gate

Reviewer findings (2 independent reviewers, 4 findings), all fixed in 4f294d2:

gpt-6-astra: 1 round, on 4f294d2. The verdict was clean: "No actionable regressions found within the documented core-only scope."

Bots: CodeRabbit was rate-limited and posted no review comments. There were no Gemini comments.

CI on 4f294d2: all green (Lint & Type Check, test 3.12 and 3.13, CodeQL).

Local validation: all green: ruff, audit (0 hard failures), --check-docs, --strict 733/733 at chat@4.31.0, pytest 5604 passed, pyrefly 0 errors. Fidelity: Delta vs committed report (HEAD): missing 265 -> 265 (+0). These are Python-only tests, and the total stays at 265 against chat@4.41.1.

…DateInput/NumberInput, dispatch_action (#202)

Core slice of upstream 4717a384 (chat@4.34.0), 0153a39f (chat@4.36.0),
4a0b5c0c (chat@4.40.0), 84219537 and ad904325 (chat@4.41.0):

- cards: Chart() + Chart* TypedDicts, chart_element_to_fallback_text
  (JS String() number formatting), chart case in card fallback text and
  shared card_utils; Table caption/page_size/widths/vertical_align/
  grid_lines/grid_style; Button/LinkButton tooltip; Card width.
- modals: DateInput/NumberInput children (+ VALID_MODAL_CHILD_TYPES,
  ModalChild); dispatch_action on Select/RadioSelect.
- Root exports, upstream-named tests, UPSTREAM_SYNC/CHANGELOG, and
  regenerated fidelity_target.json (282 -> 265 missing).

Additive only: unset options are omitted, so existing output is unchanged.

Part of #184
@coderabbitai

coderabbitai Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 3010b1aa-18dc-4b64-abd9-e6da27828e01

📥 Commits

Reviewing files that changed from the base of the PR and between 4817dc0 and 4f294d2.

📒 Files selected for processing (10)
  • CHANGELOG.md
  • docs/UPSTREAM_SYNC.md
  • scripts/fidelity_target.json
  • src/chat_sdk/__init__.py
  • src/chat_sdk/cards.py
  • src/chat_sdk/modals.py
  • src/chat_sdk/shared/card_utils.py
  • tests/test_cards.py
  • tests/test_modals.py
  • tests/test_root_reexports.py

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.

@patrick-chinchill
patrick-chinchill marked this pull request as ready for review September 30, 2026 10:37
@patrick-chinchill

Copy link
Copy Markdown
Collaborator Author

Merge gate: CI green (Analyze (actions), Analyze (python), CodeQL, Lint & Type Check, test (3.12), test (3.13)); local Codex review (gpt-6-astra, xhigh, --base origin/main) on 4f294d2: "No actionable regressions found within the documented core-only scope. Targeted card, modal, and export tests passed, along with type checking, linting, and strict upstream test-fidelity verification."; 1 recorded astra round on the final HEAD (earlier review feedback addressed in 4f294d2); origin/main already an ancestor, so no re-merge was needed; CodeRabbit rate-limited (no review posted), no human reviews. Merging with --admin (Protect Main requires a code-owner approval).

@patrick-chinchill
patrick-chinchill merged commit 1d0eb49 into main Sep 30, 2026
8 checks passed
@patrick-chinchill
patrick-chinchill deleted the sync/4.41-c10 branch September 30, 2026 10:43
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.

[4.41/C10] Cards & modals core: Chart, Table options, Button tooltip, Card width, DateInput/NumberInput, select change events

1 participant