Skip to content

feat(nuget): ship precompiled CSS bundle + fix safelist gap (variant .cs helpers)#22

Merged
Shewart merged 20 commits into
mainfrom
feat/nuget-precompiled-bundle
Jul 3, 2026
Merged

feat(nuget): ship precompiled CSS bundle + fix safelist gap (variant .cs helpers)#22
Shewart merged 20 commits into
mainfrom
feat/nuget-precompiled-bundle

Conversation

@Shewart

@Shewart Shewart commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Delivers the "no Tailwind, no CLI, just add the package and go" install path — Path A: precompiled ~77KB CSS bundle shipped as a static web asset in the NuGet package. Consumers add one <link> tag and every ShellUI component renders styled.

While validating all four install paths end-to-end locally (see shellui-installation-tests/), discovered a material correctness bug the branch also fixes: the safelist generator only scanned .razor files, silently missing ~100 Tailwind classes that live in Variants/*.cs C# helpers (BadgeVariants, AlertVariants, etc.). Path A and Path B consumers were shipping with broken Badge padding, borders, and hover states. Path C (CLI) was unaffected because the CLI copies the .cs files into the user's project.

Combined with the safelist path from the previous branch, ShellUI now supports four install paths covering every project shape from raw HTML prototypes to full-source-ownership Blazor apps.

What ships

Path A: the precompiled CSS bundle

  • src/ShellUI.Components/wwwroot/shellui-all.css (new, committed) — 76,832 bytes minified. 961 CSS rules covering all safelisted classes. Auto-shipped as a static web asset → served at runtime as _content/ShellUI.Components/shellui-all.css.
  • Consumer usage: one <link> tag + @using ShellUI.Components. Zero Tailwind setup.

Safelist generator now scans .cs too (the bug fix)

tools/ShellUI.SafelistGenerator/Program.cs — dual scan of .razor and .cs files. Extracts Tailwind-shaped tokens from string literals in variant helpers. Result: 307 → 409 classes (+33% coverage). Every rule the components actually apply is now compiled into both the precompiled bundle and the Path B safelist.

Concrete example of what was missing:

  • BadgeVariants.cs composes "border-transparent bg-primary text-primary-foreground hover:bg-primary/80" in C#
  • Previous generator: never scanned .cs, so px-2.5, py-0.5, border-transparent, hover:bg-primary/80 etc. weren't in the safelist
  • Result: Badges rendered flat with no padding, no border, no hover in Path A and Path B
  • Now: all classes captured, rendered correctly

ShellUI.Tests/SafelistDriftTests.cs — the drift test was renamed and updated to feed the generator both file types. Regeneration locked into CI, so this can never re-ship.

scripts/rebuild-precompiled-css.sh (new)

Shared script for local dev and CI. Reads Tailwind version from TailwindConstants.cs (single source of truth), downloads the standalone CLI (cached at ~/.shellui/bin/ — reusable across projects), composes a fixture with shellui-theme.css + @source inline("…") containing all safelist classes, compiles a minified bundle.

The @source inline("…") form was a deliberate choice over @source "file.txt" — Tailwind's file-based extractor silently fails on classes with [state=…] arbitrary values.

CI validation

.github/workflows/ci.yml:

  • New "Verify precompiled CSS bundle is up-to-date" step runs the regen script and fails via git diff --exit-code if the committed bundle drifted. 150KB size guard.
  • NuGet-only smoke step asserts shellui-all.css lands at _content/ShellUI.Components/shellui-all.css in the consumer's build output, contains --background: theme var, .bg-background, hover:bg-accent:hover, data-[state=open] selector.

.github/workflows/release.yml: same drift check before release build.

Documentation overhaul

Root README.md and src/ShellUI.Components/README.md now consistently frame four install paths with who each is for, benefits, and trade-offs:

Path Setup CSS size Best for
A — Precompiled bundle dotnet add package + <link> 77KB fixed New projects, prototypes, no-Tailwind teams
B — Safelist + own Tailwind dotnet add package + @source directive ~30-50KB tree-shaken Existing Blazor+Tailwind projects
C — CLI shellui init + shellui add Even smaller (only installed components) shadcn workflow, custom design systems
D — CDN jsdelivr <link> 77KB (same file, CDN-served) Static HTML, JSFiddle, non-Blazor

Each path documents ✅ benefits and ❌ trade-offs. A "Quick decision matrix" leads the section. Cross-path theming comparison table shows where the theme lives and how to edit it for each path.

src/ShellUI.CLI/README.md (ships on nuget.org) now leads with "Is this what I want?" pointing users to Paths A/B/D if the CLI isn't the right fit.

shellui-installation-tests/ (gitignored, local-only)

Four minimal test projects, one per path, for manual verification before shipping:

  • path-a-precompiled/ — Blazor Web App with the bundle wired. Runs at localhost:5100. Showcase page with Button/Card/Alert/Badge.
  • path-b-safelist/ — Blazor Web App + hand-composed input.css + standalone Tailwind CLI compilation. Runs at localhost:5100 (after Path A is stopped). Same showcase → surfaced the .cs bug.
  • path-c-cli/ — CLI installed locally, shellui init + shellui add. Runs at localhost:5200. Showcase using project-local Components/UI/*.razor.
  • path-d-cdn/ — static HTML using ShellUI's Tailwind classes via jsdelivr URL (or local file for dev).

Each subdirectory README covers: what's already set up, what YOU need to do, how to run the demo, how to modify the theme. Top-level README explains the folder's purpose.

Verification

  • dotnet test ShellUI.Tests54/54 passing including the extended drift test that feeds both file types
  • Local end-to-end smoke: dotnet pack → install into dotnet new blazordotnet build → confirmed shellui-all.css lands at bin/Debug/net10.0/wwwroot/_content/ShellUI.Components/shellui-all.css, served at 200 by Kestrel
  • Path A visual verification: Button/Card/Alert/Badge variants all render correctly with proper spacing, borders, hover states
  • Path B visual verification: same result after the .cs scan fix. Before the fix, Badges were flat/broken — proves the bug was real and the fix works
  • Path C visual verification: source-owned components in Components/UI/*.razor render identically to Path A/B (as expected — same underlying classes)
  • Path D visual verification: hand-authored HTML works via CDN, proving the bundle is standalone

Test plan

  • CI green (drift check + size guard + NuGet smoke assertions)
  • Local: dotnet run in shellui-installation-tests/path-a-precompiled — styled showcase at http://localhost:5100
  • Local: dotnet run in shellui-installation-tests/path-c-cli — same showcase, source-owned components
  • Verify no Path A/B badges have broken padding (this was the ship-blocker bug)
  • Verify EnableShellUIAutoBuild=false escape hatch works for consumers on custom Tailwind pipelines

Shewart added 7 commits July 2, 2026 01:38
…lwind classes

- Introduced a new `shellui-all.css` file containing Tailwind CSS styles, enhancing the styling capabilities of the ShellUI framework.
- Updated `shellui-classes.txt` to include additional Tailwind utility classes, improving the safelist for better integration and usage in consumer projects.
- Added various background, border, and text color classes, along with new utility classes for layout and spacing adjustments.
…UI components

- Updated the README files for both ShellUI and ShellUI.CLI to introduce a new installation path matrix, clarifying the four available methods for integrating ShellUI components.
- Enhanced the descriptions for each installation path, detailing benefits, trade-offs, and setup instructions to improve user experience and understanding.
- Added a new section in ShellUI.CLI README to emphasize the CLI's role in source ownership and customization.
- Improved clarity in ShellUI.Components README regarding the integration of Tailwind CSS and the usage of the safelist for tree-shaken CSS.
…onents

- Introduced a new script `rebuild-precompiled-css.sh` that automates the regeneration of the precompiled Tailwind CSS file `shellui-all.css`.
- The script downloads the Tailwind standalone CLI, caches it, and compiles the CSS using a combination of theme and utility classes.
- Ensures compatibility across different platforms and integrates with CI workflows to validate no drift in the generated CSS.
- Updated the `ShellUI.SafelistGenerator` to scan both `.razor` and `.cs` files, ensuring comprehensive extraction of Tailwind utility classes.
- Introduced a new method `ExtractFromCSharp` to handle class extraction from C# source files, improving the accuracy of the generated safelist.
- Modified the output message to reflect the count of classes extracted from both file types, enhancing user feedback during execution.
…elist generation

- Renamed the test method for clarity, reflecting the inclusion of both `.razor` and `.cs` files in the safelist generation process.
- Enhanced the test to concatenate C# files from the components root directory with the existing Razor files, ensuring comprehensive coverage for Tailwind utility class extraction.
- Added numerous new Tailwind utility classes to the safelist, including background, border, and text color classes, enhancing styling options for ShellUI components.
- Introduced additional classes for dark mode and hover states, improving responsiveness and visual appeal.
- Updated the structure to include new utility classes for layout and spacing adjustments, ensuring comprehensive coverage for Tailwind's capabilities.
…orkflows

- Introduced a new step in both CI and release workflows to verify that the precompiled CSS bundle is up-to-date, preventing stale assets from being shipped.
- Implemented checks to ensure the bundle size does not exceed 150KB and that essential Tailwind rules are present, enhancing the reliability of the CSS output.
- Added error messages to guide developers in regenerating the CSS bundle if discrepancies are found, improving the development workflow.
Copilot AI review requested due to automatic review settings July 1, 2026 23:45
Shewart added 2 commits July 2, 2026 01:49
- Changed the file mode of `rebuild-precompiled-css.sh` from 644 to 755, ensuring it is executable. This adjustment facilitates the script's execution in CI workflows and local development environments.
…css.sh with bash

- Modified the invocation of the `rebuild-precompiled-css.sh` script in both CI and release workflows to use `bash` instead of relying on the file's executable bit. This change ensures compatibility for Windows contributors and simplifies the execution process.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR adds a “NuGet-only” installation path for ShellUI by shipping a precompiled Tailwind CSS bundle as a static web asset, and fixes a safelist-generation gap by scanning both .razor and .cs sources so Tailwind utilities composed in C# variant helpers are included.

Changes:

  • Ship a committed, precompiled shellui-all.css bundle for consumers to include via a single <link> tag (no Tailwind pipeline required).
  • Extend the safelist generator (and drift tests) to scan .cs files in addition to .razor, improving coverage for variant/helper-composed class strings.
  • Update CI/release workflows, rebuild script, and docs to support and validate the new install paths.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/ShellUI.SafelistGenerator/Program.cs Adds .cs scanning and C# string-literal extraction for safelist generation.
src/ShellUI.Components/wwwroot/shellui-classes.txt Updated committed safelist output used for Tailwind @source builds.
src/ShellUI.Components/wwwroot/shellui-all.css New committed precompiled Tailwind bundle shipped as a static web asset.
src/ShellUI.Components/README.md Documentation update describing the three NuGet package install paths (A/B/C).
src/ShellUI.Components/build/ShellUI.Components.targets Updated embedded safelist entries written into consumer wwwroot/ at build time.
src/ShellUI.CLI/README.md CLI README reframed to clarify when Path C (CLI) is the right choice.
ShellUI.Tests/SafelistDriftTests.cs Drift test updated to match generator behavior by scanning .razor + .cs.
scripts/rebuild-precompiled-css.sh New script to regenerate the committed shellui-all.css bundle deterministically.
README.md Root docs overhauled to present four install paths (A/B/C/D) and trade-offs.
.github/workflows/release.yml Adds a release-time drift check to ensure the precompiled bundle is up-to-date.
.github/workflows/ci.yml Adds CI drift/size checks and a NuGet-consumer smoke test for the bundle asset.
Files not reviewed (1)
  • src/ShellUI.Components/wwwroot/shellui-all.css: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tools/ShellUI.SafelistGenerator/Program.cs Outdated
Comment thread tools/ShellUI.SafelistGenerator/Program.cs Outdated
Comment thread scripts/rebuild-precompiled-css.sh Outdated
Comment thread .github/workflows/ci.yml Outdated
Comment thread src/ShellUI.Components/README.md Outdated
Comment thread README.md Outdated
Copilot AI review requested due to automatic review settings July 1, 2026 23:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Shewart added 3 commits July 2, 2026 02:02
- Added a comment to the .gitignore file regarding the generated Tailwind bundle and instructions for local developers to regenerate it.
- Removed the shellui-all.css file as it is now generated in CI, preventing unnecessary drift-check failures.
…bundle

- Modified the CI and release workflows to generate the precompiled CSS bundle on every run, eliminating drift-check failures due to platform-specific output differences.
- Implemented content validation checks to ensure essential Tailwind rules are present in the generated bundle, enhancing reliability and preventing stale assets from being shipped.
- Updated error handling to provide clearer guidance for developers if the bundle is not produced or if critical classes are missing.
…orkflow

- Added a step to remove cached ShellUI.Components from the NuGet packages directory to prevent stale versions from interfering with the package restore process.
- This change ensures that the latest version of the package is used, improving the reliability of the CI workflow.
Copilot AI review requested due to automatic review settings July 2, 2026 00:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Shewart Shewart marked this pull request as draft July 2, 2026 00:14
@Shewart Shewart marked this pull request as ready for review July 2, 2026 00:16
Shewart added 8 commits July 3, 2026 01:40
…and consumer output

- Added diagnostic steps to the CI workflow to verify the contents of the generated nupkg, ensuring essential assets are included.
- Implemented checks to list the consumer's build output and NuGet cache, providing clearer error messages if the expected bundle is missing.
- These improvements aim to enhance the reliability of the CI process and assist developers in troubleshooting issues related to the precompiled CSS bundle.
- Updated the `rebuild-precompiled-css.sh` script to use a portable form of `mktemp`, ensuring compatibility across different operating systems, including macOS and BSD.
- Adjusted the temporary CSS file creation to append the `.css` extension after generating the temporary file, improving clarity and consistency in file handling.
- Revised README files to clarify that `shellui-classes.txt` is an auto-generated safelist of all Tailwind classes used in ShellUI.
- Updated `ShellUI.Components.targets` to remove outdated and unnecessary Tailwind classes, streamlining the safelist for better maintainability.
- Enhanced the `SafelistDriftTests` to ensure consistent source file enumeration for safelist generation, improving test reliability.
… safelist

- Revised the README to specify that `shellui-classes.txt` is an auto-generated safelist of all Tailwind classes used in ShellUI.
- Removed outdated Tailwind classes from `shellui-classes.txt`, streamlining the safelist for better maintainability and clarity.
…ist generation

- Introduced a new method, `EnumerateSources`, to encapsulate the logic for retrieving both .razor and .cs files, improving code organization and reusability.
- Enhanced the extraction process from .cs files to filter out non-class-list strings, ensuring only relevant tokens are included in the safelist.
- Added a heuristic to identify class-list strings, reducing the risk of including irrelevant literals in the safelist.
- Replaced manual file retrieval for .razor and .cs files with a call to `Program.EnumerateSources`, aligning the test's source enumeration with the CLI's approach.
- This change ensures consistency in file lists used for safelist generation, reducing the risk of false-positive drifts.
- Revised the README to clarify that `shellui-classes.txt` is an auto-generated safelist of every Tailwind class used in ShellUI, enhancing understanding for users.
- Modified the CI workflow to adapt to .NET 10's handling of static web assets, ensuring the correct assertion for the presence of the `shellui-all.css` file in the extracted NuGet cache.
- Updated error messages and checks for Tailwind rules in the bundle to improve clarity and accuracy, enhancing the reliability of the CI process.
Copilot AI review requested due to automatic review settings July 3, 2026 17:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Shewart Shewart merged commit 5301e29 into main Jul 3, 2026
1 check passed
@Shewart Shewart deleted the feat/nuget-precompiled-bundle branch July 3, 2026 17:34
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.

2 participants