Skip to content

fix(ui): keep tailwind imports granular so preflight stays scoped#34

Merged
lukeocodes merged 1 commit intomainfrom
fix/restore-granular-imports
May 7, 2026
Merged

fix(ui): keep tailwind imports granular so preflight stays scoped#34
lukeocodes merged 1 commit intomainfrom
fix/restore-granular-imports

Conversation

@lukeocodes
Copy link
Copy Markdown
Member

Why

deepgram/ui#32 (0.1.2) switched from granular Tailwind imports to the full @import "tailwindcss" prefix(dg) shortcut. The shortcut works for prefix(dg) but it also injects preflight at root scope. The tailwindcss-scoped-preflight plugin still runs and adds its scoped copy on top, so the 0.1.2 bundle ships TWO preflight copies: one scoped to [data-dg-agent], one raw at root. The raw copy bled *, ::before, ::after { box-sizing: border-box; ... }, html { ... }, body { ... }, h1,h2,h3 { font-size: inherit }, etc. onto every host page that loaded the bundle. Undid the original #27 preflight scoping work.

What changed

packages/ui/src/styles.css:

- @import "tailwindcss" prefix(dg);
+ @import "tailwindcss/theme.css" layer(theme) prefix(dg);
+ @import "tailwindcss/utilities.css" layer(utilities) prefix(dg);

Granular imports skip preflight entirely, leaving the scoped-preflight plugin as the only source of preflight in the bundle. prefix(dg) continues to apply to theme tokens and utility classes per Tailwind v4 docs for preflight-free setups.

Adds a comment block explaining why the granular pattern is required and what happens if a future contributor switches back to the full import. Lived through that exact regression today.

Verification

0.1.1 (granular, no prefix) 0.1.2 (full + prefix) this PR (granular + prefix)
Unscoped @layer base{*,:after,:before...} 0 1 (LEAK) 0
Unscoped html{}, body{} rules 0 multiple (LEAK) 0
Unscoped h1,h2,h3{...} reset 0 multiple (LEAK) 0
Scoped :where([data-dg-agent], …) preflight 76 76 76
Prefixed .dg\:* utility rules 0 (no prefix) 353 353
Bundle size 167.5 KB 188.9 KB 185.2 KB (-3.7 KB)
Unit tests 13/13 13/13 13/13

Expected after merge

  1. release-please opens chore(main): release ui 0.1.3.
  2. Merging that publishes @deepgram/ui@0.1.3.
  3. @deepgram/agents-widget follow-up bumps the dep, releases 0.1.6, CDN deploys.
  4. cdn.deepgram.com/widgets/latest/widget.umd.js ships preflight ONLY inside [data-dg-agent]. Host-page CSS (margins, box-sizing, headings, body) untouched.

Refs

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)
@vercel
Copy link
Copy Markdown

vercel Bot commented May 7, 2026

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

Project Deployment Actions Updated (UTC)
ui-web Ready Ready Preview, Comment May 7, 2026 9:19am

Request Review

@lukeocodes lukeocodes merged commit b724a91 into main May 7, 2026
4 checks passed
@lukeocodes lukeocodes deleted the fix/restore-granular-imports branch May 7, 2026 09:20
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
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