Mantine migration - #2339
Open
ReDBrother wants to merge 46 commits into
Open
Conversation
Infra (Phase 0): add @mantine/core + @mantine/hooks v9, PostCSS setup, CSS-layer coexistence with Bootstrap, dark theme, MantineProvider on all React roots. Spacing scale matched to Bootstrap-4 spacers. Components (Phase 1): replace all react-bootstrap components with Mantine equivalents behind compatible wrappers (CbModal, PopoverStickOnHover); remove the react-bootstrap dependency. Global Bootstrap CSS stays for .heex templates (Phase 3). Co-Authored-By: Claude <noreply@anthropic.com>
First Phase 2 slice: replace Bootstrap utility classes with idiomatic Mantine primitives in the low-risk presentational leaves. - Card: Container + Paper + Title - Loading: Center + Loader - InfoMessage / SystemMessage / MessageTimestamp: Group + Text (semantic status colors mapped to theme tokens) - ResultIcon: Box-wrapped icon for spacing/color Tests that mount these leaves (directly or via Message) now wrap in MantineTestProvider; DOM-class assertions retargeted to behavior. Co-Authored-By: Claude <noreply@anthropic.com>
Second Phase 2 slice of clean, self-contained leaves: - OnlineContainer: Text (c="dimmed") - Editor: Box for the Vim status bar (bg/c props) - GamesHeatmap: Mantine Card in place of Bootstrap card/card-body Co-Authored-By: Claude <noreply@anthropic.com>
Align Mantine's default border color with the app's $cb-border-color (#4c4c5a) via cssVariablesResolver, wired into the app provider and the test provider. Now `<Paper withBorder radius="md">` reproduces the legacy `.border.cb-border-color.cb-rounded` panels (cb-rounded = 0.5rem = md). First consumer: TournamentPreviewPanel → Box + Paper(withBorder) + Stack. Co-Authored-By: Claude <noreply@anthropic.com>
- PlayerLoading: Mantine Loader (visibility toggle replaces `invisible`), keeps `cb-player-loading` positioning - EditorLoading: Mantine Flex overlay (display toggle replaces d-flex/ d-none), keeps `cb-loading-background` Presentational tests retargeted from Bootstrap-size/class assertions to behavior (role present, visibility/display). Co-Authored-By: Claude <noreply@anthropic.com>
- UserAchievements: Box (mt="sm"), keeps cb-achievements-grid - MessageTag: Text (fw/mr), keeps cb-private-text - TournamentTimer: Text (inline-flex, monospace, c="yellow") - GameLevelBadge: Box (p/ta), keeps bg-gray + cb-rounded Wrapped the tests that mount these (directly or transitively) in MantineTestProvider. Co-Authored-By: Claude <noreply@anthropic.com>
Grade rows → Flex (responsive column→row), highlights → Stack, headings → Text. The `.card.cb-card` ranking panel is left as Bootstrap: its styling is keyed on the card/card-header/card-body structure and needs a browser pass to convert alongside the card theming (documented in-file). Co-Authored-By: Claude <noreply@anthropic.com>
Header row → Group (bottom border via themed default-border), "Clean banned" admin action → Mantine Button (subtle/red). Rooms child unchanged. Co-Authored-By: Claude <noreply@anthropic.com>
- Message: header/body layout → Flex/Stack/Group/Text; ban + delete icon-buttons → ActionIcon (behavior covered by ChatMessageDelete / TournamentChatMessage tests). Keeps cb-username-max-length, cb-private-text, cb-tournament-chat-ban, cb-chat-message-delete. - Messages: list container + scroll button → Box (props for pos/spacing/ overflow, visibility toggle replaces `invisible`). Keeps cb-messages-list, cb-bg-secondary, scroll-button, list-unstyled. Chat layout still needs a browser QA pass (flex spacing, scroll button, username truncation). Co-Authored-By: Claude <noreply@anthropic.com>
Mark Phase 2 in progress, log the 20 converted leaf components and the remaining (theming/framework-coupled) leaves, document the border-token theme work, and add gotchas for unlayered-Bootstrap radius overrides and grep over-counting. Co-Authored-By: Claude <noreply@anthropic.com>
- UserName/UserLabel: layout → Group/Text (drop d-flex/align-items/mr-*/ text-truncate); keep cb-user-online/cb-user-dark-offline/cb-text/ x-username-truncated design classes. - UserStats: container/row/col + flex layout → Box/Stack/Group/Text; StatsRow grid wrapper → Box with c/fz; play + follow icon-buttons → ActionIcon (text-primary/muted/danger → c props). Keeps cb-rounded avatar. - UserInfo: John Doe / id=0 fallbacks → Text. Keeps the string className/ linkClassName passthrough API (~12 page callers still pass BS color classes; cleaned when pages convert). - Wrap UserName.test in MantineTestProvider (gotcha #1). Toolchain-verified (typecheck/vitest/build/lint); still needs manual browser QA (avatar rounding, stat grid, follow/play buttons, truncation). Co-Authored-By: Claude <noreply@anthropic.com>
Swap Bootstrap positioning/overflow utilities (position-*, h-100, z-3, start-0/end-0/top-0, d-block/d-none, pb-2) for Mantine Box/Flex + style props, and the icon-only scroll btns for UnstyledButton. Gradient cb-left/right-scroll-control design classes are kept. Co-Authored-By: Claude <noreply@anthropic.com>
Swap d-flex→Flex and pr-2/pl-2 spacing→Group gap. Replace the
div role="button" .btn-link prev/next controls with real
UnstyledButton c="white", dropping the manual role/tabIndex/onKeyPress
a11y shims and the custom .btn-link{color:white} override.
Co-Authored-By: Claude <noreply@anthropic.com>
…e 2) Port .cb-btn-secondary's lighten-on-hover into the theme via Button.extend vars keyed on color="cbSecondary", then drop the Bootstrap button classes from Rooms so it renders as pure Mantine. Co-Authored-By: Claude <noreply@anthropic.com>
…ase 2) Convert InvitesList + InvitesContainer layout/buttons/badges to Mantine primitives (Flex/Group, Button variant="outline", Badge, VisuallyHidden), keeping cb-btn-outline-secondary so the secondary buttons' look is preserved. Wrap the empty-invites Localization test in MantineTestProvider. Delete DropdownMenuDefault, which had no consumers anywhere in js/. Co-Authored-By: Claude <noreply@anthropic.com>
Only SubMenu + Item are rendered (by game Output), so delete the dead root/Menu/renderFirstAssert/getMessage and collapse the export to a plain namespace. Convert the live parts to Mantine (Box/Flex/Badge/Button/Collapse/ Text), preserving the replayer font zoom via a fontSize->rem map. Co-Authored-By: Claude <noreply@anthropic.com>
Trigger + Type radio buttons -> Mantine Button (filled/outline, color=cbSecondary), form-group/label/textarea -> Text label + Textarea. Add explicit tabIndex to the role=radio buttons since oxlint can't infer focusability of a custom component. Co-Authored-By: Claude <noreply@anthropic.com>
Port the shared .alert-dark-theme gradient design out of SCSS into a reusable darkThemeAlertStyles(status) helper in ui/alert.ts, and use it on the Mantine Alert instead of the Bootstrap alert class set. The three other dark-theme alerts can adopt the same helper as their pages convert. Co-Authored-By: Claude <noreply@anthropic.com>
7 leaves left: 3 cleanly convertible (ChatInput, SeasonLeaderboard, PlayerInsightsModal), 3 blocked on a lib/behavior decision, 1 Phase 3. Note ChatInput as newly surfaced and list audit false positives. Co-Authored-By: Claude <noreply@anthropic.com>
Replace the Bootstrap input-group form with a Mantine Flex + TextInput + Buttons for both the default and tournament chat composers. Drop the cb-btn-secondary class from the default send button (hover now comes from the theme); keep the cb-tournament-chat-* design classes. The is-invalid / invalid-tooltip validation becomes TextInput error + an absolute Text overlay. Wrap TournamentChatInput.test in MantineTestProvider. Co-Authored-By: Claude <noreply@anthropic.com>
Swap the Bootstrap table, hand-rolled pagination, filter bar and native selects for Mantine Table/Pagination/NativeSelect/Grid, keeping the cb-custom-event-* and cb-season-filter-* design classes. The dead bi bi-* Bootstrap-Icons (no bootstrap-icons package is imported) become FontAwesome icons. Exported helper functions that PlayerInsightsModal still consumes are left untouched. Co-Authored-By: Claude <noreply@anthropic.com>
Port all Bootstrap layout/utility markup in the season player-stats modal to Mantine (Grid, Group, Card, Table, Badge, Button toggle tabs, Alert, Text), keeping the cb-bg-panel design class and every Recharts chart untouched. Place badges use a local Mantine color map instead of the Bootstrap-class helper, which stays exported for the still-Bootstrap HallOfFamePage. Drop the dead modal-90w class in favor of Mantine size="90%". Co-Authored-By: Claude <noreply@anthropic.com>
Both keep their non-Mantine libraries (native <select> listbox / react-contexify) by design; only the Bootstrap utility classes are removed. EmojiTooltip's classes become an inline style with an explicit dark background. ChatContextMenu's load-bearing text-white / mr-2 utilities become inline color/margin tokens at the same elements so they still beat react-contexify's own item styling. Co-Authored-By: Claude <noreply@anthropic.com>
First Phase 2 page slice: UserSettings + UserSettingsForm + EmailSettingsForm. Formik inputs → Mantine TextInput, Menu triggers → Button, submit buttons → brand-colored Button with loading state, Notification → darkThemeAlertStyles. Kept the native range slider and cb-settings-* design classes; retargeted the .cb-settings-social-links card selector off the Bootstrap .d-flex class. Co-Authored-By: Claude <noreply@anthropic.com>
UserStatCharts row/col → Grid; UserTournaments table → Mantine Table (row borders now use the resolved default border = cb-border-color, so per-cell classes dropped); Heatmap responsive header → Flex + NativeSelect. Kept the scroll container, infinite-scroll behavior, CalendarHeatmap, and cb-* design classes (incl. cb-profile-heatmap-select). Co-Authored-By: Claude <noreply@anthropic.com>
Sidebar row/col → Grid; rewrote the Bootstrap-JS tab system (nav-tabs/tab-pane/ data-toggle) as a controlled Mantine Tabs with keepMounted panels, removing the page's dependency on Bootstrap's tab plugin. Pills/links → Anchor/Box + style props. Kept .h1/.lead typography classes (coupled to responsive cb-* overrides) and cb-* design classes. UserProfile.test now wraps in MantineTestProvider. Co-Authored-By: Claude <noreply@anthropic.com>
LiveTournaments + CompletedTournaments tables → Mantine Table with responsive display/hiddenFrom for the desktop-table vs mobile-card split. ShowButton and TournamentCard left as Bootstrap pending the shared-ShowButton slice (coupled to GameActionButton and its test). Recorded lobby progress + couplings in the spec. Co-Authored-By: Claude <noreply@anthropic.com>
Shared "Show" anchor → Mantine Button component="a" (color cbSecondary). Safe standalone leaf — no test renders it provider-less. Updated the lobby progress notes: GameActionButton (tooltips/btn-group/data-methods) + GameCard + TournamentCard remain as the next slice. Co-Authored-By: Claude <noreply@anthropic.com>
…ase 2) Shared game-button cluster: ContinueButton/Fight/Sign-in → Mantine Button (keeping Phoenix data-method/data-to); waiting-opponent btn-group → Group with tooltip-wrapped ActionIcons (Bootstrap-JS tooltips → Mantine Tooltip; cancel keeps btn-hover for the game-item:hover reveal). GameCard/TournamentCard layout → Flex/Paper keeping cb-*/game-item/bg-gray design classes. GameActionButton.test wrapped in MantineTestProvider; w-100 assertion → data-block. Co-Authored-By: Claude <noreply@anthropic.com>
Players emits raw <td> cells inside ActiveGames' <tr>, so it must convert to Table.Td in the same slice as the ActiveGames/CompletedGames tables. Co-Authored-By: Claude <noreply@anthropic.com>
ActiveGames + CompletedGames tables → Mantine Table (desktop display / mobile hiddenFrom card split); Players now emits Table.Td via Table context. Kept the scroll container + infinite scroll, game-item hover coupling, and cb-* design classes; per-cell cb-border-color dropped (Mantine row borders resolve to it). Co-Authored-By: Claude <noreply@anthropic.com>
Raw table markup → Table.*; Bootstrap-JS nav-tabs period selector → controlled Mantine SegmentedControl bound to the Redux period (fixes the hardcoded-active state). Kept cb-bg-panel/cb-border-color; dropped per-row border classes. Co-Authored-By: Claude <noreply@anthropic.com>
GameRoomPreview: container-fluid/w-100/d-flex → Box/Flex, kept preview BEM classes. LobbyLoading skeleton: col-in-flex responsive grid → Flex/Box responsive props, sr-only → VisuallyHidden, kept all cb-lobby-loading-*/cb-text-skeleton design classes. Co-Authored-By: Claude <noreply@anthropic.com>
Player-select rows: div[role=button] + a11y shims → native Mantine Button (color=cbSecondary), dropping role/tabIndex/onKeyPress; d-flex flex-column → Stack. Co-Authored-By: Claude <noreply@anthropic.com>
Layout utilities → Flex/Box + style props; root border card → Paper withBorder radius="md" (theme resolves cb-border-color); main action <a> → Button component="a" color=cbSecondary; info icon <button> → ActionIcon (kept cb-tournament-info-icon-btn sizing + cb-btn-outline- secondary color); text-white → c="white". Kept all cb-tournament-* design classes and Bootstrap typography (h5) / text-warning icons. Co-Authored-By: Claude <noreply@anthropic.com>
Two-column responsive layout + nearby-users/stat panels: d-flex/flex-* → Flex/Box with responsive direction/w/p/m props; col-12/col-lg-8/-4 → responsive w percentages; action btn anchors → Button component="a" color=cbSecondary fullWidth; text-white → c="white"; avatar rounded-circle → inline borderRadius. Kept all cb-*/stat-*/clan-* design classes, Bootstrap typography (h1/h4), and User* passthrough props. text-primary "add clan" link → Anchor (brand orange). Test wraps in MantineTestProvider. Co-Authored-By: Claude <noreply@anthropic.com>
Rewrote the Bootstrap-JS collapse/accordion (data-toggle/data-parent) as a controlled Mantine Collapse (outer "See Rules & Details" toggle) wrapping a single-open Accordion (variant="separated", defaultValue= "overview"). card/card-header/card-body → Accordion.Item/Control/Panel; row/col-md-6 → Grid/Grid.Col; text-white → c="white" on panels; btn btn-secondary → Button color=cbSecondary. Removes this component's dependency on Bootstrap's JS collapse plugin. Kept cb-bg-panel/ cb-bg-highlight-panel/cb-rounded design classes. Co-Authored-By: Claude <noreply@anthropic.com>
…e conversions (Phase 2) Co-Authored-By: Claude <noreply@anthropic.com>
Title/body/footer layout → Flex/Text/Title + style props; the footer
"Open Tournament" anchor (btn + invalid disabled-attr hack + cn) →
Button component="a" color=cbSecondary disabled={isUpcoming}; body
position-relative → style prop. Left the TournamentPreviewPanel /
TournamentDescription passthrough classNames as documented leftovers
(both only accept className, applied to a Box).
Co-Authored-By: Claude <noreply@anthropic.com>
Card/columns/sidebar layout → Flex/Box + style props (responsive direction for the column→row breakpoint); the two icon-only action btns → ActionIcon variant="transparent" (envelope icon gets c="white" in place of the FontAwesome text-white); online-count p → Text. Kept all cb-lobby-*/cb-players-container/cb-border-color design classes and the responsive rounded-*/h-sm-100/pb-sm-4 utilities. ChatUserInfo's mb-1 passthrough replaced by wrapping each row in Box mb="xs"; left Messages' text-white passthrough (theme default isn't pure white). Co-Authored-By: Claude <noreply@anthropic.com>
row/col grids → Grid/Grid.Col (span responsive, gap="xs" — note this
build's Grid uses `gap`, not `gutter`); the Level/GameType toggle
<button>s → Mantine Button keeping the bg-orange/btn-outline-orange/
bg-gray design colors via conditional className (dropped btn/border-0/
cb-rounded/w-100; level buttons keep title for getByTitle, dropped the
Bootstrap-JS data-toggle tooltip); footer btn → Button color=cbSecondary;
h5 → Title order={5}. Kept the native range input (+ cb-range) and both
react-select widgets (OpponentSelect AsyncSelect + TaskChoice) untouched
for the future one-PR lib swap. Test wraps in MantineTestProvider.
Co-Authored-By: Claude <noreply@anthropic.com>
Create/Join/Continue/experimental game btns → Mantine Button color=cbSecondary (removed the module-level cn className consts); the controls Stack + bottom two-column layout → Flex/Box with responsive direction/w/p props (col-12 col-lg-8/-4 → responsive w percentages); dropped the text-white passthrough on the (forced-dark) CbModal headers/bodies, kept cb-border-color. Completes the lobby page's own React markup; remaining lobby lib-swap items (TaskChoice + the CreateGameDialog react-selects) stay for the one-PR swap. Co-Authored-By: Claude <noreply@anthropic.com>
…ersions (Phase 2) Lobby React markup is fully converted; only the deferred react-select lib swap remains. Update the Phase-2 status row and lobby section. Co-Authored-By: Claude <noreply@anthropic.com>
Fixes a pre-existing suite failure: the "lobby loading shell" case rendered the (already Mantine-converted) LobbyLoading without a MantineProvider. Full frontend suite now green (166 tests). Co-Authored-By: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
DON'T MERGE IT