Skip to content

feat(web): Add TailwindCSS integration with theme support#106

Merged
mpaulosky merged 1 commit intomainfrom
wip/add-tailwindcss
Mar 11, 2026
Merged

feat(web): Add TailwindCSS integration with theme support#106
mpaulosky merged 1 commit intomainfrom
wip/add-tailwindcss

Conversation

@mpaulosky
Copy link
Owner

Summary

Comprehensive TailwindCSS integration for the Web project with full theme support.

Changes

TailwindCSS Integration

  • Added npm/postcss build pipeline for TailwindCSS
  • New package.json and tailwind.config.js configuration
  • CSS reorganization: wwwroot/css/app.css, input.css, themes.css

Theme Support

  • Light/dark/system theme modes via theme-manager.js
  • ThemeToggle and ThemeSelector components
  • CSS custom properties for consistent theming

Component Reorganization

  • Moved App.razor and Routes.razor to Components/ directory
  • New shared components: ReconnectModal, LoadingComponent, ErrorAlertComponent
  • New page components: About, Contact, Error, NotFound
  • Updated all feature pages with Tailwind utility classes

Authentication

  • Added Auth0AuthenticationStateProvider
  • Added AuthenticationServiceExtensions
  • Updated appsettings.json with Auth0 configuration structure

Other

  • Updated GlobalUsings.cs with new namespace imports
  • Updated Web.csproj with new dependencies
  • Added favicon.png

Testing

  • All existing unit tests pass
  • Build succeeds with 1 warning (missing LoginComponent - expected, not yet implemented)

Notes

This is a WIP branch establishing the TailwindCSS foundation. The LoginComponent referenced in NavMenuComponent will be implemented in a follow-up PR.

- Integrate TailwindCSS build pipeline with npm/postcss
- Add light/dark/system theme support with theme-manager.js
- Reorganize component structure (App.razor, Routes.razor moved)
- Add new shared components: ReconnectModal, ThemeToggle, ThemeSelector
- Add new page components: About, Contact, Error, NotFound
- Update all feature pages with Tailwind utility classes
- Add Auth0 authentication service extensions
- Update GlobalUsings and Web.csproj for new dependencies

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 11, 2026 22:31
@github-actions
Copy link

github-actions bot commented Mar 11, 2026

Test Results Summary

  7 files  ±0   38 suites  ±0   16s ⏱️ +2s
840 tests ±0  840 ✅ ±0  0 💤 ±0  0 ❌ ±0 
851 runs  ±0  851 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 4ca58e8. ± Comparison against base commit 54fe33c.

♻️ This comment has been updated with latest results.

@codecov
Copy link

codecov bot commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 0% with 251 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.10%. Comparing base (54fe33c) to head (4ca58e8).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/Web/Components/User/Profile.razor 0.00% 29 Missing and 9 partials ⚠️
src/Web/Components/Shared/ThemeToggle.razor 0.00% 29 Missing and 5 partials ⚠️
src/Web/Components/Shared/ThemeSelector.razor 0.00% 27 Missing and 1 partial ⚠️
...c/Web/Services/Auth0AuthenticationStateProvider.cs 0.00% 19 Missing and 7 partials ⚠️
src/Web/Components/Shared/ErrorPageComponent.razor 0.00% 21 Missing and 2 partials ⚠️
...rc/Web/Services/AuthenticationServiceExtensions.cs 0.00% 14 Missing and 2 partials ⚠️
.../Components/Shared/ComponentHeadingComponent.razor 0.00% 12 Missing and 1 partial ⚠️
...c/Web/Components/Shared/PageHeadingComponent.razor 0.00% 8 Missing and 1 partial ⚠️
...rc/Web/Components/Shared/PageHeaderComponent.razor 0.00% 7 Missing and 1 partial ⚠️
src/Web/Components/Pages/Error.razor 0.00% 5 Missing and 2 partials ⚠️
... and 15 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #106      +/-   ##
==========================================
- Coverage   58.89%   54.10%   -4.80%     
==========================================
  Files         110      124      +14     
  Lines        2496     2717     +221     
  Branches      254      287      +33     
==========================================
  Hits         1470     1470              
