Skip to content

feat(plugin-table): add tokens to the reference Table#2951

Merged
christianhg merged 1 commit into
mainfrom
table-tokens-prop
Jul 7, 2026
Merged

feat(plugin-table): add tokens to the reference Table#2951
christianhg merged 1 commit into
mainfrom
table-tokens-prop

Conversation

@christianhg

Copy link
Copy Markdown
Member

The plugin themes through --pt-plugin-table-* custom properties, which works cleanly when the host's theme is CSS: declare overrides in a stylesheet and the zero-specificity defaults yield. But when the theme exists only as a runtime object (a design system resolving colors, fonts, and radii in JavaScript), the host has to write the properties into the DOM itself, and every scope it owns fails one way or another: a wrapper around the editor cannot reach the chrome that portals out of the editor's subtree (the trash chips, the built-in menu's dropdown), and a shared global scope like documentElement makes concurrent tables fight over one set of values, with the last unmount's cleanup stripping properties a surviving table still needs.

Table now accepts the values through its own API:

render: (props) => (
  <Table
    {...props}
    tokens={{
      "--pt-plugin-table-accent": theme.focusRing,
      "--pt-plugin-table-bg": theme.bg,
      // ...any subset; the stylesheet defaults cover the rest
    }}
  />
)

The record's keys are the documented token names, so the README's Theming table remains the single contract and the prop is a second delivery route for the same vocabulary, not a second vocabulary. The plugin applies the values inline to the roots it owns: the in-tree chrome wrapper (covering the table, handles, lanes, dots, and drag ghost by inheritance) and each portal layer (the trash layer and the built-in menu's dropdown carry their own copy, since portals escape the in-tree scope). Inline properties win over the stylesheet defaults exactly where a value is passed and nowhere else, and each table instance carries its own set, so two tables with different tokens theme independently by construction.

This is the same host-facing shape widgets with their own theming systems conventionally expose: live theme values in through the widget's API, applied by the widget to surfaces only it knows about. The application mechanism is inherited custom properties rather than generated stylesheets because the plugin's styling is one static stylesheet already parameterized by these properties, so no rule generation is needed, only values.

The pin sets --pt-plugin-table-bg and --pt-plugin-table-trash-bg through the prop and asserts computed colors in both worlds: a cell resolving the value by inheritance through the in-tree root, and the trash chip resolving it from its portaled layer's own copy (summoned by selecting a row via keyboard, so the scenario also exercises the portal path end to end).

The theming custom properties could only arrive through stylesheets,
which leaves hosts whose theme exists solely as a runtime object to
write the properties into the DOM themselves. Any scope such a host
owns fails one way or another: a wrapper around the editor cannot
reach the chrome that portals out of it, and a shared global scope
makes concurrent tables fight over one set of values.

`Table` now takes an optional `tokens` record keyed by the documented
`--pt-plugin-table-*` names and applies the values inline to the
roots it owns: the in-tree chrome wrapper, the trash layer, and the
built-in menu's dropdown. Inline values win over the stylesheet's
zero-specificity defaults exactly where they're passed, and each
table instance carries its own set. `TableTokens` ships from `./ui`.

The pin sets `--pt-plugin-table-bg` and `--pt-plugin-table-trash-bg`
through the prop and asserts computed colors on a cell (inheritance
through the in-tree root) and on the trash chip (a portaled layer
carrying its own copy).
@vercel

vercel Bot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
portable-text-editor-documentation Ready Ready Preview, Comment Jul 7, 2026 3:08pm
portable-text-example-basic Ready Ready Preview, Comment Jul 7, 2026 3:08pm
portable-text-playground Ready Ready Preview, Comment Jul 7, 2026 3:08pm

Request Review

@changeset-bot

changeset-bot Bot commented Jul 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: b81a361

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@portabletext/plugin-table Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Stats — @portabletext/editor

Compared against main (9dbc50f5)

@portabletext/editor

Metric Value vs main (9dbc50f)
Internal (raw) 803.0 KB -
Internal (gzip) 153.7 KB -
Bundled (raw) 1.41 MB -
Bundled (gzip) 317.9 KB -
Import time 96ms +0ms, +0.0%

@portabletext/editor/behaviors

Metric Value vs main (9dbc50f)
Internal (raw) 467 B -
Internal (gzip) 207 B -
Bundled (raw) 424 B -
Bundled (gzip) 171 B -
Import time 2ms +0ms, +1.4%

@portabletext/editor/plugins

Metric Value vs main (9dbc50f)
Internal (raw) 2.7 KB -
Internal (gzip) 894 B -
Bundled (raw) 2.5 KB -
Bundled (gzip) 827 B -
Import time 7ms +0ms, +0.1%

@portabletext/editor/selectors

Metric Value vs main (9dbc50f)
Internal (raw) 81.2 KB -
Internal (gzip) 14.9 KB -
Bundled (raw) 76.7 KB -
Bundled (gzip) 13.8 KB -
Import time 8ms -0ms, -1.2%

@portabletext/editor/traversal

Metric Value vs main (9dbc50f)
Internal (raw) 28.1 KB -
Internal (gzip) 5.6 KB -
Bundled (raw) 27.9 KB -
Bundled (gzip) 5.5 KB -
Import time 6ms +0ms, +0.3%

@portabletext/editor/utils

Metric Value vs main (9dbc50f)
Internal (raw) 29.7 KB -
Internal (gzip) 6.2 KB -
Bundled (raw) 27.1 KB -
Bundled (gzip) 5.8 KB -
Import time 6ms -0ms, -0.9%

🗺️ . · ./behaviors · ./plugins · ./selectors · ./traversal · ./utils · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

📦 Bundle Stats — @portabletext/markdown

Compared against main (9dbc50f5)

Metric Value vs main (9dbc50f)
Internal (raw) 53.8 KB -
Internal (gzip) 9.8 KB -
Bundled (raw) 348.9 KB -
Bundled (gzip) 96.3 KB -
Import time 38ms +0ms, +1.3%

🗺️ View treemap · Artifacts

Details
  • Import time regressions over 10% are flagged with ⚠️
  • Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.

@christianhg christianhg marked this pull request as ready for review July 7, 2026 15:14
@christianhg christianhg merged commit ede35c4 into main Jul 7, 2026
17 checks passed
@christianhg christianhg deleted the table-tokens-prop branch July 7, 2026 15:15
@ecoscript ecoscript Bot mentioned this pull request Jul 7, 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.

1 participant