Skip to content

chore(website): migrate tailwind to v4, daisyui to v5 and flowbite-react to v0.12#6510

Open
corneliusroemer wants to merge 27 commits into
mainfrom
worktree-tailwind-v4-fresh
Open

chore(website): migrate tailwind to v4, daisyui to v5 and flowbite-react to v0.12#6510
corneliusroemer wants to merge 27 commits into
mainfrom
worktree-tailwind-v4-fresh

Conversation

@corneliusroemer
Copy link
Copy Markdown
Contributor

@corneliusroemer corneliusroemer commented May 27, 2026

Resolves #4020, resolves #3714, resolves #5117

Unblocks #6513

Commit messages have more detail about reasoning behind the changes. I've tried to keep changes minimal but a bunch of things were unavoidable. Overview of main changes:

  • Tailwind renames a lot of classes, this causes the majority of the churn. Much of the renames were done by tailwind's upgrade cli but it missed some files and some class patterns so Codex/Claude reviewed migration guide as well to find anything remaining.
  • DaisyUI v5 hides modals with .modal-box class unless they are inside .modal, we had a bunch of modals that weren't following this pattern
  • We now need to pin vite to v6, the same used by our current version of astro, as otherwise our 2-stage build with npm ci --omit=dev gets mismatch issues

Feel free to ask if you have questions about some of the changes.

🚀 Preview: https://worktree-tailwind-v4-fres.loculus.org

@corneliusroemer corneliusroemer changed the title Worktree tailwind v4 fresh wip: tailwind v4 attempt 2 May 27, 2026
@claude claude Bot added the website Tasks related to the web application label May 27, 2026
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 27, 2026

This PR may be related to: #3714 (Updating tailwindcss to v4, @astrojs/tailwind now deprecated)

@corneliusroemer corneliusroemer added the preview Triggers a deployment to argocd label May 27, 2026
@corneliusroemer corneliusroemer changed the title wip: tailwind v4 attempt 2 chore(website): migrate tailwind to v4, daisyui to v5 and flowbite to v0.12 May 27, 2026
@corneliusroemer corneliusroemer marked this pull request as ready for review May 27, 2026 19:14
Copilot AI review requested due to automatic review settings May 27, 2026 19:14
@claude
Copy link
Copy Markdown
Contributor

claude Bot commented May 27, 2026

Claude finished @corneliusroemer's task in 4m 37s —— View job


Code Review

  • Gather context and understand the PR
  • Review CSS/config changes (base.css, tailwind config removal)
  • Review package.json and dependency changes
  • Review modal structure fixes for DaisyUI v5
  • Review class rename correctness across components
  • Check for any missed migrations or regressions
  • Post final review

Overall this is a well-executed migration. The approach — consolidating Tailwind config into CSS @plugin/@theme directives, fixing DaisyUI v5 modal structures, handling flowbite-react v0.12 API changes — looks correct and comprehensive.

Key observations:

Config/CSS architecture

The move from tailwind.config.cjs + base.scss to a pure CSS approach (base.css with @import 'tailwindcss', @plugin, @theme) is the idiomatic TW v4 approach and simplifies the build. The Vite pin to ^6.x with the comment in package.json explaining why is a good practice.

DaisyUI v5 modal fixes

The core fix — wrapping <div class="modal-box"> inside <dialog class="modal"> in EditDataUseTermsButton.tsx — is correct. Before this PR, the code was using <dialog className='modal-box'> directly, which would have broken with DaisyUI v5. DataUseTermsHistoryModal.tsx was already correctly structured.

Note: neither of the fixed modals adds a backdrop close mechanism (<form method="dialog" class="modal-backdrop">), so clicking outside the modal-box doesn't close the dialog. This pre-existed, but DaisyUI v5's docs show this pattern. Worth a follow-up issue.

Bundled correctness fix in SandwichMenu

organism === currentOrganism was a reference-equality comparison that would essentially never be true when organisms are re-created across renders. Changed to organism.key === currentOrganism?.key. Good catch.

helperText removed from FloatingLabel theme override

The old code extracted helperTextClasses from getTheme().floatingLabel.helperText.default (which no longer exists in flowbite-react v0.12). The removal is correct — if there's no helper text rendered on FloatingLabel, this is fine. Worth verifying that no FloatingLabel in the codebase uses the helperText prop.

focus-visible:outlinefocus-visible:outline-solid in DataUploadForm.tsx