- Misses        844     1032     +188     
- Partials      182      215      +33     
Files with missing lines Coverage Δ
...c/Web/Components/Features/Admin/AdminPage.razor.cs 0.00% <ø> (ø)
.../Components/Features/Admin/SampleDataPage.razor.cs 0.00% <ø> (ø)
...ponents/Features/Categories/EditCategoryPage.razor 0.00% <ø> (ø)
...b/Components/Features/Issues/CreateIssuePage.razor 0.00% <ø> (ø)
...Web/Components/Features/Issues/EditIssuePage.razor 0.00% <ø> (ø)
...b/Components/Features/Profile/ProfilePage.razor.cs 0.00% <ø> (ø)
.../Components/Features/Statuses/EditStatusPage.razor 0.00% <ø> (ø)
src/Web/Components/IssueForm.razor 0.00% <ø> (ø)
src/Web/Components/Shared/ConfirmDialog.razor 0.00% <ø> (ø)
src/Web/Components/Shared/DataTable.razor 0.00% <ø> (ø)
... and 27 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

Copilot AI left a comment

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 integrates TailwindCSS into the Web project, introduces a new theme system (color families + light/dark), and expands authentication-related wiring (Auth0 + auth-aware routing/components) while restyling many pages/components to use shared Tailwind component classes.

Changes:

  • Added Tailwind build pipeline (npm + MSBuild target) and reorganized CSS into wwwroot/css/input.css + themes.css.
  • Introduced a new theme manager (theme-manager.js) and multiple UI components for theme selection/toggling.
  • Added Auth0 authentication state provider + updated routing/pages/components to use authorization-aware flows.

Reviewed changes

Copilot reviewed 61 out of 65 changed files in this pull request and generated 18 comments.

Show a summary per file
File Description
tests/Web.Tests.Bunit/Components/Features/Issues/IssueDetailPageTests.cs Updates selector to match new button class (.btn-action).
src/Web/wwwroot/js/theme.js Adds themeHelpers helpers (currently appears unused/not loaded).
src/Web/wwwroot/js/theme-manager.js Adds class-based Tailwind theme manager persisted in localStorage.
src/Web/wwwroot/favicon.png Adds favicon asset.
src/Web/wwwroot/css/themes.css Defines OKLCH theme palettes + semantic tokens + dark overrides.
src/Web/wwwroot/css/input.css Tailwind entrypoint + component class definitions (btn-action, card, etc.).
src/Web/wwwroot/app.css Removes old handcrafted CSS variables + base styling (now replaced by Tailwind output).
src/Web/package.json Adds Tailwind CLI scripts to build/watch CSS.
src/Web/package-lock.json Locks Tailwind v4 dependency graph.
src/Web/appsettings.json Adds baseline Web app configuration file.
src/Web/Web.csproj Adds Blazored.LocalStorage + MSBuild targets to run npm Tailwind build.
src/Web/Services/TokenForwardingHandler.cs Removes now-redundant using (moved to global usings).
src/Web/Services/AuthenticationServiceExtensions.cs Adds helper to configure Auth0 auth + cascading auth state.
src/Web/Services/Auth0AuthenticationStateProvider.cs Adds authentication state provider reading HttpContext user + role claims.
src/Web/Program.cs Updates startup wiring (local storage, output cache middleware, auth endpoints).
src/Web/GlobalUsings.cs Adds global usings for Auth0/auth/local-storage/service defaults + component namespaces.
src/Web/Extensions/AuthExtensions.cs Removes redundant using (moved to global usings).
src/Web/Components/User/Profile.razor Adds an authorized profile page showing user info/roles/claims.
src/Web/Components/Shared/WelcomeComponent.razor Adds welcome “hero” section component.
src/Web/Components/Shared/ThemeToggle.razor.js Adds JS module to toggle dark/light and sync with ThemeManager.
src/Web/Components/Shared/ThemeToggle.razor Adds localStorage-backed theme toggle component.
src/Web/Components/Shared/ThemeSelector.razor Adds UI to pick color + brightness via ThemeManager JS calls.
src/Web/Components/Shared/RedirectToLogin.razor Adds redirect-to-login helper component.
src/Web/Components/Shared/PageHeadingComponent.razor Adds page heading component (with Level-based heading selection).
src/Web/Components/Shared/PageHeaderComponent.razor Adds another heading/header component variant.
src/Web/Components/Shared/LoadingComponent.razor Adds loading UI component.
src/Web/Components/Shared/ErrorPageComponent.razor Adds error display component based on status codes.
src/Web/Components/Shared/ErrorAlertComponent.razor Adds reusable error alert component with optional child content.
src/Web/Components/Shared/DataTable.razor Uses shared Tailwind class loading-state for empty state.
src/Web/Components/Shared/ConfirmDialog.razor Restyles confirm dialog using shared Tailwind component classes.
src/Web/Components/Shared/ComponentHeadingComponent.razor Adds component heading helper with variable levels/colors.
src/Web/Components/Routes.razor Adds auth-aware routing (AuthorizeRouteView + NotAuthorized handling).
src/Web/Components/Pages/NotFound.razor Adds not-found page.
src/Web/Components/Pages/Home.razor Restyles home page to use Tailwind component classes.
src/Web/Components/Pages/Error.razor Adds error page.
src/Web/Components/Pages/Contact.razor Adds contact page.
src/Web/Components/Pages/Admin.razor Adds simple admin page (role-gated).
src/Web/Components/Pages/About.razor Adds about page.
src/Web/Components/Layout/ReconnectModal.razor.js Adds reconnect modal JS behavior.
src/Web/Components/Layout/ReconnectModal.razor.css Adds reconnect modal styling.
src/Web/Components/Layout/ReconnectModal.razor Adds reconnect modal markup.
src/Web/Components/Layout/NavMenuComponent.razor Adds/updates nav menu component (references LoginComponent WIP).
src/Web/Components/Layout/NavMenu.razor Restyles main nav + mobile nav and references theme controls.
src/Web/Components/IssueForm.razor Restyles the issue form using shared Tailwind component classes.
src/Web/Components/Features/Statuses/StatusesPage.razor Restyles statuses list/grid page.
src/Web/Components/Features/Statuses/EditStatusPage.razor Restyles edit status page.
src/Web/Components/Features/Statuses/CreateStatusPage.razor Restyles create status page.
src/Web/Components/Features/Profile/ProfilePage.razor.cs Removes redundant using.
src/Web/Components/Features/Profile/ProfilePage.razor Restyles profile feature page.
src/Web/Components/Features/Issues/IssuesPage.razor Restyles issues list page.
src/Web/Components/Features/Issues/IssueDetailPage.razor Restyles issue details + comments UI and confirm dialog usage.
src/Web/Components/Features/Issues/EditIssuePage.razor Restyles edit issue page + IssueForm usage.
src/Web/Components/Features/Issues/CreateIssuePage.razor Restyles create issue page.
src/Web/Components/Features/Categories/EditCategoryPage.razor Restyles edit category page.
src/Web/Components/Features/Categories/CreateCategoryPage.razor Restyles create category page.
src/Web/Components/Features/Categories/CategoriesPage.razor Restyles categories list/grid page.
src/Web/Components/Features/Admin/SampleDataPage.razor.cs Removes redundant usings.
src/Web/Components/Features/Admin/SampleDataPage.razor Restyles sample data page and error message display.
src/Web/Components/Features/Admin/AdminPage.razor.cs Removes redundant using.
src/Web/Components/Features/Admin/AdminPage.razor Restyles admin review page.
src/Web/Components/App.razor Moves app shell to Components/ and initializes new theme classes early.
src/Web/App.razor Removes old app shell (data-theme + CDN Tailwind approach).
IssueManager.sln.DotSettings Adds issuemanagerdb to dictionary.
Directory.Packages.props Adds Blazored.LocalStorage package version.
Files not reviewed (1)
  • src/Web/package-lock.json: Language not supported

