fix(ui): scope tailwind preflight to [data-dg-agent] via plugin#27
Merged
lukeocodes merged 1 commit intomainfrom May 6, 2026
Merged
fix(ui): scope tailwind preflight to [data-dg-agent] via plugin#27lukeocodes merged 1 commit intomainfrom
lukeocodes merged 1 commit intomainfrom
Conversation
The full `@import "tailwindcss";` shortcut shipped global preflight rules with universal selectors (`*, ::before, ::after`, `html`, `body`) that bled into every host page that loaded `@deepgram/ui` or `@deepgram/agents-widget`. Symptoms reported in deepgram/deepgram-docs included content width collapse on every non-demo page after the widget bundle finished loading. Fix: split the Tailwind import into theme + utilities (granular, no preflight) and use `tailwindcss-scoped-preflight` to re-introduce preflight scoped to `[data-dg-agent]`. The plugin's `inside` strategy rewrites every preflight rule with `:where([data-dg-agent], [data-dg-agent] *)` so the reset only applies to widget descendants. Verified end-to-end through @deepgram/agents-widget UMD build: before: 0 `:where([data-dg-agent]` matches, full unscoped preflight after: 76 `:where([data-dg-agent]` matches, 0 unscoped preflight Bundle size grew ~3KB after gzip from the added scope selectors, which is acceptable to stop the host-page regression. Also moved `tailwindcss-scoped-preflight` from devDependencies to dependencies so consumers get the plugin transitively when they install @deepgram/ui. The plugin only runs at the consumer's Tailwind build time, so it must be resolvable from the consumer's node_modules. Bonus cleanup: extended tokens that were previously on `:root` are now scoped to `[data-dg-agent]` so they do not leak to the host page either. `--primary-hover`, `--msg-user-bg`, `--dg-va-primary`, and `--dg-va-border` are widget-internal and should never have been on `:root`.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
lukeocodes
added a commit
to deepgram/agent
that referenced
this pull request
May 6, 2026
#48) ## Why `@deepgram/ui@0.1.1` (just published from [deepgram/ui#27](deepgram/ui#27) + [deepgram/ui#30](deepgram/ui#30)) ships preflight scoped to `[data-dg-agent]` via [`tailwindcss-scoped-preflight`](https://github.com/Roman86/tailwindcss-scoped-preflight). Until the widget bumps its dependency, the published UMD on `cdn.deepgram.com/widgets/` still ships unscoped Tailwind preflight that bleeds into host pages. Symptoms reported in [deepgram/deepgram-docs#777](deepgram/deepgram-docs#777): content width collapsed on every non-demo page on the docs site after the widget bundle finished loading. Same regression hits any customer embedding the widget on their own site. ## What changed - `packages/widget/package.json`: `@deepgram/ui` `^0.1.0` → `^0.1.1` - `bun.lock` regenerated ## Verification Rebuilt the widget locally against `@deepgram/ui@0.1.1`: | | before | after | |---|---|---| | Unscoped `@layer base{*,:after,…}` rules in widget UMD | many | **0** | | `:where([data-dg-agent], …)` scoped rules | 0 | **76** | | Total `[data-dg-agent]` occurrences | 9 | **171** | Bundle size: 384.30 KB → 387.53 KB (+3.23 KB) from the added scope selectors. Acceptable trade. ## Expected after merge 1. release-please opens `chore(main): release agents-widget 0.1.4`. 2. Merging that PR bumps `packages/widget/package.json` to 0.1.4 and tags `agents-widget-v0.1.4`. 3. The npm publish workflow pushes `@deepgram/agents-widget@0.1.4` to npm. 4. The CDN publish job uploads the new UMD bundle to: - `https://cdn.deepgram.com/widgets/v0.1.4/widget.umd.js` (immutable, 365-day TTL) - `https://cdn.deepgram.com/widgets/latest/widget.umd.js` (5-min TTL plus invalidation) 5. Anyone loading either URL gets the scoped preflight. ## Refs - [deepgram/ui#27](deepgram/ui#27) — the source fix - [deepgram/ui#30](deepgram/ui#30) — unpin release-please to actually publish 0.1.1 - [deepgram/dx-stack#4](deepgram/dx-stack#4) — recipe + gotchas doc - [deepgram/deepgram-docs#777](deepgram/deepgram-docs#777) — where the bleed was first surfaced
This was referenced May 7, 2026
lukeocodes
added a commit
that referenced
this pull request
May 7, 2026
The 0.1.2 change switched from granular tailwind imports to the full `@import "tailwindcss" prefix(dg)` shortcut to apply prefix(dg) cleanly. That shortcut also imports preflight at root scope. The scoped-preflight plugin still ran and added its own `:where([data-dg-agent], ...)` copy of every preflight rule, but it did NOT strip the upstream raw preflight that the full import had already injected. The 0.1.2 bundle therefore shipped TWO copies of preflight: one scoped, one raw. The raw copy bled the universal selector reset onto every host page, undoing the original 0.1.1 work. Restoring granular imports with prefix() applied per-import: @import "tailwindcss/theme.css" layer(theme) prefix(dg); @import "tailwindcss/utilities.css" layer(utilities) prefix(dg); is the configuration documented for "preflight-free" Tailwind v4 setups. Theme tokens and utility classes still get the dg- and dg: prefix from prefix(). Preflight is not imported at all, so the only preflight rules in the bundle are the scoped copies the plugin emits. Verified locally: before (0.1.2): unscoped @layer base{*,:after,:before{...}}, raw html{}, body{}, h1,h2,h3{} rules at root scope alongside the scoped versions after (0.1.3): 0 unscoped preflight indicators, 76 scoped :where([data-dg-agent], …) rules, 353 prefixed .dg\: utility refs, 13/13 tests pass Bundle size: 188.9 KB -> 185.2 KB (-3.7 KB) from removing the duplicate raw-preflight rules. Refs: - https://tailwindcss.com/docs/preflight#disabling-preflight (granular import pattern) - #27 (the original scoped-preflight work) - #32 (the prefix(dg) work that introduced this regression) - deepgram/dx-stack#4 (gotchas doc gains a "full import re-leaks preflight" section)
lukeocodes
added a commit
to deepgram/agent
that referenced
this pull request
May 7, 2026
…egression (#52) ## Why [`@deepgram/ui@0.1.2`](https://www.npmjs.com/package/@deepgram/ui/v/0.1.2) introduced a regression by switching to the full `@import "tailwindcss"` shortcut. The shortcut applied `prefix(dg)` correctly to utilities but also pulled raw preflight in at root scope, alongside the scoped-preflight plugin's scoped copy. The bundle shipped two preflights and the unscoped one leaked `*, ::before, ::after { box-sizing: border-box; ... }`, `html{...}`, `body{...}`, and `h1,h2,h3{...}` onto every host page that loaded the widget. [`@deepgram/ui@0.1.3`](https://www.npmjs.com/package/@deepgram/ui/v/0.1.3) (just published from [deepgram/ui#34](deepgram/ui#34)) restored granular imports (`tailwindcss/theme.css` + `tailwindcss/utilities.css` with `prefix(dg)` on each) so preflight comes ONLY from the scoped-preflight plugin. Every preflight rule in the bundle now has a `[data-dg-agent]` ancestor. ## What changed - `packages/widget/package.json`: `@deepgram/ui` `^0.1.2` -> `^0.1.3` - `bun.lock` regenerated ## Verification Rebuilt the widget locally against `@deepgram/ui@0.1.3`: | | 0.1.2 (broken) | 0.1.3 (this PR) | |---|---|---| | Unscoped `@layer base{*,...}` block | **1** | **0** | | Unscoped `html{}`, `body{}`, `h1,h2,h3{}` etc | **multiple** | **0** | | Scoped `:where([data-dg-agent], …)` preflight | 76 | **76** (unchanged) | | Prefixed `.dg\:*` utility refs | 353 | **353** (unchanged) | | Unprefixed Tailwind utility leaks | 0 | **0** (unchanged) | | Bundle size | 393.5 KB | **389.8 KB** (-3.7 KB) | ## Expected after merge 1. release-please opens `chore(main): release agents-widget 0.1.6`. 2. Merging publishes `@deepgram/agents-widget@0.1.6` to npm and uploads: - `https://cdn.deepgram.com/widgets/v0.1.6/widget.umd.js` (immutable) - `https://cdn.deepgram.com/widgets/latest/widget.umd.js` (cache-invalidated) 3. Anyone embedding the widget on their own site stops having their host-page CSS reset by the widget bundle. ## Refs - [deepgram/ui#34](deepgram/ui#34) - the granular-imports fix - [deepgram/ui#32](deepgram/ui#32) - the prefix(dg) work - [deepgram/ui#27](deepgram/ui#27) - the original scoped-preflight work - [#50](#50) - the broken 0.1.2 bump this supersedes
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The full
@import "tailwindcss";shortcut ships preflight at the global scope. The preflight uses universal selectors (*, ::before, ::after,html,body) that override the host page's box model, list styling, heading margins, button appearance, and more.Symptoms reported in deepgram/deepgram-docs#777: content width collapsed on every non-demo page after the widget bundle finished loading. Same regression hits any customer embedding
@deepgram/agents-widgeton their own site, not just the docs.What changed
theme+utilitiesonly. Preflight is no longer pulled in at the global scope.tailwindcss-scoped-preflightplugin withisolation-strategy: insideandselector: [data-dg-agent]. The plugin re-introduces preflight, but every rule is rewritten as:where([data-dg-agent], [data-dg-agent] *)…. The reset only applies to widget descendants.tailwindcss-scoped-preflightfromdevDependenciestodependencies. The plugin runs at the consumer's Tailwind build time, so it must be installed transitively when consumers depend on@deepgram/ui.:root-level extended tokens (--primary-hover,--msg-user-bg,--dg-va-primary,--dg-va-border, etc.) to[data-dg-agent]. These are widget-internal tokens; they should never have been on:rootin the first place.Verification
End-to-end through
@deepgram/agents-widget@0.1.3UMD build (locally patched to consume this @deepgram/ui):*,:after,:before,::backdroprules in widget bundle:where([data-dg-agent], [data-dg-agent] *)rules in widget bundle[data-dg-agent]occurrences in widget bundleBundle size grew ~3 KB gzipped from the added scope selectors. Acceptable trade for stopping the host-page regression.
Follow-up
@deepgram/agents-widgetneeds to bump its@deepgram/uidependency once this lands and a new@deepgram/uiversion publishes. The widget's UMD build will then ship correctly-scoped preflight automatically.There's a separate (smaller) widget-side issue where the widget's Vite build appears to also process Tailwind directly, producing its own copy of unscoped output. That trail leads to widget vite config and is out of scope for this PR; will file separately.