The automated upgrade tool changed focus-visible:outline to focus-visible:outline-solid. In TW v3, outline set outline-style: auto. In TW v4, outline-solid sets outline-style: solid. Both produce a visible focus ring, but the appearance differs slightly across browsers. This seems acceptable.

Integration test console warning suppression

Adding 'has been externalized for browser compatibility.' to harmless warnings is a pragmatic fix for the Vite/Flowbite integration generating this warning during integration tests. The risk is this pattern could mask real accidental Node.js imports in client code. The suppression is substring-matched so it will silence any module name — consider making it more specific if possible.

id moved out of standardProps in TextField.tsx

The id was shared between the FloatingLabel input case and the textarea case in standardProps. It's now only on textareaProps. For the FloatingLabel path, flowbite-react v0.12 generates its own id internally, so passing an external id caused duplicate-id issues. The fix is correct.

@reference './base.css' in mdcontainer.css

The @reference directive is the correct TW v4 way to make @apply utilities available in a CSS file that doesn't @import 'tailwindcss' itself. Without this, @apply text-main etc. would fail. Good.

Copy link
Copy Markdown
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 upgrades the website’s styling/tooling stack to Tailwind CSS v4, DaisyUI v5, and Flowbite React v0.12, updating build integration and refactoring many class names/components to match new framework behaviors.

Changes:

  • Replace Tailwind v3 config-based setup with Tailwind v4 CSS-first configuration and Vite plugin integration.
  • Migrate utility classes across Astro/React components for Tailwind v4 (e.g., rounding/shadows/variants) and update overlays/modals for DaisyUI v5 behavior.
  • Upgrade Flowbite React usage (themes/plugins) and adjust lint/format ignores to account for generated Flowbite artifacts.

Reviewed changes

Copilot reviewed 73 out of 74 changed files in this pull request and generated no comments.