You can also share your feedback on Copilot code review. Take the survey.

</AuthorizeView>
<!-- Auth Links (Mobile) -->
<div class="border-t border-[var(--border-color)] pt-2 mt-2">
<div class="border-t border--[var(--border-color)] pt-2 mt-2">
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Class name border--[var(--border-color)] has an extra - and won’t apply any style. It looks like this should be border-[var(--border-color)] (or another valid Tailwind class).

Suggested change
<div class="border-t border--[var(--border-color)] pt-2 mt-2">
<div class="border-t border-[var(--border-color)] pt-2 mt-2">

Copilot uses AI. Check for mistakes.
Comment on lines +146 to +149
<!-- Ensure npm packages are installed -->
<Target Name="EnsureNodeModules" BeforeTargets="BuildTailwindCSS" Condition="'$(SkipTailwindBuild)' != 'true'">
<Exec Command="npm install" WorkingDirectory="$(MSBuildProjectDirectory)" Condition="!Exists('node_modules')" />
<Message Importance="high" Text="Node modules installed successfully" />
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

EnsureNodeModules checks Exists('node_modules') without an explicit path. To avoid false negatives/positives when the working directory differs, prefer Exists('$(MSBuildProjectDirectory)\node_modules') (and similarly ensure the condition aligns with the WorkingDirectory).

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +6
<header
class=@($"container flex items-center justify-between max-w-7xl px-6 py-2 mx-auto rounded-b-mdxl:max-w-5xl border-b border-blue-700 shadow-md {ShadowStyle}")>
<h1 class=@($"text-6xl font-bold mb-4 {TextColor}")>@GetErrorTitle(ErrorCode)</h1>
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The header class string contains rounded-b-mdxl:max-w-5xl which looks like two Tailwind classes accidentally concatenated (missing a space). This will prevent both rounded-b-md and xl:max-w-5xl from applying.

