Skip to content

fix(tailwind): export STREAMDOWN_CLASSES and getSourceInline() for Tailwind v4 prefix support#453

Open
sleitor wants to merge 3 commits intovercel:mainfrom
sleitor:fix-450
Open

fix(tailwind): export STREAMDOWN_CLASSES and getSourceInline() for Tailwind v4 prefix support#453
sleitor wants to merge 3 commits intovercel:mainfrom
sleitor:fix-450

Conversation

@sleitor
Copy link
Contributor

@sleitor sleitor commented Mar 10, 2026

Problem

Fixes #450

When using Tailwind v4's prefix() option (e.g. prefix(tw)), Tailwind's build-time scanner looks for tw:flex, tw:items-center, etc. in scanned files. However, streamdown's dist files only contain the unprefixed class names (flex, items-center, etc.), so no matching CSS utilities are generated and all styling breaks.

Solution

Add a new streamdown/tailwind entry point that exports:

  • STREAMDOWN_CLASSES – a readonly array of every Tailwind utility class used across streamdown and its official plugins
  • getSourceInline(prefix?) – returns a ready-to-paste Tailwind v4 @source inline(...) directive with all classes, optionally prefixed

Usage with Tailwind v4 prefix

/* globals.css */
@import "tailwindcss" prefix(tw);

/* Replace 'tw' with your actual prefix: */
@source inline("tw:{absolute,animate-spin,...}");

Generate the exact directive with the helper:

// scripts/gen-streamdown-source.js
import { getSourceInline } from 'streamdown/tailwind';
process.stdout.write(getSourceInline('tw') + '\n');
node scripts/gen-streamdown-source.js >> app/globals.css

Or use the raw class array in your own tooling:

import { STREAMDOWN_CLASSES } from 'streamdown/tailwind';
// string[] – 166 Tailwind utilities used by streamdown

No-prefix usage unchanged

Users who are not using a prefix are unaffected — they continue to use @source "../node_modules/streamdown/dist/*.js" as documented.

Changes

  • packages/streamdown/lib/tailwind-classes.ts – new file: exports STREAMDOWN_CLASSES and getSourceInline
  • packages/streamdown/tailwind.ts – new entry point re-exporting the helpers
  • packages/streamdown/tsup.config.ts – adds tailwind.ts to build entries
  • packages/streamdown/package.json – adds ./tailwind export condition
  • packages/streamdown/README.md – documents Tailwind v4 prefix setup
  • .changeset/fix-tailwind-prefix-scanning.md – patch bump

@vercel
Copy link
Contributor

vercel bot commented Mar 10, 2026

Someone is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

* Use this list to configure Tailwind v4's `@source inline()` directive when
* you need a custom prefix. See the README for details.
*/
export const STREAMDOWN_CLASSES: readonly string[] = [
Copy link
Contributor

@vercel vercel bot Mar 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

STREAMDOWN_CLASSES array is missing 6 Tailwind CSS utility classes ([&_thead]:sticky, [&_thead]:top-0, [&_thead]:z-10, overflow-auto, pt-0, underline) that are actively used in the source code, causing those styles to be absent when using Tailwind v4 prefix scanning.

Fix on Vercel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — added 20 missing utility classes that are actively used in the source but were absent from the array:

-mt-10, [&>p]:inline, [&_svg]:h-auto, [&_svg]:w-auto, [counter-increment:line_0], [counter-reset:line], [li_&]:pl-6, before:content-[counter(line)], bg-[var(--sdm-bg,inherit], bg-[var(--sdm-tbg)], border, dark:bg-[var(--shiki-dark-bg,var(--sdm-bg,inherit)], dark:bg-[var(--shiki-dark-bg,var(--sdm-tbg))], dark:text-[var(--shiki-dark,var(--sdm-c,inherit))], list-decimal, list-disc, list-inside, rounded, sticky, text-[var(--sdm-c,inherit)]

@haydenbleasel
Copy link
Contributor

Thanks @sleitor but i don't think manually keeping track of all the classnames is the best way to solve, i'm hoping Tailwind have some better way of handling this 😭

@sleitor
Copy link
Contributor Author

sleitor commented Mar 16, 2026

Thanks for the feedback, @haydenbleasel! I did dig into the Tailwind v4 docs — unfortunately there's no native mechanism to handle the prefix case with @source path scanning.

The problem: when prefix(tw) is active, Tailwind looks for tw:flex, tw:items-center etc. in scanned files. But streamdown's dist only contains unprefixed class names (flex, items-center), so @source "../node_modules/streamdown/dist/*.js" won't help here.

The Tailwind v4 docs actually recommend exactly this approach for classes that can't be picked up by static scanning — Safelisting specific utilities via @source inline().

And notably, tailwind-merge — widely used by shadcn/ui and others — takes the same approach of maintaining an explicit class list internally. It's a well-established pattern, not a fragile one.

Happy to be corrected if there's a v4 API I missed! 🙏

sleitor added 2 commits March 16, 2026 22:40
…uplicate 'dist' in package.json files

Addresses VADE review comments:
- STREAMDOWN_CLASSES was missing 20 Tailwind utility classes actively used
  in source: -mt-10, [&>p]:inline, [&_svg]:h-auto/w-auto, [counter-*:line_0/line],
  [li_&]:pl-6, before:content-[counter(line)], bg-[var(--sdm-bg,*)],
  bg-[var(--sdm-tbg)], border, dark:bg/text CSS-var variants,
  list-decimal/disc/inside, rounded, sticky, text-[var(--sdm-c,inherit)]
- package.json: removed duplicate 'dist' entry from files array
- tailwind.ts: sort exports (biome organizeImports)
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.

prefix prop does not work - Tailwind scanner cannot detect unprefixed classes in dist files

2 participants