Show a summary per file
File Description
website/tailwind.config.cjs Removed Tailwind v3 config (moved to CSS-first v4 setup).
website/src/styles/mdcontainer.css Add Tailwind v4 @reference and keep markdown container styles.
website/src/styles/base.css New Tailwind v4 entrypoint (@import, @theme, plugins, base layer tweaks).
website/src/pages/index.astro Switch md container import from SCSS to CSS.
website/src/pages/[organism]/submission/metadataformat.astro Switch md container import from SCSS to CSS.
website/src/pages/[organism]/submission/[groupId]/index.astro Update rounding class naming.
website/src/layouts/MdLayout.astro Switch md container import from SCSS to CSS.
website/src/layouts/DocLayout.astro Switch md container import + update important-utility syntax.
website/src/layouts/BaseLayout.astro Switch base stylesheet import + flex-growgrow.
website/src/layouts/AboutLayout.astro Switch md container import from SCSS to CSS.
website/src/components/User/UserPage.astro Update rounding utilities.
website/src/components/User/ListOfGroupsOfUser.tsx Update rounding utilities.
website/src/components/User/GroupPage.tsx Update rounding/grow utilities + dropdown shadow/z-index class changes.
website/src/components/Submission/SubmissionGroupSelector.tsx Update dropdown shadow utility.
website/src/components/Submission/FileUpload/SequenceEntryUploadComponent.tsx Update rounding utilities.
website/src/components/Submission/FileUpload/FolderUploadComponent.tsx Update focus outline utility naming.
website/src/components/Submission/FileUpload/FileUploadComponent.tsx Update focus outline utility naming.
website/src/components/Submission/FileUpload/ColumnMappingModal.tsx Update data-state variants + rounding utilities.
website/src/components/Submission/DataUploadForm.tsx Update shadow/outline utilities + checkbox styling to DaisyUI.
website/src/components/SequenceDetailsPage/SequencesDataTableTitle.astro Update dropdown shadow utility.
website/src/components/SequenceDetailsPage/SequenceEntryHistoryMenu.tsx Update dropdown shadow/z-index/right offset utilities.
website/src/components/SequenceDetailsPage/RevokeButton.tsx Replace DaisyUI modal-box usage with custom panel styling.
website/src/components/SequenceDetailsPage/LinkWithMenuComponent.tsx Update ring opacity + outline utility naming.
website/src/components/SearchPage/Table.tsx Add explicit checkbox sizing.
website/src/components/SearchPage/SeqPreviewModal.tsx Refactor Dialog structure + update outline/shadow utilities.
website/src/components/SearchPage/SegmentFilter.tsx Update checkbox rounding utility.
website/src/components/SearchPage/RecentSequencesBanner.tsx Update rounding utility.
website/src/components/SearchPage/fields/TextField.tsx Update Flowbite theme usage and Tailwind class changes.
website/src/components/SearchPage/fields/TextField.spec.tsx Update assertions for Tailwind v4 important-suffix class syntax.
website/src/components/SearchPage/fields/SingleChoiceAutoCompleteField.tsx Update rounding/ring opacity + outline utility naming.
website/src/components/SearchPage/fields/MutationField.tsx Update shadow + outline utility naming.
website/src/components/SearchPage/fields/MultiChoiceAutoCompleteField.tsx Update grow/outline utilities + ring opacity syntax.
website/src/components/SearchPage/fields/LineageField.tsx Replace Tailwind theme() usage with CSS variable in arbitrary value.
website/src/components/SearchPage/fields/FloatingLabelContainer.tsx Update label positioning utilities (origin-[0]origin-left, start-1 → logical inset).
website/src/components/SearchPage/fields/DateRangeField.tsx Replace Tailwind theme() usage with CSS variable in arbitrary value.
website/src/components/SearchPage/DownloadDialog/LinkOutMenu.tsx Update ring opacity + outline utility naming.
website/src/components/SearchPage/DownloadDialog/FieldSelector/FieldSelectorButton.tsx Update shadow + outline utility naming.
website/src/components/SearchPage/DownloadDialog/DownloadDialog.tsx Update checkbox rounding utility.
website/src/components/SearchPage/DownloadDialog/DownloadButton.tsx Update tooltip rounding utility and formatting.
website/src/components/SearchPage/DownloadDialog/DowloadDialogButton.tsx Replace arbitrary width with scale width utility.
website/src/components/SearchPage/DisplaySearchDocs.tsx Update overlay opacity syntax.
website/src/components/ReviewPage/SequencesDialog.tsx Update overlay opacity syntax + flex-growgrow.
website/src/components/ReviewPage/ReviewCard.tsx Update grow/shrink utility naming.
website/src/components/ReviewPage/FilesDialog.tsx Update overlay opacity syntax.
website/src/components/OrganismMetadataTable/OrganismMetadataTableSelector.tsx Update shadow + outline utility naming.
website/src/components/OrganismMetadataTable/OrganismMetadataTable.tsx Update shadow + outline utility naming.
website/src/components/OffCanvasOverlay.tsx Update overlay opacity syntax.
website/src/components/Navigation/SubmenuLink.tsx Update rounding utility.
website/src/components/Navigation/SandwichMenu.tsx flex-growgrow + fix organism active check + shrink utility update.
website/src/components/Navigation/OrganismSubmenu.astro Update rounding/shadow/outline utilities.
website/src/components/Navigation/OrganismNavigation.tsx Update data attribute variant syntax + outline utility naming + shrink utility update.
website/src/components/Navigation/NavigationTab.tsx Convert to forwardRef + update min-height utility.
website/src/components/Navigation/DocsSearch.tsx Update shrink + outline utility naming.
website/src/components/Navigation/DocsMenu.tsx Update outline utility naming.
website/src/components/Navigation/AccessionSearchBox.tsx Update outline utility naming.
website/src/components/Group/Inputs.tsx Update shadow utility naming.
website/src/components/Group/GroupForm.tsx Update rounding utility.
website/src/components/Edit/InputField.tsx Update ring opacity + overlay opacity syntax + outline utility naming.
website/src/components/DataUseTerms/EditDataUseTermsButton.tsx Wrap dialog content in DaisyUI .modal/.modal-box structure for v5.
website/src/components/DataUseTerms/DateChangeModal.tsx Flowbite Datepicker theme type rename + overlay/width utility updates.
website/src/components/DataUseTerms/DataUseTermsSelector.tsx Update button rounding utility and formatting.
website/src/components/ConfirmationDialog.tsx Replace DaisyUI modal-box usage with custom panel styling.
website/src/components/common/FormattedText.tsx Update rounding utility.
website/src/components/common/FixedLengthTextViewer.tsx flex-growgrow + outline utility naming.
website/src/components/common/FieldSelectorModal.tsx Update checkbox rounding utility.
website/src/components/common/BaseDialog.tsx Update overlay opacity syntax.
website/src/components/common/ActiveFilters.tsx Update rounding utility.
website/package.json Upgrade Tailwind/DaisyUI/Flowbite React; add Tailwind Vite plugin; pin Vite; adjust prettier ignore paths; add rationale comment.
website/package-lock.json Lockfile updates for upgraded dependencies and removed Astro Tailwind integration.
website/eslint.config.js Ignore Flowbite generated .flowbite-react/**.
website/astro.config.mjs Swap Astro Tailwind integration for @tailwindcss/vite plugin + Flowbite React Astro integration.
website/.prettierignore Ignore .flowbite-react/.
website/.gitignore Ignore Flowbite generated .flowbite-react/.
integration-tests/tests/fixtures/console-warnings.fixture.ts Add a new harmless console warning substring for test stability.
Comments suppressed due to low confidence (1)

website/src/components/SearchPage/fields/TextField.tsx:82

  • In the single-line path, the generated id is no longer passed into the FloatingLabel props (it was removed from standardProps, and inputProps doesn’t add it back). This can break label→input association and any behavior/tests that rely on a stable id. Consider passing id into inputProps (similar to the multiline/textarea branch) so both variants are consistently labeled.

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

corneliusroemer and others added 17 commits May 27, 2026 22:02
…ss renames

Ran `npx @tailwindcss/upgrade@latest --config tailwind.config.cjs --force`
to handle the automated parts of the Tailwind v3→v4 migration.

## Workarounds required to get the tool to run

The tool has two failure modes that had to be worked around:

1. **No CSS entry file**: The website uses `@astrojs/tailwind` which
   auto-injects the `@tailwind` directives, so there was no CSS file with
   `@tailwind base/components/utilities` for the tool to find. Fix: created
   a minimal `src/styles/base.css` with the three `@tailwind` directives so
   the tool had an entry point to work from.

2. **DaisyUI v4 plugin error**: Even with the CSS file, the tool crashed
   trying to evaluate `tailwind.config.cjs` because DaisyUI v4's plugin
   calls `addUtilities()` with media-query selectors that are invalid in the
   v4 evaluation context (`@media (min-width: 640px)` is not a valid utility
   selector). Fix: temporarily stripped DaisyUI and flowbite plugins from
   the config before running the tool, leaving only the color theme.

## What the tool did

- **52 template files migrated** (TSX + Astro): renamed deprecated utilities:
  - `flex-shrink-*` → `shrink-*`, `flex-grow-*` → `grow-*`
  - `shadow-sm` → `shadow-xs` (scale shift), bare `shadow` → `shadow-sm`
  - `rounded-sm` → `rounded-xs` (scale shift)
  - `overflow-ellipsis` → `text-ellipsis`
  - `outline-none` → `outline-hidden` (focus:outline-none cases)
  - CSS var arbitrary values `[--var]` → `(--var)` syntax
  - And others as flagged by the tool
- **Deleted `tailwind.config.cjs`** and migrated color theme into
  `@theme` block in `src/styles/base.css`
- **Deleted `src/styles/base.scss`** (it contained `@tailwind` directives
  which the tool treated as a duplicate entry point)
- **Deleted `src/styles/mdcontainer.scss`** (same reason — contained
  `@tailwind` directives via inherited scope)
- **Updated `tailwindcss`** in package.json: `^3.4.19` → `^4.3.0`

## What remains (follow-up commits)

- Restore and convert custom CSS from deleted `base.scss` into `base.css`
  (replacing SCSS `theme()` calls with CSS variables)
- Recreate `mdcontainer.css` from the deleted `mdcontainer.scss`
- Update all layout imports (`.scss` → `.css`)
- Replace `@astrojs/tailwind` with `@tailwindcss/vite` in astro.config.mjs
- Upgrade DaisyUI v4 → v5 and flowbite-react v0.10 → v1+
- Re-add plugins (DaisyUI, flowbite-react, @tailwindcss/forms) as CSS
  `@plugin` directives in `base.css`
- Apply known manual fixes for DaisyUI v5 regressions (dark mode variant,
  modal-box opacity, checkbox sizing, etc.)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…v0.12

Replace @astrojs/tailwind with @tailwindcss/vite for Tailwind v4 compatibility.
Convert base.scss to base.css using @import 'tailwindcss' and CSS-based plugin
declarations (@plugin 'daisyui', @plugin '@tailwindcss/forms'). Migrate DaisyUI
from v4 to v5 and flowbite-react from v0.10 to v0.12, using the official
flowbite-react Tailwind v4 integration (@import 'flowbite-react/plugin/tailwindcss'
+ @source '.flowbite-react/class-list.json'). Update all layout files to reference
the new .css extension.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…] context

DaisyUI v5 sets opacity:0 on .modal-box unless inside .modal[open]. Components
using react-confirm-alert render outside a .modal context, so replace .modal-box
with explicit styling. For EditDataUseTermsButton, fix the dialog element itself
to use .modal wrapper with .modal-box child so DaisyUI v5's [open] selector works.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wichMenu hydration mismatch

HeadlessUI v2 MenuButton requires ref forwarding when used as={NavigationTab}.
Convert NavigationTab from FC to forwardRef and pass ref to Button.

SandwichMenu used reference equality (organism === currentOrganism) which fails
after Astro JSON serialization creates separate object instances. Fix to key
comparison (organism.key === currentOrganism?.key).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DataUploadForm: flex-shrink-0 was renamed to shrink-0 in Tailwind v4; also add
checkbox-sm for consistent sizing. Table: add explicit w-4 h-4 to row-selection
checkbox to prevent layout shift on check/uncheck.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DateChangeModal: rename FlowbiteDatepickerTheme→DatepickerTheme, add required
'today' property to datepicker day items theme, fix bg-opacity-75→bg-gray-900/75.

TextField: replace removed getTheme() with direct floatingLabelTheme import,
remove helperText from theme override (no longer in FloatingLabelTheme v0.12),
don't pass id to FloatingLabel (v0.12 hardcodes htmlFor to its internal id,
causing label/input mismatch).

Also includes prettier formatting fixes in DataUseTermsSelector and DownloadButton.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tainer.css

Run `npx flowbite-react@latest init` which adds the Astro integration plugin
(auto-runs dev/build commands to regenerate .flowbite-react/class-list.json).
Gitignore class-list.json since it is auto-generated from component imports.
Commit config.json and init.tsx from the init command.

Convert mdcontainer.scss to mdcontainer.css (no SCSS features were used, plain
CSS with @apply works in Tailwind v4).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…support

Tailwind v4 requires @reference in secondary CSS files that use @apply, to
point to the main entry point where utilities are defined.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…upgrade

In Tailwind v3, the `transform` utility created a stacking context on the
DialogPanel, letting it render above the fixed backdrop. In Tailwind v4,
`transform` is a no-op unless a specific transform value is also set, so
the inline-block DialogPanel falls below the fixed backdrop in paint order,
making the overlay cover the content and block all clicks.

Fix: separate backdrop and content into their own fixed inset-0 containers,
with content coming after backdrop in DOM order.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The test-id needs to be on the DialogPanel so tests can locate it after
the backdrop/content restructuring.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wind v4

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
wrap-break-word is not a valid Tailwind class; replace with break-words.
Also fix standalone 'rounded' → 'rounded-sm' in FieldSelectorModal (TW v4
renamed the bare rounded utility).

These were missed because the tool only processes files reachable via the
CSS entry point's @source paths, and these files weren't in its scan scope.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ration tests

flowbite-react triggers a Vite 'has been externalized for browser compatibility'
warning. Add it to the harmless-messages list. Also commit the flowbite-react
.gitignore (ignores class-list.json and pid files).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@corneliusroemer corneliusroemer force-pushed the worktree-tailwind-v4-fresh branch from 0c9baaf to 4263fe6 Compare May 27, 2026 20:02
@theosanderson
Copy link
Copy Markdown
Member

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/dependabot.yml
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(nice work on the PR)
We should probably set up a corresponding PPX PR before we merge this

Comment thread .github/dependabot.yml
Comment thread website/package.json
"vite": "^6.4.2",
"vitest": "4.1.5"
},
"comments": {
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.

looking above vite is on v6.4?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

not sure i understand your point

--color-warning: #fbbd23;
--color-error: #f87272;
}

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.

Im a bit confused where the color-primary come from? I see that the colorTheme was in website/tailwind.config.cjs but not where the color-primary is from?

customTheme: {
                    'secondary': '#f000b8',
                    'accent': '#1dcdbc',
                    'base-100': '#ffffff',
                    'info': '#9ab9bd',
                    'success': '#36d399',
                    'warning': '#fbbd23',
                    'error': '#f87272',
                },

type='checkbox'
name='confirmation-no-pii'
className='mr-3 ml-1 h-5 w-5 rounded border-gray-300 text-primary-600 focus:ring-primary-600'
className='shrink-0 checkbox checkbox-sm mr-3 ml-1'
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.

this change is large - TODO: check if it looks different

{controls}
{content}
</DialogPanel>
<Dialog as='div' className='relative z-40' onClose={onClose}>
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.

TODO: check this

<div className='[&_label]:pointer-events-none my-1.5'>
<FloatingLabel
theme={{
helperText: {
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.

why is helperText removed from the theme?

Copy link
Copy Markdown
Contributor

@anna-parker anna-parker May 28, 2026

Choose a reason for hiding this comment

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

@corneliusroemer Im now looking too closely at checkboxes, but it looks like the shape is different? Oh also the color!

New:
Image

Old:
Image

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.

oh the color in the search bar has also changed - I think sth is wrong with the colors:
image

vs old:
image

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.

color in downloads has changed:
image
vs old:
image

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.

More color changes:
image
vs:
image

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.

styling of do you want to submit looks off:
image

tick boxes are now blue on review page:
image
vs:
image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Checkbox styling fixed by manually adding the global styles flowbite used to add.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Looking at it, we shouldn't really have cancel and confirm buttons both have primary colors... but that's for another time

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.

The sequences boxes are nolonger outlined when selected (also outline is bold and black and nolonger grey):

Image

vs old:

Image

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

yeah the tab class was renamed ugh - getting Claude to go through all the breaking changes of daisyui now. good spot

Copy link
Copy Markdown
Collaborator

@tombch tombch left a comment

Choose a reason for hiding this comment

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

This is looking great! Spotted some small style changes:

Before:

Image

After:

Image

Before:

Image

After:

Image

Before:

Image

After:

Image

Before:

Image

After (review use terms text larger):

Image

Copy link
Copy Markdown
Collaborator

@tombch tombch left a comment

Choose a reason for hiding this comment

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

Another one on the submit sequences page for the radio and checkboxes:

Before:

Image

After:

Image

Before:

Image

After:

Image

@corneliusroemer
Copy link
Copy Markdown
Contributor Author

corneliusroemer commented May 28, 2026

Thanks for all the reviews/spot-checks. Here are some findings from my investigations:

Difference in api-documentation padding of buttons:

Google Chrome 2026-05-28 17 03 43

this is due to tailwind 3->4 changes in space-y-4 class. It used to produce a selector .space-y-4>:not([hidden])~:not([hidden]) now it produces :where(.space-y-4>:not(:last-child)) this changes the margin from being applied to last instead of first button when wrapped. It seems we're maybe misusing the class - for normal usage there would be no change but in our case there is. In Codex words:

In v3, space-y-4 added margin-top to every sibling after the first. In v4, it adds margin-block-end to
every child except the last. For wrapped inline-blocks, that changes which line boxes get extra vertical space. So this is still a Tailwind v4 change, but this usage was relying on an implementation detail that Tailwind explicitly says space-* is not designed for: wrapped/complex layouts. The better fix is to use flex
wrapping with gap.

I've fixed this now in new commit.


Claude point 2 dropdown is false positive.

The organism tab losing hover css after click was a bug actually. Headless UI added inert because some ref wasn't forwarded (which we got a console warning about and which I hence fixed here on this branch). Side effect is that now no inert is added so hover remains active.

Old behavior is back with some extra CSS.


Claude point 3 dropdown differences: not sure about the element spacing but I noticed different padding in the text field. Lots of digging suggests flowbite used to inject global css rules for forms. That's no longer the case after upgrade (which is I think a good thing in principle, except for causing changes now).

I opened an issue on Flowbite React, it's not so clear what we should do here. Maybe copy over the old global styles for compatibility as our current design implicitly assumes these styles are present. Issue: themesberg/flowbite-react#1677

The textfield's height is different, now 40px down from 48px, this seems to be a change in DaisyUI's emitted CSS as we use input class. Border radius of text fields also changed because of DaisyUI changes.


Claude point 4 checkbox styling in download form: I traced this to the same global flowbite styles. Porting the previously applied global styles as custom CSS base style fixes it.

@theosanderson
Copy link
Copy Markdown
Member

Claude point 2 dropdown is false positive.

There is a difference here but Claude explains it badly. In the original once you click "Organisms" the border disappears, making you focus on the menu. In the new one it doesn't. It's very minor but I do think the original behaviour is slightly better. We can turn my comment here into an issue to address eventually.

Flowbite React v0.10 wired the standalone Flowbite Tailwind plugin, which emitted global form base styles by default. The Tailwind v4 Flowbite React CSS import no longer emits those reset rules, so raw form controls lost padding and checkbox/radio styling during the migration.\n\nAdd an explicit compatibility stylesheet with the old Flowbite form reset and import it from the main Tailwind entrypoint. Keep @tailwindcss/forms in class-only mode so this preserves the previous Flowbite behavior without switching to Tailwind Forms global base mode.
Headless UI now receives a forwarded ref for the organism menu button, so the button is no longer inert while the menu is open. Preserve the previous visual behavior explicitly by using the parent menu's data-open state to cancel inactive hover styling on the button while the menu is expanded.
@corneliusroemer
Copy link
Copy Markdown
Contributor Author

@anna-parker noticed that colors were different. This is because TW4 uses var(--color-primary) and while we set that variable it gets overridden by DaisyUI v5.`

Solution is to opt out of Daisy's default theme and use our own colors. That seems to fix things.

corneliusroemer and others added 2 commits May 28, 2026 19:30
Tailwind v4 emits color utilities through CSS variables, so focus:border-primary now resolves through --color-primary instead of compiling to a fixed RGB value. daisyUI v5 also writes --color-primary from its default light theme, which caused those utilities to pick up daisyUI's default purple instead of the Loculus primary color.

Disable daisyUI's implicit built-in theme emission and add an explicit default light daisyUI theme that mirrors the Loculus color tokens used by Tailwind. This keeps daisyUI components configured while preserving the color assumptions from the Tailwind v3 setup.
Tailwind v4 is configured in CSS rather than a JS config, so the palette
that used to live in `colors.json` now lives in the `@theme` block in
`base.css` as the single source of truth. The comment there documents how
to re-skin the instance (edit `--color-primary-*`).

Components that imported `colors.json` now read the palette at runtime via
`getThemeColor()` (SeqSetItem plots) or reference `var(--color-primary-*)`
directly (OrganismSubmenu fly animation).

daisyUI v5 renamed its semantic colors to `--color-*`, sharing Tailwind's
namespace, so `--color-primary` now backs both daisyUI components and the
`text-primary`/`border-primary` utilities. The daisyUI theme customizes the
built-in `light` theme (inheriting neutral/base/content defaults) and pins
`--color-primary` to the 400 token, so bare primary utilities keep resolving
to #88a1d2. `--color-main` and `--color-logoSecondary` reference the 600 token
instead of duplicating its hex.

Drop the redundant `btn-primary` from GroupForm's submit button: it was the
only `btn-primary` in the codebase and was fully overridden by `loculusColor`
+ `text-white`, matching the ~18 sibling `btn loculusColor text-white` buttons.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@corneliusroemer
Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request by using thet updated versions of all packages, i.e. updates on main and updates here

The Tailwind v4 / daisyUI v5 upgrade replaced `.modal-box` with hand-rolled
Tailwind classes in ConfirmationDialog and RevokeButton, instead of fixing the
root cause.

daisyUI v5 sets `opacity: 0` on `.modal-box` unless it has an open `.modal`
ancestor (`.modal.modal-open .modal-box`, `.modal[open] .modal-box`, etc.). The
EditDataUseTermsButton dialog was migrated correctly (wrapping `.modal-box` in a
`<dialog className='modal'>`), but the two react-confirm-alert dialogs render
their content inside react-confirm-alert's own overlay, not a `.modal`, so the
box was hidden — hence the Tailwind workaround.

Fix it properly by giving react-confirm-alert's overlay the `modal modal-open`
classes via its `overlayClassName` prop. The overlay then satisfies daisyUI's
`.modal.modal-open .modal-box` selector and the box renders. The overlay's own
`.react-confirm-alert-overlay` rules are unlayered, so they override daisyUI's
layered `.modal` backdrop/positioning — the overlay keeps its existing white
backdrop, flex centering, and click-outside behaviour (which keys off
`e.target === overlay`, still the same element). `.modal-box` is restored
verbatim, matching how it was used on main under daisyUI v4.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@theosanderson theosanderson mentioned this pull request May 28, 2026
Resolve website/package.json by keeping the newest of each dependency from
both sides (fflate 0.8.3, sass 1.100.0, yaml 2.9.0 from main; flowbite-react
0.12.17, tailwindcss 4.3.0, daisyui 5 from this branch). Kept this branch's
deliberate vite ^6.4.2 pin (Astro 5 / production Docker esbuild fix, see the
package.json "comments" block) rather than main's vite 7, and took main's
newer vitest 4.1.7.

package-lock.json regenerated from scratch against the merged package.json.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@corneliusroemer corneliusroemer changed the title chore(website): migrate tailwind to v4, daisyui to v5 and flowbite to v0.12 chore(website): migrate tailwind to v4, daisyui to v5 and flowbite-react to v0.12 May 28, 2026
corneliusroemer and others added 2 commits May 29, 2026 01:18
The merge of origin/main regenerated website/package-lock.json and floated
the direct dependency `astro` from 5.17.1 to 5.18.2 (allowed by the ^5.17.1
range). Astro 5.18 enforces host-header-injection protection: it ignores the
Host / X-Forwarded-Host headers unless `security.allowedDomains` is configured
and falls back to the literal "localhost". As a result Astro.url resolved to
https://localhost/..., so the Keycloak login link's redirect_uri became
https://localhost/... and Keycloak rejected it with invalid_redirect_uri (400).

Regenerate the lockfile from main's baseline so astro stays at 5.17.1 (matching
main) while keeping only the intended Tailwind-v4 / flowbite-react / vite-6
deltas. No package.json change.

Follow-up for the eventual move to astro >=5.18: add
`security: { allowedDomains: [{}] }` to astro.config.mjs (the documented
allow-all for trusted reverse proxies with dynamic domains).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Tailwind v3 -> v4 upgrade swapped Tailwind's emulated layering for
native CSS @layer. Under v3, precedence was specificity-first (source order
only as a tiebreaker); under v4, layer order is the PRIMARY sort key and
beats specificity outright. The layer order is `base < daisyui < utilities`.

That single change silently broke the coexistence of our Flowbite form
reset (broad `[type=...]` selectors in flowbite-forms-compat.css) and
daisyUI's own form components (`.checkbox`, `.radio`, `.select`, `.input`).
On v3 the numbers happened to line up so one rule (specificity-first) gave
both behaviours we wanted; v4's stricter model can't express them with
layer placement alone. Fixes here:

* Checkbox/radio checked state (the `:not()` hack):
  - The compat `:checked` rules must beat Tailwind `bg-*` utilities (Flowbite
    markup ships `bg-gray-100`, which otherwise hides the dot/checkmark), so
    they have to live in `@layer utilities`.
  - But in `utilities` they then also beat daisyUI's own `.checkbox`/`.radio`,
    painting the Flowbite SVG on top of daisyUI's mark (two stacked
    checkboxes on the "strict" date filter / "include sublineages").
  - We need the rules ABOVE utilities yet BELOW daisyui, but utilities is
    above daisyui, so no single layer works. Resolved by scoping the
    selectors with `:not(.checkbox)` / `:not(.radio)` to opt daisyUI's own
    components out entirely. This hand-rebuilds the carve-out that v3's
    specificity-first cascade produced for free.

* Checkbox custom colors (v4 vars removed in v5):
  --chkbg / --chkfg no longer exist. v5 reads the checked box color from
  --input-color and fills the checkmark ::before with currentColor, so
  `[--chkbg:white]` -> `checked:[--input-color:white]` (scoped to :checked
  so the unchecked border keeps daisyUI's light default) and
  `[--chkfg:gray-700]` -> `text-gray-700`. (DateRangeField, LineageField.)

* Select focus weight:
  daisyUI v5 ramps the focus border to full-opacity base-content plus a
  matching 2px outline (a heavy "double border"); v4 used base-content/.2.
  Both lines derive from --input-color, so a single focus override restores
  the subtler v4 ring (base.css).

* daisyUI v5 class/var renames carried over:
  tabs-lifted -> tabs-lift; removed select-bordered / input-bordered (border
  is default in v5); rounded-btn -> rounded-field; label-text -> text-sm
  (class deleted in v5); removed the dead --animation-btn theme var.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Triggers a deployment to argocd website Tasks related to the web application

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade daisyui from v4 to v5 Bump flowbite Updating tailwindcss to v4, @astrojs/tailwind now deprecated

5 participants