Copilot uses AI. Check for mistakes.
Comment on lines +48 to +55
// Add role claims if they exist
string? rolesClaim = user.FindFirst("https://articlesite.com/roles")?.Value;

if (!string.IsNullOrEmpty(rolesClaim))
{
string[] roles = rolesClaim.Split(',', StringSplitOptions.RemoveEmptyEntries);

foreach (string role in roles)
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Role extraction is hard-coded to the custom claim type https://articlesite.com/roles. If this app is deployed to different Auth0 tenants/APIs, this namespace is likely to differ and roles won’t be picked up. Consider making the roles claim type configurable (appsettings/user secrets) or using the standard Auth0 claim(s) you expect.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +26
<p class="font-bold text-gray-900 dark:text-gray-100">
<span>Name:</span>
<h4>@_username</h4>
</p>
<p class="font-bold text-gray-900 dark:text-gray-100">
<span>Email:</span>
<h4>@_emailAddress</h4>
</p>
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The markup nests <h4> elements inside <p> tags, which is invalid HTML and can confuse screen readers/layout engines. Consider using a block container (e.g., <div>) or inline elements (e.g., <span>) for the values instead of heading tags inside paragraphs.

Copilot uses AI. Check for mistakes.

<!-- Blazor framework script -->
<script src="@Assets["_framework/blazor.web.js"]"></script>

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The layout theme components (Components/Layout/ThemeToggle.razor + ThemeColorSelector.razor) invoke themeHelpers.*, but this document no longer loads wwwroot/js/theme.js that defines window.themeHelpers. As-is, theme toggling/color selection will throw JS errors. Either load js/theme.js here or migrate those components to use ThemeManager/the new theme system.

Suggested change
<!-- Legacy theme helpers used by ThemeToggle and ThemeColorSelector -->
<script src="js/theme.js"></script>

Copilot uses AI. Check for mistakes.
Comment on lines +140 to +144
<!-- Optimized CSS build - only runs when source CSS changes -->
<Target Name="BuildTailwindCSS" BeforeTargets="PreBuildEvent" Condition="'$(SkipTailwindBuild)' != 'true'">
<Exec Command="npm run build:css" />
<Message Importance="high" Text="TailwindCSS compiled successfully" />
</Target>
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The comment says the Tailwind build “only runs when source CSS changes”, but this target has no Inputs/Outputs, so it will run on every build. If you want incremental behavior, add Inputs/Outputs (e.g., input.css/themes.css → app.css) so MSBuild can skip when unchanged.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +8
{
"dependencies": {
"@tailwindcss/cli": "^4.2.1",
"tailwindcss": "^4.2.1"
},
"scripts": {
"build:css": "npx @tailwindcss/cli -i wwwroot/css/input.css -o wwwroot/css/app.css",
"watch:css": "npx @tailwindcss/cli -i wwwroot/css/input.css -o wwwroot/css/app.css --watch"
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Tailwind v4.2.1 pulls @tailwindcss/oxide which requires Node >= 20 (per the lockfile). Since CSS compilation is now part of the MSBuild pipeline, builds/CI will fail on older Node versions unless the repo pins/installs a compatible Node version (e.g., via CI setup or documentation).

Copilot uses AI. Check for mistakes.
Comment on lines +37 to +43
// Log user claims for debugging
_logger.LogInformation("User authenticated with claims:");

foreach (Claim claim in user.Claims)
{
_logger.LogInformation("Claim: {Type} = {Value}", claim.Type, claim.Value);
}
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Logging every user claim at Information level can leak PII and potentially large claim payloads into logs. Consider removing this, downgrading to Debug/Trace, or guarding it behind a development-only check/config flag.

Copilot uses AI. Check for mistakes.
Comment on lines +19 to +22
case "3":

<h3 class=@($"text-1xl")>@HeaderText</h3>

Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

Tailwind doesn’t include a text-1xl utility by default. If this is intended to be “extra large” text, use a valid class such as text-xl/text-lg, otherwise this heading size won’t apply.

Copilot uses AI. Check for mistakes.
@mpaulosky mpaulosky merged commit dfcc460 into main Mar 11, 2026
29 checks passed
@mpaulosky mpaulosky deleted the wip/add-tailwindcss branch March 11, 2026 22:40
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