From f7bf5218e47746d649cf74627de3d7fc5ea82a46 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 20:53:41 -0400 Subject: [PATCH 01/11] Run @mui/codemod v5 preset-safe and swap @material-ui for @mui Mechanical rename of @material-ui/core, @material-ui/lab, and @material-ui/styles imports to their @mui/* equivalents. Adds Emotion (MUI v5's default styling engine) and keeps @mui/styles as a JSS shim so the existing makeStyles/withStyles call sites keep working. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.json | 8 +- src/components/AppWrap.tsx | 8 +- src/components/about/AboutPageView.tsx | 7 +- src/components/about/FeedbackForm.tsx | 5 +- src/components/about/FeedbackModal.tsx | 5 +- src/components/about/FeedbackToggle.tsx | 6 +- src/components/about/WaysToHelp.tsx | 5 +- src/components/about/WelcomeDialog.tsx | 17 +- src/components/about/WelcomeFooter.tsx | 6 +- src/components/config/theme.ts | 51 +- src/components/context/ProvidersWrap.tsx | 19 +- src/components/details/Chips.tsx | 6 +- src/components/details/DetailedIntro.tsx | 6 +- src/components/details/DetailsPanel.tsx | 2 +- src/components/details/EndoImageWrap.tsx | 3 +- src/components/details/LocationLink.tsx | 6 +- src/components/details/MoreLikeThis.tsx | 4 +- src/components/details/NeighborhoodList.tsx | 6 +- src/components/details/RandomLinkBtn.tsx | 2 +- src/components/details/styles.ts | 5 +- src/components/explore/BasicExploreIntro.tsx | 6 +- src/components/explore/Breadcrumbs.tsx | 8 +- src/components/explore/CardList.tsx | 5 +- src/components/explore/CensusPopover.tsx | 6 +- src/components/explore/ClearSelectionBtn.tsx | 2 +- src/components/explore/CustomCard.tsx | 6 +- src/components/explore/LayerToggle.tsx | 8 +- .../explore/NeighborhoodsInstance.tsx | 10 +- .../explore/PanelIntroTitleSubtitle.tsx | 6 +- src/components/explore/StatsAndMeta.tsx | 5 +- src/components/generic/BackToTopBtn.tsx | 15 +- src/components/generic/Explanation.tsx | 6 +- src/components/generic/FancyHorizRule.tsx | 5 +- src/components/generic/Logo.tsx | 4 +- .../generic/MarkdownWithRouteLinks.tsx | 2 +- src/components/generic/ReadMore.tsx | 6 +- src/components/generic/ShareButtons.tsx | 4 +- src/components/generic/ShareButtonsWrap.tsx | 6 +- src/components/generic/SimplePopover.tsx | 8 +- src/components/generic/SlideDown.tsx | 5 +- src/components/generic/SubtleText.tsx | 6 +- src/components/generic/ToggleWithHelper.tsx | 6 +- src/components/generic/ToggleableSection.tsx | 3 +- src/components/generic/hooks.ts | 2 +- .../generic/modals/DialogCloseBtn.tsx | 7 +- .../generic/modals/LoadingBackdrop.tsx | 6 +- .../generic/modals/LoadingIndicator.tsx | 6 +- .../generic/modals/LoadingTextOnElem.tsx | 6 +- .../generic/modals/SimpleDialog.tsx | 13 +- src/components/generic/modals/SlideUp.tsx | 4 +- src/components/home/ClearFiltersBtn.tsx | 2 +- src/components/home/FiltersWarning.tsx | 6 +- src/components/home/ListboxComponent.tsx | 2 +- src/components/home/OmniboxResult.tsx | 6 +- src/components/home/SearchByOmnibox.tsx | 10 +- src/components/home/utils.tsx | 4 +- src/components/legend/LangPointsToggle.tsx | 9 +- src/components/legend/LayerLabelSelect.tsx | 2 +- src/components/legend/LayerSymbSelect.tsx | 2 +- src/components/legend/Legend.tsx | 6 +- src/components/legend/LegendPanel.tsx | 6 +- src/components/legend/LegendSwatch.tsx | 6 +- src/components/legend/WorldRegionMap.tsx | 7 +- src/components/legend/config.ts | 2 +- src/components/local/CensusAutoZoomToggle.tsx | 2 +- src/components/local/CensusFieldSelect.tsx | 10 +- src/components/local/CensusTogglesWrap.tsx | 7 +- src/components/local/LegendGradient.tsx | 5 +- src/components/map/BaseLayerToggles.tsx | 6 +- src/components/map/GeocodeMarker.tsx | 6 +- src/components/map/GeocoderPopout.tsx | 5 +- src/components/map/MapCtrlBtns.tsx | 8 +- src/components/map/MapOptionsMenu.tsx | 6 +- src/components/map/MapPopup.tsx | 8 +- src/components/media/Media.tsx | 6 +- src/components/media/MediaModal.tsx | 13 +- src/components/nav/AboutLinkAsIcon.tsx | 3 +- src/components/nav/BottomNav.tsx | 17 +- src/components/nav/Nav.tsx | 6 +- src/components/nav/OffCanvasNav.tsx | 6 +- src/components/nav/Settings.tsx | 6 +- src/components/nav/TopBar.test.tsx | 4 +- src/components/nav/TopBar.tsx | 6 +- src/components/panels/NavItemWithBadge.tsx | 8 +- src/components/panels/PanelCloseBtn.tsx | 6 +- src/components/panels/PanelHeading.tsx | 6 +- src/components/panels/PanelTitleBar.tsx | 10 +- src/components/panels/PanelTitleRoutes.tsx | 8 +- src/components/panels/PanelWrap.tsx | 14 +- src/components/panels/SearchTabs.tsx | 14 +- src/components/panels/ShowPanelBtn.tsx | 10 +- src/components/panels/SplitCrumbs.tsx | 6 +- src/components/panels/TabPanel.tsx | 7 +- src/components/panels/TimelineCrumbs.tsx | 6 +- src/components/results/Cells.tsx | 9 +- .../results/CountryListItemWithFlag.tsx | 7 +- src/components/results/EndoImageModal.tsx | 8 +- src/components/results/MediaColumnFilter.tsx | 6 +- src/components/results/RecordDescription.tsx | 6 +- src/components/results/ResultsModal.tsx | 2 +- src/components/results/ResultsTitle.tsx | 8 +- src/components/results/ResultsToolbar.tsx | 6 +- src/components/results/styles.ts | 11 +- src/components/results/utils.tsx | 2 +- .../style-guide/DemoBreadcrumbs.tsx | 6 +- src/components/style-guide/DemoBtns.tsx | 14 +- src/components/style-guide/DemoCard.tsx | 15 +- src/components/style-guide/DemoColors.tsx | 2 +- src/components/style-guide/DemoSplitBtn.tsx | 16 +- src/components/style-guide/DomElements.tsx | 2 +- src/components/style-guide/StyleGuide.tsx | 10 +- .../form-inputs/DemoCheckboxes.tsx | 10 +- .../form-inputs/DemoNativeSelects.tsx | 14 +- .../style-guide/form-inputs/DemoRadios.tsx | 10 +- .../form-inputs/DemoRangeSlider.tsx | 6 +- .../style-guide/form-inputs/DemoSwitches.tsx | 6 +- .../form-inputs/DemoTextFields.tsx | 16 +- src/utils.ts | 2 +- yarn.lock | 564 +++++++++++++----- 119 files changed, 934 insertions(+), 478 deletions(-) diff --git a/package.json b/package.json index 76a29175..6999f4bf 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,11 @@ "version": "0.1.0", "private": true, "dependencies": { - "@material-ui/core": "^4.10.2", - "@material-ui/lab": "^4.0.0-alpha.56", + "@emotion/react": "^11.11.4", + "@emotion/styled": "^11.11.5", + "@mui/lab": "^5.0.0-alpha.176", + "@mui/material": "^5.16.7", + "@mui/styles": "^5.16.7", "@sentry/react": "^5.24.2", "@testing-library/jest-dom": "^5.11.0", "@testing-library/react": "^10.4.5", @@ -87,7 +90,6 @@ ] }, "peerDependencies": { - "@material-ui/styles": "^4.10.0", "clsx": "^1.1.1", "filefy": "^0.1.10", "history": "^5.0.0", diff --git a/src/components/AppWrap.tsx b/src/components/AppWrap.tsx index 9d5c90c9..17677ad3 100644 --- a/src/components/AppWrap.tsx +++ b/src/components/AppWrap.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { InteractiveMap } from 'react-map-gl' -import { Hidden } from '@material-ui/core' +import { Hidden } from '@mui/material' import { panelWidths } from 'components/panels/config' import { PanelWrap, usePanelState, ShowPanelBtn } from 'components/panels' @@ -45,7 +47,7 @@ const useStyles = makeStyles((theme: Theme) => [theme.breakpoints.up('xl')]: { left: (props: Style) => (props.open ? panelWidths.midLarge : 0), }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { top: PANEL_TITLE_BAR_HT_MOBILE, width: '100%', bottom: (props: Style) => diff --git a/src/components/about/AboutPageView.tsx b/src/components/about/AboutPageView.tsx index 88ac403f..d4ef2d5a 100644 --- a/src/components/about/AboutPageView.tsx +++ b/src/components/about/AboutPageView.tsx @@ -1,6 +1,9 @@ import React, { FC } from 'react' import { useQuery } from 'react-query' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { LoadingIndicator } from 'components/generic/modals' import { AboutPageProps, WpApiPageResponse } from './types' @@ -19,7 +22,7 @@ const useStyles = makeStyles((theme: Theme) => boxShadow: theme.shadows[8], // Prevent screenshots from getting lost in Paper bg if same color: // outline: 'solid 1px hsl(0deg 0% 40%)', - [theme.breakpoints.down('xs')]: { + [theme.breakpoints.down('sm')]: { margin: '0.5rem 0', }, }, diff --git a/src/components/about/FeedbackForm.tsx b/src/components/about/FeedbackForm.tsx index 791de7b0..bbb74ba5 100644 --- a/src/components/about/FeedbackForm.tsx +++ b/src/components/about/FeedbackForm.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/about/FeedbackModal.tsx b/src/components/about/FeedbackModal.tsx index a59f3722..814e2fce 100644 --- a/src/components/about/FeedbackModal.tsx +++ b/src/components/about/FeedbackModal.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { SimpleDialog } from 'components/generic/modals' import { FeedbackForm } from 'components/about' diff --git a/src/components/about/FeedbackToggle.tsx b/src/components/about/FeedbackToggle.tsx index c09d3b15..4ce6b2db 100644 --- a/src/components/about/FeedbackToggle.tsx +++ b/src/components/about/FeedbackToggle.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button } from '@mui/material' import { FeedbackModal } from 'components/about' import { Explanation, UItextFromAirtable } from 'components/generic' diff --git a/src/components/about/WaysToHelp.tsx b/src/components/about/WaysToHelp.tsx index 50591597..0146328e 100644 --- a/src/components/about/WaysToHelp.tsx +++ b/src/components/about/WaysToHelp.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { BasicExploreIntro } from 'components/explore' import { UItextFromAirtable } from 'components/generic' diff --git a/src/components/about/WelcomeDialog.tsx b/src/components/about/WelcomeDialog.tsx index 11d3b565..50f572ca 100644 --- a/src/components/about/WelcomeDialog.tsx +++ b/src/components/about/WelcomeDialog.tsx @@ -1,12 +1,14 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Dialog, DialogContent, DialogTitle, Typography, Backdrop, -} from '@material-ui/core' +} from '@mui/material' import { MarkdownWithRouteLinks, useUItext, Logo } from 'components/generic' import { WelcomeFooter } from './WelcomeFooter' @@ -20,7 +22,7 @@ const useStyles = makeStyles((theme: Theme) => display: 'flex', justifyContent: 'center', paddingTop: '1rem', - [theme.breakpoints.down('xs')]: { + [theme.breakpoints.down('sm')]: { padding: '1rem 0.75rem 0.75rem', }, }, @@ -42,7 +44,7 @@ const useStyles = makeStyles((theme: Theme) => fontSize: '1rem', paddingTop: '1.5rem', paddingBottom: '1.5rem', - [theme.breakpoints.down('xs')]: { + [theme.breakpoints.down('sm')]: { paddingLeft: '1.25rem', paddingRight: '1.25rem', '& p': { @@ -56,10 +58,10 @@ const useStyles = makeStyles((theme: Theme) => marginLeft: theme.spacing(3), marginRight: theme.spacing(3), }, - [theme.breakpoints.down('xs')]: { + [theme.breakpoints.down('sm')]: { marginBottom: 0, marginTop: 0, - maxHeight: `calc(100% - ${theme.spacing(4)}px)`, + maxHeight: `calc(100% - ${theme.spacing(4)})`, }, }, }) @@ -112,14 +114,13 @@ export const WelcomeDialog: FC = () => { open={open} onClose={handleClose} disableEscapeKeyDown - disableBackdropClick aria-labelledby="welcome-dialog-title" aria-describedby="welcome-dialog-description" maxWidth="sm" BackdropProps={{ classes: { root: backdrop } }} PaperProps={{ classes: { root: paper }, elevation: 24 }} > - + diff --git a/src/components/about/WelcomeFooter.tsx b/src/components/about/WelcomeFooter.tsx index 75912b4f..152e5527 100644 --- a/src/components/about/WelcomeFooter.tsx +++ b/src/components/about/WelcomeFooter.tsx @@ -1,12 +1,14 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Button, Checkbox, DialogActions, FormControlLabel, Typography, -} from '@material-ui/core' +} from '@mui/material' import { HIDE_WELCOME_LOCAL_STG_KEY } from './config' diff --git a/src/components/config/theme.ts b/src/components/config/theme.ts index 1c7f633d..263229a2 100644 --- a/src/components/config/theme.ts +++ b/src/components/config/theme.ts @@ -1,8 +1,9 @@ import { - createMuiTheme, + createTheme, responsiveFontSizes, - fade, -} from '@material-ui/core/styles' + alpha, + adaptV4Theme, +} from '@mui/material/styles' // Always have a hard time finding the Typography variant docs for some reason: // https://material-ui.com/components/typography/#component @@ -61,28 +62,30 @@ const headings = { // Easy access to theme properties when used in `createMuiTheme` overrides // CRED: https://stackoverflow.com/a/57127040/1048518 -const customTheme = createMuiTheme({ - palette: { - type: 'dark', - primary: { - light: '#62aca0', - main: '#379587', - dark: '#286a61', - contrastText: '#fff', +const customTheme = createTheme( + adaptV4Theme({ + palette: { + mode: 'dark', + primary: { + light: '#62aca0', + main: '#379587', + dark: '#286a61', + contrastText: '#fff', + }, + secondary: { + light: '#55a9c1', + main: '#207d96', + dark: '#2d6777', + contrastText: '#fff', + }, }, - secondary: { - light: '#55a9c1', - main: '#207d96', - dark: '#2d6777', - contrastText: '#fff', + typography: { + fontFamily: BODY_FONTS, + fontSize: 16, + ...headings, }, - }, - typography: { - fontFamily: BODY_FONTS, - fontSize: 16, - ...headings, - }, -}) + }) +) // Global overrides of MUI components that need to be re-styled often. More // examples available at: @@ -132,7 +135,7 @@ customTheme.overrides = { // which is too hard to see against dark paper backgrounds outlinedSecondary: { color: customTheme.palette.secondary.light, - border: `1px solid ${fade(customTheme.palette.secondary.light, 0.5)}`, + border: `1px solid ${alpha(customTheme.palette.secondary.light, 0.5)}`, }, }, MuiLink: { diff --git a/src/components/context/ProvidersWrap.tsx b/src/components/context/ProvidersWrap.tsx index 46587fa7..31ef9ec5 100644 --- a/src/components/context/ProvidersWrap.tsx +++ b/src/components/context/ProvidersWrap.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react' -import { CssBaseline } from '@material-ui/core' -import { ThemeProvider } from '@material-ui/styles' +import { CssBaseline } from '@mui/material' +import { ThemeProvider, Theme, StyledEngineProvider } from '@mui/styles' import '../style.css' @@ -8,6 +8,11 @@ import { GlobalProvider } from './GlobalContext' import { SymbAndLabelProvider } from './SymbAndLabelContext' import { theme } from '../config/theme' +declare module '@mui/styles/defaultTheme' { + // eslint-disable-next-line @typescript-eslint/no-empty-interface + interface DefaultTheme extends Theme {} +} + // Everything the app needs except Routes. This makes it testable and reusable // (e.g. ) export const ProvidersWrap: FC = ({ children }) => { @@ -16,10 +21,12 @@ export const ProvidersWrap: FC = ({ children }) => { // https://medium.com/heuristics/react-dark-mode-switch-in-material-ui-dashboard-82fcf1cded66 return ( - - - {children} - + + + + {children} + + ) } diff --git a/src/components/details/Chips.tsx b/src/components/details/Chips.tsx index 9eb564f0..ee5ef234 100644 --- a/src/components/details/Chips.tsx +++ b/src/components/details/Chips.tsx @@ -1,8 +1,10 @@ import React, { FC } from 'react' import { isMobile } from 'react-device-detect' import { Link as RouterLink } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Paper } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Paper } from '@mui/material' import * as Types from './types' diff --git a/src/components/details/DetailedIntro.tsx b/src/components/details/DetailedIntro.tsx index 417a6742..bd0c8c54 100644 --- a/src/components/details/DetailedIntro.tsx +++ b/src/components/details/DetailedIntro.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Route, Switch } from 'react-router-dom' -import { Grow } from '@material-ui/core' +import { Grow } from '@mui/material' import { Media } from 'components/media' import { MoreLikeThis } from 'components/details' diff --git a/src/components/details/DetailsPanel.tsx b/src/components/details/DetailsPanel.tsx index 7926127d..90920372 100644 --- a/src/components/details/DetailsPanel.tsx +++ b/src/components/details/DetailsPanel.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react' import { Switch, Route } from 'react-router-dom' -import { Typography } from '@material-ui/core' +import { Typography } from '@mui/material' import { RecordDescription } from 'components/results' import { DetailedIntro, LangOrEndoIntro } from 'components/details' diff --git a/src/components/details/EndoImageWrap.tsx b/src/components/details/EndoImageWrap.tsx index f57eaac7..dafbe691 100644 --- a/src/components/details/EndoImageWrap.tsx +++ b/src/components/details/EndoImageWrap.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react' -import { createStyles, makeStyles } from '@material-ui/core/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' type EndoImageComponent = { url: string diff --git a/src/components/details/LocationLink.tsx b/src/components/details/LocationLink.tsx index 046a76ac..3f5e02aa 100644 --- a/src/components/details/LocationLink.tsx +++ b/src/components/details/LocationLink.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button, Popover } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button, Popover } from '@mui/material' import { BiMapPin } from 'react-icons/bi' import { NeighborhoodList } from 'components/details' diff --git a/src/components/details/MoreLikeThis.tsx b/src/components/details/MoreLikeThis.tsx index 1ba14bf3..3535f7bd 100644 --- a/src/components/details/MoreLikeThis.tsx +++ b/src/components/details/MoreLikeThis.tsx @@ -1,5 +1,7 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { IoIosPeople } from 'react-icons/io' import { routes } from 'components/config/api' diff --git a/src/components/details/NeighborhoodList.tsx b/src/components/details/NeighborhoodList.tsx index d9891cd6..a0b0fd46 100644 --- a/src/components/details/NeighborhoodList.tsx +++ b/src/components/details/NeighborhoodList.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Link as RouterLink, Route, Switch } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography, Link } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography, Link } from '@mui/material' import { BiMapPin } from 'react-icons/bi' import { CustomCard, CardListWrap } from 'components/explore' diff --git a/src/components/details/RandomLinkBtn.tsx b/src/components/details/RandomLinkBtn.tsx index ccccc76a..d266fc0e 100644 --- a/src/components/details/RandomLinkBtn.tsx +++ b/src/components/details/RandomLinkBtn.tsx @@ -1,6 +1,6 @@ import React, { FC, useContext } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { Button } from '@material-ui/core' +import { Button } from '@mui/material' import { FaRandom } from 'react-icons/fa' import { GlobalContext } from 'components/context' diff --git a/src/components/details/styles.ts b/src/components/details/styles.ts index e60db6aa..9825a9d4 100644 --- a/src/components/details/styles.ts +++ b/src/components/details/styles.ts @@ -1,4 +1,7 @@ -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' export const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/explore/BasicExploreIntro.tsx b/src/components/explore/BasicExploreIntro.tsx index 670382b2..6db70114 100644 --- a/src/components/explore/BasicExploreIntro.tsx +++ b/src/components/explore/BasicExploreIntro.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Route } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Grow, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Grow, Typography } from '@mui/material' import { FiltersWarning } from 'components/home/FiltersWarning' import { Explanation } from 'components/generic' diff --git a/src/components/explore/Breadcrumbs.tsx b/src/components/explore/Breadcrumbs.tsx index c665e4a7..60e8b91f 100644 --- a/src/components/explore/Breadcrumbs.tsx +++ b/src/components/explore/Breadcrumbs.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' -import { Link } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { Link } from '@mui/material' import { useLocation, Link as RouterLink, @@ -17,7 +19,7 @@ const useStyles = makeStyles((theme: Theme) => alignItems: 'center', display: 'flex', overflow: 'hidden', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { overflowX: 'auto', // Easter egg: scroll sideways on small screens }, '& > :last-child': { diff --git a/src/components/explore/CardList.tsx b/src/components/explore/CardList.tsx index ee049fef..7306f2c5 100644 --- a/src/components/explore/CardList.tsx +++ b/src/components/explore/CardList.tsx @@ -1,6 +1,9 @@ import React, { FC } from 'react' import { useParams, useRouteMatch } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { ColoredCircle } from 'components/generic/icons-and-swatches' import { RouteMatch, TonsWithAddl } from './types' diff --git a/src/components/explore/CensusPopover.tsx b/src/components/explore/CensusPopover.tsx index 450fd1a3..862fc92d 100644 --- a/src/components/explore/CensusPopover.tsx +++ b/src/components/explore/CensusPopover.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import { Typography, Popover, Button } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { Typography, Popover, Button } from '@mui/material' import { FaClipboardList } from 'react-icons/fa' import { MdLayersClear, MdLayers } from 'react-icons/md' diff --git a/src/components/explore/ClearSelectionBtn.tsx b/src/components/explore/ClearSelectionBtn.tsx index 7cf353ba..ecf468fc 100644 --- a/src/components/explore/ClearSelectionBtn.tsx +++ b/src/components/explore/ClearSelectionBtn.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { Button } from '@material-ui/core' +import { Button } from '@mui/material' import { IoIosCloseCircleOutline } from 'react-icons/io' import { routes } from 'components/config/api' diff --git a/src/components/explore/CustomCard.tsx b/src/components/explore/CustomCard.tsx index 4d2e6dcb..cb9f77b2 100644 --- a/src/components/explore/CustomCard.tsx +++ b/src/components/explore/CustomCard.tsx @@ -1,8 +1,10 @@ import React, { FC } from 'react' import { isMobile } from 'react-device-detect' import { Link } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Grow, Card, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Grow, Card, Typography } from '@mui/material' import { CustomCardProps } from './types' import * as utils from './utils' diff --git a/src/components/explore/LayerToggle.tsx b/src/components/explore/LayerToggle.tsx index 57f8172a..457413b3 100644 --- a/src/components/explore/LayerToggle.tsx +++ b/src/components/explore/LayerToggle.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { FormControlLabel, Switch } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { FormControlLabel, Switch } from '@mui/material' import { useMapToolsState, useMapToolsDispatch } from 'components/context' @@ -26,7 +28,7 @@ const useStyles = makeStyles((theme: Theme) => // wowww overkill, but it fits... hideOnMobile: { whiteSpace: 'pre', - [theme.breakpoints.down('xs')]: { + [theme.breakpoints.down('sm')]: { display: 'none', }, }, diff --git a/src/components/explore/NeighborhoodsInstance.tsx b/src/components/explore/NeighborhoodsInstance.tsx index dd3e22ce..73381472 100644 --- a/src/components/explore/NeighborhoodsInstance.tsx +++ b/src/components/explore/NeighborhoodsInstance.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' import { useParams, useRouteMatch } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button } from '@mui/material' import { FiShare } from 'react-icons/fi' import { BasicExploreIntro } from 'components/panels' @@ -58,7 +60,7 @@ const useStyles = makeStyles((theme: Theme) => }, '& .MuiButton-textSizeSmall': { fontSize: '0.85rem', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { minWidth: 'auto', }, }, @@ -66,7 +68,7 @@ const useStyles = makeStyles((theme: Theme) => // wowww overkill, but it fits... hideOnMobile: { whiteSpace: 'pre', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { display: 'none', }, }, diff --git a/src/components/explore/PanelIntroTitleSubtitle.tsx b/src/components/explore/PanelIntroTitleSubtitle.tsx index b7424298..8d474d1e 100644 --- a/src/components/explore/PanelIntroTitleSubtitle.tsx +++ b/src/components/explore/PanelIntroTitleSubtitle.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/explore/StatsAndMeta.tsx b/src/components/explore/StatsAndMeta.tsx index 3b68d086..411769b4 100644 --- a/src/components/explore/StatsAndMeta.tsx +++ b/src/components/explore/StatsAndMeta.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { StatsAndMetaProps } from 'components/explore/types' diff --git a/src/components/generic/BackToTopBtn.tsx b/src/components/generic/BackToTopBtn.tsx index 77446845..e645a31c 100644 --- a/src/components/generic/BackToTopBtn.tsx +++ b/src/components/generic/BackToTopBtn.tsx @@ -1,12 +1,7 @@ import React, { FC } from 'react' -import { - createStyles, - makeStyles, - Theme, - Fab, - fade, - Zoom, -} from '@material-ui/core' +import { Theme, Fab, alpha, Zoom } from '@mui/material' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { FaArrowCircleUp } from 'react-icons/fa' import { BOTTOM_NAV_HEIGHT } from 'components/nav/config' @@ -21,7 +16,7 @@ const useStyles = makeStyles((theme: Theme) => position: 'absolute', bottom: BOTTOM_NAV_HEIGHT + 8, right: '1.25rem', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { bottom: '1rem', right: '1rem', }, @@ -30,7 +25,7 @@ const useStyles = makeStyles((theme: Theme) => width: 36, height: 36, minHeight: 36, - backgroundColor: fade(theme.palette.secondary.main, 0.75), + backgroundColor: alpha(theme.palette.secondary.main, 0.75), }, }) ) diff --git a/src/components/generic/Explanation.tsx b/src/components/generic/Explanation.tsx index d4847e3d..fb841659 100644 --- a/src/components/generic/Explanation.tsx +++ b/src/components/generic/Explanation.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/generic/FancyHorizRule.tsx b/src/components/generic/FancyHorizRule.tsx index a51db29d..e14134c8 100644 --- a/src/components/generic/FancyHorizRule.tsx +++ b/src/components/generic/FancyHorizRule.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/generic/Logo.tsx b/src/components/generic/Logo.tsx index 1998d70c..df3e12c9 100644 --- a/src/components/generic/Logo.tsx +++ b/src/components/generic/Logo.tsx @@ -1,5 +1,7 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import ProjectLogo from '../../img/logo.svg?react' type LogoProps = { diff --git a/src/components/generic/MarkdownWithRouteLinks.tsx b/src/components/generic/MarkdownWithRouteLinks.tsx index 02ac11ca..b7d63050 100644 --- a/src/components/generic/MarkdownWithRouteLinks.tsx +++ b/src/components/generic/MarkdownWithRouteLinks.tsx @@ -1,7 +1,7 @@ import React, { FC } from 'react' import ReactMarkdown from 'react-markdown' import { Link as RouterLink } from 'react-router-dom' -import { Link } from '@material-ui/core' +import { Link } from '@mui/material' import { LinkRenderer, MarkdownRootElemType } from './types' diff --git a/src/components/generic/ReadMore.tsx b/src/components/generic/ReadMore.tsx index a61b137e..a55c12a4 100644 --- a/src/components/generic/ReadMore.tsx +++ b/src/components/generic/ReadMore.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' import { isMobile } from 'react-device-detect' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button } from '@mui/material' import { ToggleableSection, MarkdownWithRouteLinks } from 'components/generic' diff --git a/src/components/generic/ShareButtons.tsx b/src/components/generic/ShareButtons.tsx index bed3d5bc..d318d7f4 100644 --- a/src/components/generic/ShareButtons.tsx +++ b/src/components/generic/ShareButtons.tsx @@ -1,7 +1,7 @@ // CRED: for the majority of this file: // https://github.com/Covid-Self-report-Tool/cov-self-report-frontend/blob/master/src/components/ShareButtons.tsx import React, { FC } from 'react' -import { Grid, GridSpacing } from '@material-ui/core' +import { Grid, GridSpacing } from '@mui/material' import { EmailIcon, EmailShareButton, @@ -47,7 +47,7 @@ export const ShareButtons: FC = (props) => { return ( createStyles({ diff --git a/src/components/generic/ToggleWithHelper.tsx b/src/components/generic/ToggleWithHelper.tsx index 68e836b3..08f5477c 100644 --- a/src/components/generic/ToggleWithHelper.tsx +++ b/src/components/generic/ToggleWithHelper.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { FormControlLabel, Switch } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { FormControlLabel, Switch } from '@mui/material' import { ToggleWithHelperProps } from './types' import { SubtleText } from './SubtleText' diff --git a/src/components/generic/ToggleableSection.tsx b/src/components/generic/ToggleableSection.tsx index 52f8b58c..a21ce963 100644 --- a/src/components/generic/ToggleableSection.tsx +++ b/src/components/generic/ToggleableSection.tsx @@ -1,5 +1,6 @@ import React, { FC } from 'react' -import { createStyles, makeStyles } from '@material-ui/core/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' type ToggleableProps = { show: boolean diff --git a/src/components/generic/hooks.ts b/src/components/generic/hooks.ts index fc1b1fc5..a1dbdf97 100644 --- a/src/components/generic/hooks.ts +++ b/src/components/generic/hooks.ts @@ -1,5 +1,5 @@ import { useRef, useState, useCallback, useEffect } from 'react' -import { useTheme } from '@material-ui/core/styles' +import { useTheme } from '@mui/material/styles' import { useAirtable } from 'components/explore/hooks' import { useLocation, useRouteMatch } from 'react-router-dom' import { routes } from 'components/config' diff --git a/src/components/generic/modals/DialogCloseBtn.tsx b/src/components/generic/modals/DialogCloseBtn.tsx index 3283c340..2da97557 100644 --- a/src/components/generic/modals/DialogCloseBtn.tsx +++ b/src/components/generic/modals/DialogCloseBtn.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { IconButton } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { IconButton } from '@mui/material' import { MdClose } from 'react-icons/md' const useStyles = makeStyles((theme: Theme) => @@ -34,6 +36,7 @@ export const DialogCloseBtn: FC = (props) => { onClick={onClose} className={classes.closeBtnRoot} title={tooltip} + size="large" > diff --git a/src/components/generic/modals/LoadingBackdrop.tsx b/src/components/generic/modals/LoadingBackdrop.tsx index 35c494ab..02577751 100644 --- a/src/components/generic/modals/LoadingBackdrop.tsx +++ b/src/components/generic/modals/LoadingBackdrop.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import { Backdrop, CircularProgress, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { Backdrop, CircularProgress, Typography } from '@mui/material' type LoadingBackdrop = { centerOnScreen?: boolean diff --git a/src/components/generic/modals/LoadingIndicator.tsx b/src/components/generic/modals/LoadingIndicator.tsx index b7d86452..43881476 100644 --- a/src/components/generic/modals/LoadingIndicator.tsx +++ b/src/components/generic/modals/LoadingIndicator.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography, CircularProgress, LinearProgress } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography, CircularProgress, LinearProgress } from '@mui/material' type LoadingProps = { omitText?: boolean diff --git a/src/components/generic/modals/LoadingTextOnElem.tsx b/src/components/generic/modals/LoadingTextOnElem.tsx index 1859cd3a..19894aa5 100644 --- a/src/components/generic/modals/LoadingTextOnElem.tsx +++ b/src/components/generic/modals/LoadingTextOnElem.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import { CircularProgress, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { CircularProgress, Typography } from '@mui/material' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/generic/modals/SimpleDialog.tsx b/src/components/generic/modals/SimpleDialog.tsx index a96dd70b..e9e29a2f 100644 --- a/src/components/generic/modals/SimpleDialog.tsx +++ b/src/components/generic/modals/SimpleDialog.tsx @@ -1,16 +1,13 @@ import React, { FC } from 'react' -import { - createStyles, - makeStyles, - useTheme, - Theme, -} from '@material-ui/core/styles' +import { useTheme, Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Dialog, DialogContent, DialogProps, useMediaQuery, -} from '@material-ui/core' +} from '@mui/material' import { DialogCloseBtn } from './DialogCloseBtn' import { SlideUp } from './SlideUp' @@ -19,7 +16,7 @@ const useStyles = makeStyles((theme: Theme) => createStyles({ dialogContent: { padding: theme.spacing(3), - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { padding: '2rem 1rem', // make media btns fit }, }, diff --git a/src/components/generic/modals/SlideUp.tsx b/src/components/generic/modals/SlideUp.tsx index efb53127..69b00e2f 100644 --- a/src/components/generic/modals/SlideUp.tsx +++ b/src/components/generic/modals/SlideUp.tsx @@ -1,6 +1,6 @@ import React from 'react' -import { Slide } from '@material-ui/core' -import { TransitionProps } from '@material-ui/core/transitions' +import { Slide } from '@mui/material' +import { TransitionProps } from '@mui/material/transitions' export const SlideUp = React.forwardRef(function Transition( // Don't care, came straight from the MUI example diff --git a/src/components/home/ClearFiltersBtn.tsx b/src/components/home/ClearFiltersBtn.tsx index fc5fb2b4..e3be4a85 100644 --- a/src/components/home/ClearFiltersBtn.tsx +++ b/src/components/home/ClearFiltersBtn.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { Button } from '@material-ui/core' +import { Button } from '@mui/material' import { IoMdCloseCircle } from 'react-icons/io' type ClearFiltersComponent = { diff --git a/src/components/home/FiltersWarning.tsx b/src/components/home/FiltersWarning.tsx index 34a29e50..037002f3 100644 --- a/src/components/home/FiltersWarning.tsx +++ b/src/components/home/FiltersWarning.tsx @@ -1,7 +1,9 @@ import React, { FC, useContext } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button, Link } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button, Link } from '@mui/material' import { GlobalContext } from 'components/context' import { Explanation } from 'components/generic' diff --git a/src/components/home/ListboxComponent.tsx b/src/components/home/ListboxComponent.tsx index 1865ab8a..578ca179 100644 --- a/src/components/home/ListboxComponent.tsx +++ b/src/components/home/ListboxComponent.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { ListSubheader } from '@material-ui/core' +import { ListSubheader } from '@mui/material' import { VariableSizeList, ListChildComponentProps } from 'react-window' import { useResetCache } from './utils' diff --git a/src/components/home/OmniboxResult.tsx b/src/components/home/OmniboxResult.tsx index 0e00119e..c2a33c4f 100644 --- a/src/components/home/OmniboxResult.tsx +++ b/src/components/home/OmniboxResult.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography, Box } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography, Box } from '@mui/material' import { PreppedAutocompleteGroup } from './types' diff --git a/src/components/home/SearchByOmnibox.tsx b/src/components/home/SearchByOmnibox.tsx index bc4d9c33..d65d23e6 100644 --- a/src/components/home/SearchByOmnibox.tsx +++ b/src/components/home/SearchByOmnibox.tsx @@ -1,9 +1,11 @@ import React, { FC } from 'react' import { useHistory } from 'react-router-dom' import matchSorter from 'match-sorter' -import Autocomplete from '@material-ui/lab/Autocomplete' -import { TextField, InputAdornment } from '@material-ui/core' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import Autocomplete from '@mui/material/Autocomplete' +import { TextField, InputAdornment } from '@mui/material' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { MdClose } from 'react-icons/md' import { GoSearch } from 'react-icons/go' @@ -109,7 +111,7 @@ export const SearchByOmnibox: FC = (props) => { } + clearIcon={} // Thought this helped to resolve iOS zoom issue but the cause seems to be // when font size is smaller than the page default. // blurOnSelect="touch" diff --git a/src/components/home/utils.tsx b/src/components/home/utils.tsx index bd50fc55..433d3f13 100644 --- a/src/components/home/utils.tsx +++ b/src/components/home/utils.tsx @@ -1,8 +1,8 @@ import React from 'react' import { Link as RouterLink } from 'react-router-dom' import { VariableSizeList } from 'react-window' -import { AutocompleteRenderGroupParams } from '@material-ui/lab/Autocomplete' -import ListSubheader from '@material-ui/core/ListSubheader' +import { AutocompleteRenderGroupParams } from '@mui/material/Autocomplete' +import ListSubheader from '@mui/material/ListSubheader' import { LangLevelSchema } from 'components/context/types' import { PreppedAutocompleteGroup } from './types' diff --git a/src/components/legend/LangPointsToggle.tsx b/src/components/legend/LangPointsToggle.tsx index 56e7a409..c14e4321 100644 --- a/src/components/legend/LangPointsToggle.tsx +++ b/src/components/legend/LangPointsToggle.tsx @@ -1,7 +1,10 @@ // TODO: rename file to something logical; mv it and all children to ../local import React, { FC } from 'react' -import { FormControlLabel, Switch } from '@material-ui/core' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { FormControlLabel, Switch } from '@mui/material' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { useLabelAndSymbDispatch, @@ -29,7 +32,7 @@ const useStyles = makeStyles((theme: Theme) => }, smallerText: { fontSize: '0.75rem', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { fontSize: '0.65rem', }, }, diff --git a/src/components/legend/LayerLabelSelect.tsx b/src/components/legend/LayerLabelSelect.tsx index 3f537b11..85661298 100644 --- a/src/components/legend/LayerLabelSelect.tsx +++ b/src/components/legend/LayerLabelSelect.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { TextField } from '@material-ui/core' +import { TextField } from '@mui/material' import { useSymbAndLabelState, diff --git a/src/components/legend/LayerSymbSelect.tsx b/src/components/legend/LayerSymbSelect.tsx index 5f36ac67..828c51e4 100644 --- a/src/components/legend/LayerSymbSelect.tsx +++ b/src/components/legend/LayerSymbSelect.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { TextField } from '@material-ui/core' +import { TextField } from '@mui/material' import { useSymbAndLabelState, diff --git a/src/components/legend/Legend.tsx b/src/components/legend/Legend.tsx index 41e0962a..cdb9b8ea 100644 --- a/src/components/legend/Legend.tsx +++ b/src/components/legend/Legend.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import { LegendSwatch } from 'components/legend' import { Explanation, SubtleText } from 'components/generic' diff --git a/src/components/legend/LegendPanel.tsx b/src/components/legend/LegendPanel.tsx index 5b0ef846..d2419184 100644 --- a/src/components/legend/LegendPanel.tsx +++ b/src/components/legend/LegendPanel.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import { LayerSymbSelect, diff --git a/src/components/legend/LegendSwatch.tsx b/src/components/legend/LegendSwatch.tsx index eb287c08..7cdb1deb 100644 --- a/src/components/legend/LegendSwatch.tsx +++ b/src/components/legend/LegendSwatch.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography, Box } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography, Box } from '@mui/material' import * as Types from './types' diff --git a/src/components/legend/WorldRegionMap.tsx b/src/components/legend/WorldRegionMap.tsx index ce2eb0a9..7c9410a4 100644 --- a/src/components/legend/WorldRegionMap.tsx +++ b/src/components/legend/WorldRegionMap.tsx @@ -1,6 +1,9 @@ import React, { FC, useState } from 'react' -import { Button } from '@material-ui/core' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Button } from '@mui/material' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { ToggleableSection, Explanation } from 'components/generic' diff --git a/src/components/legend/config.ts b/src/components/legend/config.ts index 8441b0ff..e8f83a9c 100644 --- a/src/components/legend/config.ts +++ b/src/components/legend/config.ts @@ -1,4 +1,4 @@ -import { OutlinedTextFieldProps } from '@material-ui/core' +import { OutlinedTextFieldProps } from '@mui/material' import { InstanceLevelSchema } from 'components/context/types' import { AtSymbFields } from './types' diff --git a/src/components/local/CensusAutoZoomToggle.tsx b/src/components/local/CensusAutoZoomToggle.tsx index 3d4be75d..d55171b8 100644 --- a/src/components/local/CensusAutoZoomToggle.tsx +++ b/src/components/local/CensusAutoZoomToggle.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { Switch } from '@material-ui/core' +import { Switch } from '@mui/material' import { CustomFormControl } from 'components/legend' import { useMapToolsDispatch, useMapToolsState } from 'components/context' diff --git a/src/components/local/CensusFieldSelect.tsx b/src/components/local/CensusFieldSelect.tsx index 3f7e298a..7fe9ad92 100644 --- a/src/components/local/CensusFieldSelect.tsx +++ b/src/components/local/CensusFieldSelect.tsx @@ -1,10 +1,12 @@ import React, { FC } from 'react' import { useHistory } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { TextField, Typography, ListSubheader } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { TextField, Typography, ListSubheader } from '@mui/material' import Autocomplete, { AutocompleteRenderGroupParams, -} from '@material-ui/lab/Autocomplete' +} from '@mui/material/Autocomplete' import { useMapToolsDispatch, useMapToolsState } from 'components/context' import { UItextFromAirtable, useUItext } from 'components/generic' @@ -42,7 +44,7 @@ const useStyles = makeStyles((theme: Theme) => }, listbox: { paddingTop: 0, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { maxHeight: 225, // maybe helps prevent unwanted upward-opening menu? }, }, diff --git a/src/components/local/CensusTogglesWrap.tsx b/src/components/local/CensusTogglesWrap.tsx index d35beea9..cfa0d67d 100644 --- a/src/components/local/CensusTogglesWrap.tsx +++ b/src/components/local/CensusTogglesWrap.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { AllLangDataToggle } from 'components/legend' import { CensusAutoZoomToggle } from './CensusAutoZoomToggle' @@ -14,7 +17,7 @@ const useStyles = makeStyles((theme: Theme) => marginBottom: '0.75rem', paddingBottom: '0.5rem', borderBottom: `solid 1px ${theme.palette.divider}`, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { gridColumnGap: 2, }, }, diff --git a/src/components/local/LegendGradient.tsx b/src/components/local/LegendGradient.tsx index d1eb980c..2c964bdf 100644 --- a/src/components/local/LegendGradient.tsx +++ b/src/components/local/LegendGradient.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { useMapToolsState } from 'components/context' import { LegendBarProps, LegendMarkersProps } from './types' diff --git a/src/components/map/BaseLayerToggles.tsx b/src/components/map/BaseLayerToggles.tsx index cbcaa56b..c5e192c3 100644 --- a/src/components/map/BaseLayerToggles.tsx +++ b/src/components/map/BaseLayerToggles.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { isMobile } from 'react-device-detect' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { ToggleButton, ToggleButtonGroup } from '@material-ui/lab' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { ToggleButton, ToggleButtonGroup } from '@mui/material' import { FiSun, FiMoon } from 'react-icons/fi' import { RiEyeCloseLine } from 'react-icons/ri' diff --git a/src/components/map/GeocodeMarker.tsx b/src/components/map/GeocodeMarker.tsx index 08153dfb..282cddef 100644 --- a/src/components/map/GeocodeMarker.tsx +++ b/src/components/map/GeocodeMarker.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Marker } from 'react-map-gl' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import * as MapTypes from './types' diff --git a/src/components/map/GeocoderPopout.tsx b/src/components/map/GeocoderPopout.tsx index c003f790..0e3e8e74 100644 --- a/src/components/map/GeocoderPopout.tsx +++ b/src/components/map/GeocoderPopout.tsx @@ -2,7 +2,10 @@ import React, { FC, useRef } from 'react' import { Map } from 'mapbox-gl' import Geocoder from 'react-map-gl-geocoder' -import { createStyles, makeStyles, Theme } from '@material-ui/core' +import { Theme } from '@mui/material' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import 'react-map-gl-geocoder/dist/mapbox-gl-geocoder.css' diff --git a/src/components/map/MapCtrlBtns.tsx b/src/components/map/MapCtrlBtns.tsx index dfba9b05..5094c3de 100644 --- a/src/components/map/MapCtrlBtns.tsx +++ b/src/components/map/MapCtrlBtns.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import { SpeedDial, SpeedDialAction } from '@material-ui/lab' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { SpeedDial, SpeedDialAction } from '@mui/material' import { MdYoutubeSearchedFor } from 'react-icons/md' import { FiLayers } from 'react-icons/fi' import { FaSearchPlus, FaSearchMinus } from 'react-icons/fa' @@ -14,7 +16,7 @@ const useStyles = makeStyles((theme: Theme) => '& svg': { fontSize: '1.25rem', }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { position: 'absolute', right: '0.5rem', top: -4, // deals w/padding on btn root diff --git a/src/components/map/MapOptionsMenu.tsx b/src/components/map/MapOptionsMenu.tsx index ae1eceb6..3211bdc1 100644 --- a/src/components/map/MapOptionsMenu.tsx +++ b/src/components/map/MapOptionsMenu.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' -import { Button, Popover, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { Button, Popover, Typography } from '@mui/material' import { DialogCloseBtn } from 'components/generic/modals' import { useMapToolsState, useMapToolsDispatch } from 'components/context' diff --git a/src/components/map/MapPopup.tsx b/src/components/map/MapPopup.tsx index bccedafb..0aa15c45 100644 --- a/src/components/map/MapPopup.tsx +++ b/src/components/map/MapPopup.tsx @@ -1,8 +1,10 @@ import React, { FC } from 'react' import { Route, useParams, Switch } from 'react-router-dom' import { Popup } from 'react-map-gl' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import { InstanceLevelSchema, useMapToolsState } from 'components/context' import { useAirtable } from 'components/explore/hooks' @@ -26,7 +28,7 @@ const useStyles = makeStyles((theme: Theme) => wordWrap: 'break-word', '& .mapboxgl-popup-content': { // Leave room for "x" close button - padding: `${theme.spacing(1)}px ${theme.spacing(3)}px`, + padding: `${theme.spacing(1)} ${theme.spacing(3)}`, }, '& .mapboxgl-popup-close-button': { fontSize: '1.25rem', diff --git a/src/components/media/Media.tsx b/src/components/media/Media.tsx index cbbe6986..5c1c466b 100644 --- a/src/components/media/Media.tsx +++ b/src/components/media/Media.tsx @@ -1,7 +1,9 @@ import React, { FC, useState } from 'react' import { useHistory, useRouteMatch } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button } from '@mui/material' import { FiVideo, FiShare } from 'react-icons/fi' import { AiOutlineSound } from 'react-icons/ai' import { IoIosCloseCircleOutline } from 'react-icons/io' diff --git a/src/components/media/MediaModal.tsx b/src/components/media/MediaModal.tsx index 256569c6..d14ab864 100644 --- a/src/components/media/MediaModal.tsx +++ b/src/components/media/MediaModal.tsx @@ -1,13 +1,10 @@ import React, { FC } from 'react' import * as Sentry from '@sentry/react' import { useQuery, QueryCache, ReactQueryCacheProvider } from 'react-query' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { - Container, - Button, - Typography, - CircularProgress, -} from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Container, Button, Typography, CircularProgress } from '@mui/material' import { SimpleDialog } from 'components/generic/modals' import { MediaModalProps, ModalContentProps, APIresponse } from './types' @@ -31,7 +28,7 @@ const useStyles = makeStyles((theme: Theme) => dialogContent: { marginTop: '1rem', marginBottom: '1rem', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { padding: 0, }, }, diff --git a/src/components/nav/AboutLinkAsIcon.tsx b/src/components/nav/AboutLinkAsIcon.tsx index 67659edf..e3f138d9 100644 --- a/src/components/nav/AboutLinkAsIcon.tsx +++ b/src/components/nav/AboutLinkAsIcon.tsx @@ -1,6 +1,6 @@ import React, { FC } from 'react' import { useHistory } from 'react-router-dom' -import { IconButton } from '@material-ui/core' +import { IconButton } from '@mui/material' import { GoInfo } from 'react-icons/go' type ListItemLinkProps = { @@ -21,6 +21,7 @@ export const AboutLinkAsIcon: FC = ({ className={muiClass} edge="end" onClick={() => history.push(to)} + size="large" > diff --git a/src/components/nav/BottomNav.tsx b/src/components/nav/BottomNav.tsx index 8b0c13d7..848e54a7 100644 --- a/src/components/nav/BottomNav.tsx +++ b/src/components/nav/BottomNav.tsx @@ -1,13 +1,10 @@ import React, { FC, useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import { NavLink, useLocation } from 'react-router-dom' -import { - createStyles, - makeStyles, - Theme, - lighten, -} from '@material-ui/core/styles' -import { BottomNavigation, BottomNavigationAction } from '@material-ui/core' +import { Theme, lighten } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { BottomNavigation, BottomNavigationAction } from '@mui/material' import { usePanelState, usePanelDispatch } from 'components/panels' import { routes } from 'components/config/api' @@ -33,7 +30,7 @@ radial-gradient(ellipse at bottom, ${theme.palette.primary.dark}, transparent)` width: '100%', position: 'absolute', bottom: 0, - [theme.breakpoints.down('md')]: { + [theme.breakpoints.down('lg')]: { boxShadow: '0px -5px 5px 0px rgba(0,0,0,0.1)', borderRadius: 0, height: BOTTOM_NAV_HEIGHT_MOBILE, @@ -65,7 +62,7 @@ radial-gradient(ellipse at bottom, ${theme.palette.primary.dark}, transparent)` }, wrapper: { fontSize: '0.85rem', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { fontSize: '0.75rem', }, }, @@ -73,7 +70,7 @@ radial-gradient(ellipse at bottom, ${theme.palette.primary.dark}, transparent)` '& .Mui-selected': { fontSize: 'inherit', // from the wrapper class }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { fontSize: '0.75rem', }, }, diff --git a/src/components/nav/Nav.tsx b/src/components/nav/Nav.tsx index 90e87d9a..bfac7a1f 100644 --- a/src/components/nav/Nav.tsx +++ b/src/components/nav/Nav.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' import { Link as RouterLink } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Divider, Link, @@ -8,7 +10,7 @@ import { ListItem, ListItemIcon, ListItemText, -} from '@material-ui/core' +} from '@mui/material' import { routes, icons } from 'components/config' import { UItextFromAirtable } from 'components/generic' diff --git a/src/components/nav/OffCanvasNav.tsx b/src/components/nav/OffCanvasNav.tsx index 7a261923..9e341050 100644 --- a/src/components/nav/OffCanvasNav.tsx +++ b/src/components/nav/OffCanvasNav.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Drawer } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Drawer } from '@mui/material' import { Nav } from 'components/nav' import { SimpleDialog } from 'components/generic/modals' diff --git a/src/components/nav/Settings.tsx b/src/components/nav/Settings.tsx index c305e74a..4cdb05cc 100644 --- a/src/components/nav/Settings.tsx +++ b/src/components/nav/Settings.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { FormControlLabel, Switch, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { FormControlLabel, Switch, Typography } from '@mui/material' import { FiShare } from 'react-icons/fi' import { GoGear } from 'react-icons/go' diff --git a/src/components/nav/TopBar.test.tsx b/src/components/nav/TopBar.test.tsx index 34624c3f..3a0cebca 100644 --- a/src/components/nav/TopBar.test.tsx +++ b/src/components/nav/TopBar.test.tsx @@ -7,9 +7,9 @@ import { TopBar } from 'components/nav' // Hoist helper functions (but not vars) to reuse between test cases const renderTopBar = () => ( // Only needed because there are components - + ( - + ) ) describe('Formerly testing off-canvas behavhior', () => { diff --git a/src/components/nav/TopBar.tsx b/src/components/nav/TopBar.tsx index 3dcc49a2..7a5156ac 100644 --- a/src/components/nav/TopBar.tsx +++ b/src/components/nav/TopBar.tsx @@ -1,5 +1,7 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { Link as RouteLink } from 'react-router-dom' import { routes } from 'components/config/api' @@ -25,7 +27,7 @@ const useStyles = makeStyles((theme: Theme) => [theme.breakpoints.up('xl')]: { top: '0.75rem', }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { display: 'none', }, }, diff --git a/src/components/panels/NavItemWithBadge.tsx b/src/components/panels/NavItemWithBadge.tsx index 665ff292..b4f450f7 100644 --- a/src/components/panels/NavItemWithBadge.tsx +++ b/src/components/panels/NavItemWithBadge.tsx @@ -1,6 +1,8 @@ import React, { FC, useContext } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Badge } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Badge } from '@mui/material' import { GlobalContext } from 'components/context' @@ -24,7 +26,7 @@ export const NavItemWithBadge: FC = (props) => { classes={{ dot: classes.badgeRoot }} badgeContent="" color="secondary" - overlap="circle" + overlap="circular" anchorOrigin={{ vertical: 'top', horizontal: 'left' }} invisible={state.langFeatsLenCache === state.langFeatures.length} > diff --git a/src/components/panels/PanelCloseBtn.tsx b/src/components/panels/PanelCloseBtn.tsx index f3220fa1..7baac9cc 100644 --- a/src/components/panels/PanelCloseBtn.tsx +++ b/src/components/panels/PanelCloseBtn.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { IconButton, Tooltip } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { IconButton, Tooltip } from '@mui/material' import { CgClose } from 'react-icons/cg' import { usePanelDispatch } from 'components/panels' diff --git a/src/components/panels/PanelHeading.tsx b/src/components/panels/PanelHeading.tsx index 70142000..ca9a2c44 100644 --- a/src/components/panels/PanelHeading.tsx +++ b/src/components/panels/PanelHeading.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' type PanelHeadingProps = { text: string diff --git a/src/components/panels/PanelTitleBar.tsx b/src/components/panels/PanelTitleBar.tsx index 87a29100..bf52f776 100644 --- a/src/components/panels/PanelTitleBar.tsx +++ b/src/components/panels/PanelTitleBar.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' import { useLocation, Route, Switch } from 'react-router-dom' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { Popover, AppBar, @@ -8,7 +10,7 @@ import { IconButton, Toolbar, Tooltip, -} from '@material-ui/core' +} from '@mui/material' import { HiOutlineSearch } from 'react-icons/hi' import { PanelCloseBtn } from 'components/panels' @@ -27,7 +29,7 @@ const useStyles = makeStyles((theme: Theme) => top: 0, width: '100%', boxShadow: theme.shadows[12], - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { boxShadow: '0px 11px 10px 0px rgb(0 0 0 / 18%), 0px 24px 38px 3px rgb(0 0 0 / 12%), 0px 9px 46px 8px rgb(0 0 0 / 10%)', }, @@ -122,7 +124,7 @@ export const PanelTitleBar: FC = (props) => { {mapRef && } - + diff --git a/src/components/panels/PanelTitleRoutes.tsx b/src/components/panels/PanelTitleRoutes.tsx index 65cc8b37..ddb9341c 100644 --- a/src/components/panels/PanelTitleRoutes.tsx +++ b/src/components/panels/PanelTitleRoutes.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Route, Switch, Link as RouterLink } from 'react-router-dom' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' -import { IconButton, Typography, Tooltip, Hidden } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { IconButton, Typography, Tooltip, Hidden } from '@mui/material' import { icons } from 'components/config' import { routes } from 'components/config/api' @@ -87,7 +89,7 @@ export const PanelTitleRoutes: FC<{ panelTitle: string }> = (props) => {
- + diff --git a/src/components/panels/PanelWrap.tsx b/src/components/panels/PanelWrap.tsx index 5e24e93c..f878267f 100644 --- a/src/components/panels/PanelWrap.tsx +++ b/src/components/panels/PanelWrap.tsx @@ -1,7 +1,9 @@ import React, { FC, useRef } from 'react' import { Route, Switch, useLocation } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Hidden } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Hidden } from '@mui/material' import { SearchTabs, @@ -47,7 +49,7 @@ const useStyles = makeStyles((theme: Theme) => [theme.breakpoints.up('xl')]: { width: panelWidths.midLarge, }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { width: '100%', borderTop: `solid 6px ${theme.palette.primary.dark}`, bottom: BOTTOM_NAV_HEIGHT_MOBILE, @@ -75,7 +77,7 @@ const useStyles = makeStyles((theme: Theme) => [theme.breakpoints.up('md')]: { padding: '1.5rem 1.25rem', }, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { bottom: 0, top: 0, opacity: (props: Style) => (props.open ? 1 : 0), @@ -105,7 +107,7 @@ export const PanelWrap: FC = (props) => { return (
- + @@ -131,7 +133,7 @@ export const PanelWrap: FC = (props) => {
- +
diff --git a/src/components/panels/SearchTabs.tsx b/src/components/panels/SearchTabs.tsx index 42ec2761..e642bd2a 100755 --- a/src/components/panels/SearchTabs.tsx +++ b/src/components/panels/SearchTabs.tsx @@ -1,14 +1,10 @@ import React, { FC, useState } from 'react' import SwipeableViews from 'react-swipeable-views' -import AppBar from '@material-ui/core/AppBar' -import { - createStyles, - makeStyles, - Tab, - Tabs, - Theme, - useTheme, -} from '@material-ui/core' +import AppBar from '@mui/material/AppBar' +import { Tab, Tabs, Theme, useTheme } from '@mui/material' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { SearchByOmnibox } from 'components/home/SearchByOmnibox' import { GeocoderPopout } from 'components/map' diff --git a/src/components/panels/ShowPanelBtn.tsx b/src/components/panels/ShowPanelBtn.tsx index 51c9ed43..237a5884 100644 --- a/src/components/panels/ShowPanelBtn.tsx +++ b/src/components/panels/ShowPanelBtn.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { usePanelDispatch } from 'components/panels' -import { Tooltip, Zoom, Fab } from '@material-ui/core' +import { Tooltip, Zoom, Fab } from '@mui/material' import { MdKeyboardArrowRight } from 'react-icons/md' const useStyles = makeStyles((theme: Theme) => @@ -11,7 +13,7 @@ const useStyles = makeStyles((theme: Theme) => top: '1rem', left: '1rem', zIndex: 1, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { display: 'none', // TODO: think it through }, }, @@ -38,7 +40,7 @@ export const ShowPanelBtn: FC<{ panelOpen: boolean }> = (props) => { size="small" aria-label="panel open" color="secondary" - variant="round" + variant="circular" classes={{ root: classes.root, label: classes.label }} onClick={handleClick} > diff --git a/src/components/panels/SplitCrumbs.tsx b/src/components/panels/SplitCrumbs.tsx index 74540b3d..e789f065 100644 --- a/src/components/panels/SplitCrumbs.tsx +++ b/src/components/panels/SplitCrumbs.tsx @@ -1,8 +1,10 @@ // TODO: rename file and component to "BackBtn" import React, { FC, useEffect } from 'react' import { Link as RouterLink, useLocation } from 'react-router-dom' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' -import { IconButton, Popover, Tooltip } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' +import { IconButton, Popover, Tooltip } from '@mui/material' import { AiOutlineUnorderedList } from 'react-icons/ai' import { BsArrow90DegUp } from 'react-icons/bs' diff --git a/src/components/panels/TabPanel.tsx b/src/components/panels/TabPanel.tsx index af2550ca..f7cc180c 100644 --- a/src/components/panels/TabPanel.tsx +++ b/src/components/panels/TabPanel.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core' +import { Theme } from '@mui/material' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { TabPanelProps } from './types' @@ -10,7 +13,7 @@ const useStyles = makeStyles((theme: Theme) => { root: { padding: '1rem', borderBottom: `solid 1px ${palette.divider}`, - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { padding: '0.75rem 0.5rem', }, }, diff --git a/src/components/panels/TimelineCrumbs.tsx b/src/components/panels/TimelineCrumbs.tsx index 6b5c1327..11e95e34 100644 --- a/src/components/panels/TimelineCrumbs.tsx +++ b/src/components/panels/TimelineCrumbs.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' import { Link as RouterLink, Route, Switch } from 'react-router-dom' -import { makeStyles, Theme, createStyles } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { Timeline, TimelineItem, @@ -8,7 +10,7 @@ import { TimelineConnector, TimelineContent, TimelineDot, -} from '@material-ui/lab' +} from '@mui/lab' import { RouteableTableNames } from 'components/context/types' import { icons } from 'components/config' diff --git a/src/components/results/Cells.tsx b/src/components/results/Cells.tsx index b302ac23..26b40aa6 100644 --- a/src/components/results/Cells.tsx +++ b/src/components/results/Cells.tsx @@ -1,10 +1,7 @@ import React, { FC } from 'react' -import { - makeStyles, - createStyles, - useTheme, - Theme, -} from '@material-ui/core/styles' +import { useTheme, Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { MdCheck } from 'react-icons/md' import { GoCircleSlash } from 'react-icons/go' diff --git a/src/components/results/CountryListItemWithFlag.tsx b/src/components/results/CountryListItemWithFlag.tsx index 70c07e29..1ee006b6 100644 --- a/src/components/results/CountryListItemWithFlag.tsx +++ b/src/components/results/CountryListItemWithFlag.tsx @@ -1,5 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { CountryListItemWithFlagProps } from './types' @@ -9,7 +12,7 @@ const useStyles = makeStyles((theme: Theme) => alignItems: 'center', display: 'grid', gridColumnGap: theme.spacing(1), - gridTemplateColumns: `${theme.spacing(3)}px auto`, + gridTemplateColumns: `${theme.spacing(3)} auto`, gridTemplateRows: 'auto', lineHeight: 1, // proper vertical align (all good except super-long Congo) '& + li': { diff --git a/src/components/results/EndoImageModal.tsx b/src/components/results/EndoImageModal.tsx index 9e0a2758..3a64ba3d 100644 --- a/src/components/results/EndoImageModal.tsx +++ b/src/components/results/EndoImageModal.tsx @@ -1,6 +1,8 @@ import React, { FC, useState } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Button, Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Button, Typography } from '@mui/material' import { SimpleDialog } from 'components/generic/modals' import { correctDropboxURL } from '../../utils' @@ -23,7 +25,7 @@ const useStyles = makeStyles((theme: Theme) => }, // Smaller than the default so that it is not as large as table modal endoModalPaper: { - margin: `${theme.spacing(4)}px ${theme.spacing(3)}px`, + margin: `${theme.spacing(4)} ${theme.spacing(3)}`, }, image: { height: 'auto', diff --git a/src/components/results/MediaColumnFilter.tsx b/src/components/results/MediaColumnFilter.tsx index aeceb7bf..eef097ba 100644 --- a/src/components/results/MediaColumnFilter.tsx +++ b/src/components/results/MediaColumnFilter.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { FormControlLabel, Checkbox } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { FormControlLabel, Checkbox } from '@mui/material' import * as Types from './types' diff --git a/src/components/results/RecordDescription.tsx b/src/components/results/RecordDescription.tsx index 9667cd36..85fa1c85 100644 --- a/src/components/results/RecordDescription.tsx +++ b/src/components/results/RecordDescription.tsx @@ -1,6 +1,8 @@ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import { MarkdownWithRouteLinks } from 'components/generic' import { isAlpha } from '../../utils' diff --git a/src/components/results/ResultsModal.tsx b/src/components/results/ResultsModal.tsx index 6190fe5f..000f01d8 100644 --- a/src/components/results/ResultsModal.tsx +++ b/src/components/results/ResultsModal.tsx @@ -1,6 +1,6 @@ import React, { FC, useContext, useEffect, useState } from 'react' import { useHistory, useLocation, useRouteMatch } from 'react-router-dom' -import { Dialog } from '@material-ui/core' +import { Dialog } from '@mui/material' import { DialogCloseBtn, SlideUp } from 'components/generic/modals' import { InstanceLevelSchema, GlobalContext } from 'components/context' diff --git a/src/components/results/ResultsTitle.tsx b/src/components/results/ResultsTitle.tsx index 94ab8fcb..b48a41b5 100644 --- a/src/components/results/ResultsTitle.tsx +++ b/src/components/results/ResultsTitle.tsx @@ -1,8 +1,10 @@ /* eslint-disable operator-linebreak */ /* eslint-disable react/display-name */ import React, { FC } from 'react' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' -import { Typography } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Typography } from '@mui/material' import { BsTable } from 'react-icons/bs' const useStyles = makeStyles((theme: Theme) => @@ -11,7 +13,7 @@ const useStyles = makeStyles((theme: Theme) => gridArea: 'title', display: 'flex', alignItems: 'center', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { '& .MuiFormControl-root': { paddingLeft: 8 }, }, }, diff --git a/src/components/results/ResultsToolbar.tsx b/src/components/results/ResultsToolbar.tsx index 1f78c4e6..3db90c63 100644 --- a/src/components/results/ResultsToolbar.tsx +++ b/src/components/results/ResultsToolbar.tsx @@ -1,8 +1,10 @@ import React, { FC, useContext, useEffect } from 'react' import { useHistory } from 'react-router-dom' -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' import { MTableToolbar } from 'material-table' -import { Button } from '@material-ui/core' +import { Button } from '@mui/material' import { BiMapPin } from 'react-icons/bi' import { FaMap } from 'react-icons/fa' import { RiFilterOffFill } from 'react-icons/ri' diff --git a/src/components/results/styles.ts b/src/components/results/styles.ts index 402110a3..0d01c65f 100644 --- a/src/components/results/styles.ts +++ b/src/components/results/styles.ts @@ -1,4 +1,7 @@ -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' + +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' const footerCell = '.MuiTableCell-footer' const footerWrap = '.MuiPaper-root > .MuiTable-root' @@ -7,7 +10,7 @@ const headCell = '.MuiTableCell-head' export const useStyles = makeStyles((theme: Theme) => createStyles({ resultsModalRoot: { - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { '& .MuiTableFooter-root .MuiIconButton-root': { padding: 4, // waaaaayy too much default padding, can't see on mobile }, @@ -71,9 +74,9 @@ export const useStyles = makeStyles((theme: Theme) => }, // Squeeze a bit more room out of the dialog resultsModalPaper: { - height: `calc(100% - ${theme.spacing(2)}px)`, + height: `calc(100% - ${theme.spacing(2)})`, maxHeight: '100%', - [theme.breakpoints.down('sm')]: { + [theme.breakpoints.down('md')]: { height: '100%', margin: 0, }, diff --git a/src/components/results/utils.tsx b/src/components/results/utils.tsx index 56c519a1..f29f629e 100644 --- a/src/components/results/utils.tsx +++ b/src/components/results/utils.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { IconButton } from '@material-ui/core' +import { IconButton } from '@mui/material' import { GoFile } from 'react-icons/go' import { FaMapMarkedAlt } from 'react-icons/fa' diff --git a/src/components/style-guide/DemoBreadcrumbs.tsx b/src/components/style-guide/DemoBreadcrumbs.tsx index 48eb1b18..c62c7de8 100644 --- a/src/components/style-guide/DemoBreadcrumbs.tsx +++ b/src/components/style-guide/DemoBreadcrumbs.tsx @@ -1,7 +1,9 @@ import React, { FC } from 'react' import { Link as RouteLink } from 'react-router-dom' -import { Theme, createStyles, makeStyles } from '@material-ui/core/styles' -import { Breadcrumbs, Typography, Link } from '@material-ui/core' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { Breadcrumbs, Typography, Link } from '@mui/material' const useStyles = makeStyles((theme: Theme) => createStyles({ diff --git a/src/components/style-guide/DemoBtns.tsx b/src/components/style-guide/DemoBtns.tsx index b41df510..a738a34e 100644 --- a/src/components/style-guide/DemoBtns.tsx +++ b/src/components/style-guide/DemoBtns.tsx @@ -1,12 +1,14 @@ import React, { FC } from 'react' -import { makeStyles, createStyles, Theme } from '@material-ui/core/styles' +import { Theme } from '@mui/material/styles' +import makeStyles from '@mui/styles/makeStyles' +import createStyles from '@mui/styles/createStyles' import { Button, ButtonGroup, IconButton, Paper, Typography, -} from '@material-ui/core' +} from '@mui/material' import { MdDelete } from 'react-icons/md' import { DemoSplitBtn } from 'components/style-guide' @@ -124,13 +126,13 @@ export const DemoBtns: FC = () => { - + - + - + @@ -150,7 +152,7 @@ export const DemoBtns: FC = () => { > Text first - + + +
+ + +
Local community data diff --git a/src/components/results/types.ts b/src/components/results/types.ts index fc2896bf..0d0b3cb3 100644 --- a/src/components/results/types.ts +++ b/src/components/results/types.ts @@ -25,6 +25,7 @@ export type ResultsToolbarProps = { scrollToTop: () => void clearBtnEnabled: boolean setClearBtnEnabled: React.Dispatch + columns: ColumnList } export type FilterComponentProps = { From a97713e2c25d419ea1c2bec20e3f57c75420a199 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:26:40 -0400 Subject: [PATCH 06/11] Auto-size table rows so multi-value cells render fully Data Grid uses a fixed row height by default. Cells with multiple values per row (Country with two flags, Endonym wrapping non-Latin scripts, etc.) were getting clipped and bleeding into adjacent rows. Setting getRowHeight to 'auto' lets each row grow to fit its tallest cell; getEstimatedRowHeight keeps virtualization fast on the 1000+ row dataset. Cell content is top-aligned so single-line columns line up cleanly with multi-line ones. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/results/ResultsTable.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/components/results/ResultsTable.tsx b/src/components/results/ResultsTable.tsx index 7b22ad6b..fb15ad01 100644 --- a/src/components/results/ResultsTable.tsx +++ b/src/components/results/ResultsTable.tsx @@ -79,6 +79,8 @@ export const ResultsTable: FC = (props) => { getRowId={(row) => row.id} density="compact" disableRowSelectionOnClick + getRowHeight={() => 'auto'} + getEstimatedRowHeight={() => 36} onCellClick={onCellClick} onFilterModelChange={() => { setClearBtnEnabled(true) @@ -92,6 +94,13 @@ export const ResultsTable: FC = (props) => { pageSizeOptions={[10, 20, 50]} slots={{ toolbar: ResultsToolbar }} slotProps={slotProps} + sx={{ + '& .MuiDataGrid-cell': { + alignItems: 'flex-start', + paddingTop: '6px', + paddingBottom: '6px', + }, + }} /> From 6182302caf69e5d6fdc6325e2e850e70ce51f9a9 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:29:52 -0400 Subject: [PATCH 07/11] Align "Has media" checkbox with the rest of the filter row The MediaFilterInput rendered the checkbox too high because the default FormControlLabel doesn't share Data Grid's filter input baseline. Bottom-align it and pull the original 'http' marker color in via the secondary palette so the checkbox tone matches the other filter controls. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/results/MediaColumnFilter.tsx | 27 +++++++++----------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/components/results/MediaColumnFilter.tsx b/src/components/results/MediaColumnFilter.tsx index daea4317..4f4457ef 100644 --- a/src/components/results/MediaColumnFilter.tsx +++ b/src/components/results/MediaColumnFilter.tsx @@ -1,24 +1,11 @@ import React from 'react' import { GridFilterInputValueProps, GridFilterOperator } from '@mui/x-data-grid' import { FormControlLabel, Checkbox } from '@mui/material' -import { Theme } from '@mui/material/styles' -import createStyles from '@mui/styles/createStyles' -import makeStyles from '@mui/styles/makeStyles' const CHECK_VALUE = 'http' -const useStyles = makeStyles((theme: Theme) => - createStyles({ - root: { - color: theme.palette.secondary.main, - marginLeft: 2, - }, - }) -) - const MediaFilterInput: React.FC = (props) => { const { item, applyValue } = props - const classes = useStyles() const checked = item.value === CHECK_VALUE const handleChange = (e: React.ChangeEvent) => { @@ -27,9 +14,19 @@ const MediaFilterInput: React.FC = (props) => { return ( + } label="Has media" /> From 6619cb9039cdeced3e0bd31ae289b0d432489a56 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:44:03 -0400 Subject: [PATCH 08/11] Replace @mui/x-data-grid with @tanstack/react-table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Data Grid's free tier (community v6) hard-codes disableMultipleColumnsFiltering: true, so users could only filter on one column at a time. Multi-column filtering is paywalled to the Pro plan in v6, and v5 — the last version that had it free — was last released March 2023 and is no longer maintained. TanStack Table v8 is headless and actively maintained, supports React 16/17/18+, and its filter model has no paywall. The trade-off is that we render the table primitives ourselves with MUI Table / TableHead / TableBody, which lets us bring back material-table's per-column filter row UX (text input by default, Select for lookup columns, the Has-media checkbox for Audio/Video). Other features carried over: - Global search box (matches across visible columns) - Column visibility menu in the toolbar - CSV / PDF export wired to filtered+sorted rows - "View in map" and "Clear filters" buttons unchanged Column config moved to TanStack column defs via createColumnHelper. Cell renderers now receive a CellContext and read row.original; filter logic for Audio/Video lives in mediaUrlFilterFn. Co-Authored-By: Claude Opus 4.7 (1M context) --- package.json | 2 +- src/components/results/Cells.tsx | 32 +- src/components/results/MediaColumnFilter.tsx | 67 ++- src/components/results/ResultsTable.tsx | 430 ++++++++++++++++--- src/components/results/ResultsToolbar.tsx | 144 ++++--- src/components/results/config.tsx | 301 +++++-------- src/components/results/exporting.ts | Bin 6789 -> 4893 bytes src/components/results/types.ts | 71 +-- src/components/results/utils.tsx | 10 +- yarn.lock | 34 +- 10 files changed, 690 insertions(+), 401 deletions(-) diff --git a/package.json b/package.json index d8888e62..6fe478c7 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ "@mui/lab": "^5.0.0-alpha.176", "@mui/material": "^5.16.7", "@mui/styles": "^5.16.7", - "@mui/x-data-grid": "^6", "@sentry/react": "^5.24.2", + "@tanstack/react-table": "^8.21.3", "@testing-library/jest-dom": "^5.11.0", "@testing-library/react": "^10.4.5", "@testing-library/user-event": "^7.1.2", diff --git a/src/components/results/Cells.tsx b/src/components/results/Cells.tsx index 7c32e988..82805cec 100644 --- a/src/components/results/Cells.tsx +++ b/src/components/results/Cells.tsx @@ -7,7 +7,7 @@ import { GoCircleSlash } from 'react-icons/go' import { LegendSwatch } from 'components/legend' import { InstanceLevelSchema } from 'components/context/types' -import { LangCellParams } from './types' +import { LangCellContext } from './types' const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -18,12 +18,12 @@ const useStyles = makeStyles((theme: Theme) => ) export const MediaColumnCell: FC<{ - params: LangCellParams + info: LangCellContext columnName: keyof InstanceLevelSchema }> = (props) => { const classes = useStyles() - const { params, columnName } = props - const data = params.row + const { info, columnName } = props + const data = info.row.original return (
@@ -32,10 +32,10 @@ export const MediaColumnCell: FC<{ ) } -export const GlobalSpeakers: FC<{ params: LangCellParams }> = (props) => { +export const GlobalSpeakers: FC<{ info: LangCellContext }> = (props) => { const classes = useStyles() - const { params } = props - const data = params.row + const { info } = props + const data = info.row.original if (!data['Global Speaker Total']) return null @@ -46,18 +46,18 @@ export const GlobalSpeakers: FC<{ params: LangCellParams }> = (props) => { ) } -export const CommStatus: FC<{ params: LangCellParams }> = (props) => { +export const CommStatus: FC<{ info: LangCellContext }> = (props) => { const classes = useStyles() - const { params } = props - const data = params.row + const { info } = props + const data = info.row.original return
{data.Status}
} -export const CommSize: FC<{ params: LangCellParams }> = (props) => { +export const CommSize: FC<{ info: LangCellContext }> = (props) => { const theme = useTheme() - const { params } = props - const data = params.row + const { info } = props + const data = info.row.original const { Size, sizeColor } = data return ( @@ -76,9 +76,9 @@ export const CommSize: FC<{ params: LangCellParams }> = (props) => { ) } -export const WorldRegion: FC<{ params: LangCellParams }> = (props) => { - const { params } = props - const data = params.row +export const WorldRegion: FC<{ info: LangCellContext }> = (props) => { + const { info } = props + const data = info.row.original return ( = (props) => { - const { item, applyValue } = props - const checked = item.value === CHECK_VALUE +// TanStack column filter that matches rows whose value contains "http" +// (used for the Audio/Video URL columns). +export const mediaUrlFilterFn: LangFilterFn = (row, columnId, filterValue) => { + if (!filterValue) return true + + const value = row.getValue(columnId) - const handleChange = (e: React.ChangeEvent) => { - applyValue({ ...item, value: e.target.checked ? CHECK_VALUE : '' }) + if (!value) return false + if (typeof value === 'string') return value.includes(CHECK_VALUE) + if (Array.isArray(value)) { + return value.some((v) => typeof v === 'string' && v.includes(CHECK_VALUE)) } + return false +} + +export const MediaColumnFilter: FC<{ + column: Column +}> = ({ column }) => { + const checked = (column.getFilterValue() as boolean) || false + return ( column.setFilterValue(e.target.checked || undefined)} /> } - label="Has media" + label="Has" /> ) } - -// Single operator: "has URL" — value is truthy and contains "http" -export const mediaHasUrlOperator: GridFilterOperator = { - label: 'has media', - value: 'hasMedia', - getApplyFilterFn: (filterItem) => { - if (filterItem.value !== CHECK_VALUE) return null - - return ({ value }) => { - if (!value) return false - if (typeof value === 'string') return value.includes(CHECK_VALUE) - if (Array.isArray(value)) { - return value.some( - (v) => typeof v === 'string' && v.includes(CHECK_VALUE) - ) - } - - return false - } - }, - InputComponent: MediaFilterInput, -} diff --git a/src/components/results/ResultsTable.tsx b/src/components/results/ResultsTable.tsx index fb15ad01..b1f465d4 100644 --- a/src/components/results/ResultsTable.tsx +++ b/src/components/results/ResultsTable.tsx @@ -1,40 +1,177 @@ /* eslint-disable react/display-name */ -import React, { FC, useState, useCallback, useRef } from 'react' +import React, { FC, useMemo, useRef, useState } from 'react' import { Route, useHistory } from 'react-router-dom' import { - DataGrid, - GridCellParams, - GridColumnVisibilityModel, - useGridApiRef, -} from '@mui/x-data-grid' + Box, + MenuItem, + Select, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + TableSortLabel, + TextField, +} from '@mui/material' +import { Theme } from '@mui/material/styles' +import createStyles from '@mui/styles/createStyles' +import makeStyles from '@mui/styles/makeStyles' +import { + ColumnFiltersState, + ColumnOrderState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from '@tanstack/react-table' import { routes } from 'components/config/api' -import { InstanceLevelSchema } from 'components/context' +import { InstanceLevelSchema } from 'components/context/types' import { DetailsModal } from './DetailsModal' import { ResultsToolbar } from './ResultsToolbar' import { columns as columnConfig, initialColumnVisibility } from './config' -import { ResultsTableProps } from './types' +import { MediaColumnFilter } from './MediaColumnFilter' +import { LangColumnMeta, ResultsTableProps } from './types' + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + container: { + display: 'flex', + flexDirection: 'column', + height: '100%', + width: '100%', + }, + tableScroll: { + flex: 1, + overflow: 'auto', + }, + table: { + borderCollapse: 'separate', + tableLayout: 'auto', + '& th, & td': { + verticalAlign: 'top', + }, + }, + headerRow: { + backgroundColor: theme.palette.background.paper, + }, + filterRow: { + backgroundColor: theme.palette.background.paper, + '& th': { + paddingTop: 4, + paddingBottom: 4, + }, + }, + bodyRow: { + cursor: 'pointer', + '&:hover': { backgroundColor: theme.palette.action.hover }, + }, + actionsCell: { + paddingLeft: 4, + paddingRight: 4, + width: 56, + }, + pagination: { + alignItems: 'center', + borderTop: `1px solid ${theme.palette.divider}`, + display: 'flex', + flexWrap: 'wrap', + gap: '0.75rem', + justifyContent: 'flex-end', + padding: '0.5rem 1rem', + }, + paginationBtn: { + background: 'transparent', + border: `1px solid ${theme.palette.divider}`, + borderRadius: 4, + color: theme.palette.text.primary, + cursor: 'pointer', + padding: '0.25rem 0.6rem', + '&:disabled': { + cursor: 'not-allowed', + opacity: 0.4, + }, + }, + }) +) + +const PAGE_SIZE_OPTIONS = [10, 20, 50] export const ResultsTable: FC = (props) => { const { data: tableData } = props + const classes = useStyles() const history = useHistory() - const apiRef = useGridApiRef() const containerRef = useRef(null) const [clearBtnEnabled, setClearBtnEnabled] = useState(false) - const [columnVisibility, setColumnVisibility] = useState< - GridColumnVisibilityModel - >(initialColumnVisibility) + const [globalFilter, setGlobalFilter] = useState('') + const [columnFilters, setColumnFilters] = useState([]) + const [sorting, setSorting] = useState([]) + const [columnVisibility, setColumnVisibility] = useState( + initialColumnVisibility + ) + const [columnOrder, setColumnOrder] = useState([]) + + const columns = useMemo(() => columnConfig, []) + + const table = useReactTable({ + data: tableData, + columns, + state: { + globalFilter, + columnFilters, + sorting, + columnVisibility, + columnOrder, + }, + onGlobalFilterChange: (updater) => { + setGlobalFilter( + typeof updater === 'function' ? updater(globalFilter) : updater + ) + setClearBtnEnabled(true) + }, + onColumnFiltersChange: (updater) => { + setColumnFilters((old) => + typeof updater === 'function' ? updater(old) : updater + ) + setClearBtnEnabled(true) + }, + onSortingChange: setSorting, + onColumnVisibilityChange: setColumnVisibility, + onColumnOrderChange: setColumnOrder, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + initialState: { + pagination: { pageSize: 20 }, + }, + }) + + const scrollToTop = () => { + containerRef.current?.scrollTo({ top: 0 }) + } - const scrollToTop = useCallback(() => { - containerRef.current?.scrollIntoView(true) - }, []) + const visibleRows: InstanceLevelSchema[] = table + .getFilteredRowModel() + .rows.map((r) => r.original) + + const resetFilters = () => { + setGlobalFilter('') + setColumnFilters([]) + setClearBtnEnabled(false) + scrollToTop() + } const onCellClick = ( - params: GridCellParams, + field: string, + row: InstanceLevelSchema, event: React.MouseEvent ): void => { - const { field, row } = params - if (field === 'actions-id') { history.push(`/Explore/Language/${row.Language}/${row.id}`) @@ -47,62 +184,231 @@ export const ResultsTable: FC = (props) => { return } - // Endonym image cells handle their own modal — bail so the row click - // doesn't double-fire if (field === 'Endonym' && row['Font Image Alt']) return event.stopPropagation() } - const slotProps = { - toolbar: { - clearBtnEnabled, - setClearBtnEnabled, - scrollToTop, - columns: columnConfig, - }, - } - return ( - <> + -
- row.id} - density="compact" - disableRowSelectionOnClick - getRowHeight={() => 'auto'} - getEstimatedRowHeight={() => 36} - onCellClick={onCellClick} - onFilterModelChange={() => { - setClearBtnEnabled(true) + { + const headerDef = column.columnDef.header + const label = typeof headerDef === 'string' ? headerDef : column.id + + return { + id: column.id, + label, + isVisible: column.getIsVisible(), + canHide: column.getCanHide(), + toggle: () => column.toggleVisibility(), + } + })} + /> + + + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + const sortable = header.column.getCanSort() + const sortDir = header.column.getIsSorted() + const isActions = header.column.id.startsWith('actions-') + + return ( + + {sortable ? ( + + {flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ) : ( + flexRender( + header.column.columnDef.header, + header.getContext() + ) + )} + + ) + })} + + ))} + {/* Per-column filter row, à la material-table */} + + {table.getVisibleLeafColumns().map((column) => { + const meta = column.columnDef.meta as LangColumnMeta | undefined + const canFilter = column.getCanFilter() && !meta?.unfilterable + + if (!canFilter) { + return + } + + if (meta?.mediaFilter) { + return ( + + + + ) + } + + if (meta?.lookup) { + const value = (column.getFilterValue() as string) || '' + + return ( + + + + ) + } + + const value = (column.getFilterValue() as string) || '' + + return ( + + + column.setFilterValue(e.target.value || undefined) + } + /> + + ) + })} + + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => { + const isActions = cell.column.id.startsWith('actions-') + + return ( + + onCellClick(cell.column.id, row.original, e) + } + className={isActions ? classes.actionsCell : undefined} + > + {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} + + ) + })} + + ))} + {table.getRowModel().rows.length === 0 && ( + + + No communities found. Try fewer criteria or click "Clear + filters" to reset the table. + + + )} + +
+
+
+ + Rows per page:  + + + + {(() => { + const total = table.getFilteredRowModel().rows.length + + if (total === 0) return '0–0 of 0' + + const { pageIndex, pageSize } = table.getState().pagination + const start = pageIndex * pageSize + 1 + const end = Math.min((pageIndex + 1) * pageSize, total) + + return `${start}–${end} of ${total}` + })()} + + +
- + ) } diff --git a/src/components/results/ResultsToolbar.tsx b/src/components/results/ResultsToolbar.tsx index dfa3804f..a6a749f4 100644 --- a/src/components/results/ResultsToolbar.tsx +++ b/src/components/results/ResultsToolbar.tsx @@ -1,22 +1,23 @@ -import React, { FC, useContext, useEffect } from 'react' +import React, { FC, useContext, useEffect, useState } from 'react' import { useHistory } from 'react-router-dom' import { Theme } from '@mui/material/styles' import createStyles from '@mui/styles/createStyles' import makeStyles from '@mui/styles/makeStyles' -import { Button } from '@mui/material' import { - GridToolbarContainer, - GridToolbarColumnsButton, - GridToolbarFilterButton, - GridToolbarQuickFilter, - gridFilteredSortedRowEntriesSelector, - useGridApiContext, -} from '@mui/x-data-grid' + Button, + Checkbox, + FormControlLabel, + InputAdornment, + Menu, + MenuItem, + TextField, +} from '@mui/material' import { BiMapPin } from 'react-icons/bi' import { FaMap, FaFileCsv, FaFilePdf } from 'react-icons/fa' +import { GoSearch } from 'react-icons/go' +import { MdViewColumn } from 'react-icons/md' import { RiFilterOffFill } from 'react-icons/ri' -import { InstanceLevelSchema } from 'components/context/types' import { GlobalContext } from 'components/context' import { routes } from 'components/config/api' import { PopoverWithUItext } from 'components/generic' @@ -31,10 +32,7 @@ export const useStyles = makeStyles((theme: Theme) => resultsToolbarRoot: { padding: '0.5em 0.75em', borderBottom: `solid ${theme.palette.divider} 2px`, - position: 'sticky', - top: 0, backgroundColor: theme.palette.background.paper, - zIndex: 11, display: 'grid', alignItems: 'center', gridColumnGap: '0.75em', @@ -44,20 +42,12 @@ export const useStyles = makeStyles((theme: Theme) => "exports exports" "local local"`, gridTemplateColumns: 'auto 1fr', - gridTemplateRows: 'auto auto auto auto', '& .MuiIconButton-root': { padding: 4 }, - [theme.breakpoints.up('sm')]: { - gridTemplateColumns: 'auto auto', - justifyContent: 'center', - gridColumnGap: '1em', - }, [theme.breakpoints.up('md')]: { gridTemplateAreas: `"title buttons exports local searchAndActions"`, gridTemplateColumns: 'auto auto auto auto 1fr', gridTemplateRows: 'auto', - justifyContent: 'flex-start', - padding: '0.75em 1em 0', - height: 'auto', + padding: '0.75em 1em', }, }, searchAndActions: { @@ -66,7 +56,6 @@ export const useStyles = makeStyles((theme: Theme) => alignItems: 'center', [theme.breakpoints.up('md')]: { justifyContent: 'flex-end', - marginRight: 8, }, }, localIndicator: { @@ -80,10 +69,9 @@ export const useStyles = makeStyles((theme: Theme) => fontSize: '0.75em', gridArea: 'local', justifyContent: 'center', - marginTop: '0.4em', textAlign: 'center', '& svg': { fontSize: '1.2em' }, - [theme.breakpoints.up('md')]: { marginTop: 0, justifySelf: 'flex-end' }, + [theme.breakpoints.up('md')]: { justifySelf: 'flex-end' }, }, toolbarBtns: { alignItems: 'center', @@ -104,31 +92,31 @@ export const useStyles = makeStyles((theme: Theme) => ) export const ResultsToolbar: FC = (props) => { - const { clearBtnEnabled, setClearBtnEnabled, scrollToTop, columns } = props + const { + clearBtnEnabled, + setClearBtnEnabled, + scrollToTop, + visibleRows, + globalFilter, + setGlobalFilter, + resetFilters, + rowCount, + columns, + columnToggles, + } = props const { state, dispatch } = useContext(GlobalContext) const classes = useStyles() const history = useHistory() - const apiRef = useGridApiContext() - - const rowCount = apiRef.current.getRowsCount() const noResults = rowCount === 0 - const getVisibleRows = (): InstanceLevelSchema[] => - gridFilteredSortedRowEntriesSelector(apiRef).map( - (entry) => entry.model as InstanceLevelSchema - ) - function clearFiltersBtnClick(physicalClick?: boolean): void { - apiRef.current.setFilterModel({ items: [] }) - apiRef.current.setQuickFilterValues([]) - setClearBtnEnabled(false) - scrollToTop() + resetFilters() if (!physicalClick) { dispatch({ type: 'CLEAR_FILTERS', payload: 0 }) dispatch({ type: 'SET_LANG_LAYER_FEATURES', - payload: whittleLangFeats(getVisibleRows()), + payload: whittleLangFeats(visibleRows), }) } } @@ -141,8 +129,6 @@ export const ResultsToolbar: FC = (props) => { }, [state.clearFilters]) function mapFilterBtnClick(): void { - const visibleRows = getVisibleRows() - dispatch({ type: 'SET_LANG_LAYER_FEATURES', payload: whittleLangFeats(visibleRows), @@ -158,13 +144,26 @@ export const ResultsToolbar: FC = (props) => { } return ( - +
- setClearBtnEnabled(true)} + value={globalFilter} + onChange={(e) => { + setGlobalFilter(e.target.value) + setClearBtnEnabled(true) + scrollToTop() + }} + InputProps={{ + startAdornment: ( + + + + ), + }} />
@@ -179,8 +178,7 @@ export const ResultsToolbar: FC = (props) => { > View in map - - + @@ -211,7 +209,7 @@ export const ResultsToolbar: FC = (props) => { variant="outlined" size="small" startIcon={} - onClick={() => exportPdf(columns, getVisibleRows())} + onClick={() => exportPdf(columns, visibleRows)} > PDF @@ -219,6 +217,54 @@ export const ResultsToolbar: FC = (props) => { Local community data - +
+ ) +} + +const ColumnVisibilityMenu: FC<{ toggles: Types.ColumnToggle[] }> = (props) => { + const { toggles } = props + const [anchorEl, setAnchorEl] = useState(null) + + return ( + <> + + setAnchorEl(null)} + > + {toggles + .filter((t) => t.canHide) + .map((t) => ( + t.toggle()} + sx={{ paddingY: 0 }} + > + e.preventDefault()} + control={ + + } + label={t.label} + /> + + ))} + + ) } diff --git a/src/components/results/config.tsx b/src/components/results/config.tsx index c210153d..eda15356 100644 --- a/src/components/results/config.tsx +++ b/src/components/results/config.tsx @@ -1,13 +1,14 @@ /* eslint-disable react/display-name */ import React from 'react' +import { createColumnHelper } from '@tanstack/react-table' -import { Statuses } from 'components/context/types' +import { InstanceLevelSchema, Statuses } from 'components/context/types' import * as Types from './types' import * as utils from './utils' import * as Cells from './Cells' -import { mediaHasUrlOperator } from './MediaColumnFilter' +import { mediaUrlFilterFn } from './MediaColumnFilter' import { LocalColumnTitle } from './LocalColumnTitle' const COMM_STATUS_LOOKUP = { @@ -26,7 +27,7 @@ export const tableExportMeta = { fullDatasetURL: 'https://airtable.com/shrqQo5FJHvhKtffs', } -const SIZE_MAP = { +const SIZE_MAP: { [key: string]: number } = { Smallest: 1, Small: 2, Medium: 3, @@ -42,194 +43,122 @@ const COMM_SIZES = { Largest: 'Largest', } -const commonColProps = { - editable: false, - filterable: true, - sortable: true, -} - -const hiddenCols: Types.LangColumn[] = [ - { - headerName: 'Glottocode', - title: 'Glottocode', - field: 'Glottocode', - flex: 1, - minWidth: 120, - hidden: true, - ...commonColProps, - }, - { - headerName: 'ISO 639-3', - title: 'ISO 639-3', - field: 'ISO 639-3', - flex: 1, - minWidth: 120, - hidden: true, - ...commonColProps, - }, - { - headerName: 'Additional Neighborhoods', - title: 'Additional Neighborhoods', - field: 'Additional Neighborhoods', - flex: 1, - minWidth: 200, - hidden: true, - ...commonColProps, - }, -] +const ch = createColumnHelper() -export const columns: Types.LangColumn[] = [ - { - headerName: '', - title: 'View in map', - field: 'actions-id', - width: 56, - sortable: false, - filterable: false, - export: false, - renderCell: utils.renderIDcolumn, - }, - { - headerName: '', - title: 'County', - field: 'actions-county', - width: 56, - sortable: false, - filterable: false, - export: false, - renderCell: utils.renderDescripCol, - }, - { - headerName: 'Language', - title: 'Language', - field: 'Language', - flex: 1, - minWidth: 140, - ...commonColProps, - }, - { - headerName: 'Endonym', - title: 'Endonym', - field: 'Endonym', - flex: 1, - minWidth: 140, - ...commonColProps, - renderCell: utils.renderEndoColumn, - }, - { - headerName: 'World Region', - title: 'World Region', - field: 'World Region', - flex: 1, - minWidth: 160, - ...commonColProps, - renderCell: (params) => , - }, - { - headerName: 'Country', - title: 'Country', - field: 'Country', - flex: 1, - minWidth: 180, - ...commonColProps, - renderCell: utils.renderCountryColumn, - valueGetter: (params) => - Array.isArray(params.row.Country) ? params.row.Country.join(', ') : '', - }, - { - headerName: 'Global Speakers', - title: 'Global Speakers', - field: 'Global Speaker Total', - width: 140, - type: 'number', - sortable: true, - filterable: false, - renderCell: (params) => , - }, - { - headerName: 'Language Family', - title: 'Language Family', - field: 'Language Family', - flex: 1, - minWidth: 160, - ...commonColProps, - }, - { - headerName: 'Video', - title: 'Video', - field: 'Video', - width: 90, - sortable: false, - filterable: true, - filterOperators: [mediaHasUrlOperator], - export: false, - renderCell: (params) => ( - - ), - }, - { - headerName: 'Audio', - title: 'Audio', - field: 'Audio', - width: 90, - sortable: false, - filterable: true, - filterOperators: [mediaHasUrlOperator], - export: false, - renderCell: (params) => ( - - ), - }, - { - headerName: 'Location', - title: , - field: 'Primary Location', - flex: 1, - minWidth: 160, - ...commonColProps, - renderHeader: () => , - }, - { - headerName: 'Size', - title: , - field: 'Size', - width: 130, - type: 'singleSelect', - valueOptions: Object.values(COMM_SIZES), - lookup: COMM_SIZES, - sortable: true, - filterable: true, - sortComparator: (a, b) => { - const va = SIZE_MAP[a as keyof typeof SIZE_MAP] || 0 - const vb = SIZE_MAP[b as keyof typeof SIZE_MAP] || 0 +export const columns: Types.ColumnList = [ + ch.display({ + id: 'actions-id', + header: '', + size: 56, + enableSorting: false, + enableColumnFilter: false, + enableHiding: false, + cell: utils.renderIDcolumn, + meta: { excludeFromExport: true, unfilterable: true }, + }), + ch.display({ + id: 'actions-county', + header: '', + size: 56, + enableSorting: false, + enableColumnFilter: false, + enableHiding: false, + cell: utils.renderDescripCol, + meta: { excludeFromExport: true, unfilterable: true }, + }), + ch.accessor('Language', { + header: 'Language', + cell: (info) => info.getValue(), + meta: { exportTitle: 'Language' }, + }), + ch.accessor('Endonym', { + header: 'Endonym', + cell: utils.renderEndoColumn, + meta: { exportTitle: 'Endonym' }, + }), + ch.accessor('World Region', { + header: 'World Region', + cell: (info) => , + meta: { exportTitle: 'World Region' }, + }), + ch.accessor( + (row) => (Array.isArray(row.Country) ? row.Country.join(', ') : ''), + { + id: 'Country', + header: 'Country', + cell: utils.renderCountryColumn, + meta: { exportTitle: 'Country' }, + } + ), + ch.accessor('Global Speaker Total', { + header: 'Global Speakers', + cell: (info) => , + enableColumnFilter: false, + sortingFn: 'basic', + meta: { exportTitle: 'Global Speakers', unfilterable: true }, + }), + ch.accessor('Language Family', { + header: 'Language Family', + cell: (info) => info.getValue(), + meta: { exportTitle: 'Language Family' }, + }), + ch.accessor('Video', { + header: 'Video', + cell: (info) => , + enableSorting: false, + filterFn: mediaUrlFilterFn, + meta: { exportTitle: 'Video', mediaFilter: true, excludeFromExport: true }, + }), + ch.accessor('Audio', { + header: 'Audio', + cell: (info) => , + enableSorting: false, + filterFn: mediaUrlFilterFn, + meta: { exportTitle: 'Audio', mediaFilter: true, excludeFromExport: true }, + }), + ch.accessor('Primary Location', { + header: () => , + cell: (info) => info.getValue(), + meta: { exportTitle: 'Location' }, + }), + ch.accessor('Size', { + header: () => , + cell: (info) => , + sortingFn: (a, b) => { + const va = SIZE_MAP[a.original.Size as string] || 0 + const vb = SIZE_MAP[b.original.Size as string] || 0 if (va === vb) return 0 return va > vb ? 1 : -1 }, - renderCell: (params) => , - renderHeader: () => , - }, - { - headerName: 'Status', - title: , - field: 'Status', - width: 140, - type: 'singleSelect', - valueOptions: Object.values(COMM_STATUS_LOOKUP), - lookup: COMM_STATUS_LOOKUP, - sortable: true, - filterable: true, - renderCell: (params) => , - renderHeader: () => , - }, - ...hiddenCols, + meta: { exportTitle: 'Size', lookup: COMM_SIZES }, + }), + ch.accessor('Status', { + header: () => , + cell: (info) => , + meta: { exportTitle: 'Status', lookup: COMM_STATUS_LOOKUP }, + }), + ch.accessor('Glottocode', { + header: 'Glottocode', + cell: (info) => info.getValue(), + meta: { exportTitle: 'Glottocode' }, + }), + ch.accessor('ISO 639-3', { + header: 'ISO 639-3', + cell: (info) => info.getValue(), + meta: { exportTitle: 'ISO 639-3' }, + }), + ch.accessor('Additional Neighborhoods', { + header: 'Additional Neighborhoods', + cell: (info) => info.getValue(), + meta: { exportTitle: 'Additional Neighborhoods' }, + }), ] -export const initialColumnVisibility = columns.reduce<{ - [key: string]: boolean -}>((acc, col) => { - if (col.hidden) acc[col.field] = false - - return acc -}, {}) +// Hide the columns that were `hidden: true` in the material-table config. +export const initialColumnVisibility: { [key: string]: boolean } = { + Glottocode: false, + 'ISO 639-3': false, + 'Additional Neighborhoods': false, +} diff --git a/src/components/results/exporting.ts b/src/components/results/exporting.ts index 48b353be87c29c73e77f5d12edd71c14602ac96d..821bd6427f41b26f864c4b3ec778d2406a9d0335 100644 GIT binary patch delta 571 zcmZoQovSwC2bXI_L4Hw5Vp2}(#6OaY6BrpMPheVUsi|OVr=XaepQD$XT9Rn5ms*jW zQ<{?MR+OI$(V(EFrl6jfoSa%*oL}UfTB)v(nWq3$Ke?DWX!3978c7D-ll>2OH0VCu zz5mh11-g$m?te9Bf$ppM`!}y)*~5Lrzth2oN;%)E4vud2BefDQ%eE`e$S>VbO` z6c`Z0?CnAR(aT6pOi3-`0&2=kQ_v`>EJ)2yQz)5i#i1n$l1B1}LSix0n$4LUUW|OG zj+^|HQ+sj(SLWo!+><7I@Dy$S&r`)XIe=fx6le@MxHUj7gMgI8l0;yjT7g}F)r!ee z_!XIfIwv3GpE|i%K!5Ts0msQ=f-aNu1XU+*6IA1XnKfCFO?F7CO;IDW>Y9F0*2jWKTZkW(wrO@pc9HyOG1NuCYyWj$OsxRlK{{ad5M$8!Z1ogkW27s1Wdw*}Zdj$C*2G zJ2TgtZE7qb!4v%<-SSeY;)Ul>$xnTy5)YO5FZ$G%_5}%5MdCZN*NN5c%ig&&^PO|P z^PTVhdH&<;fA}uFElhvI>LN3AM5(hGEwtKUluN%*tMNZ=J;<#KqN`ii(rzh`Z%#mi-)+iO)%kukk zcgmTGD;KW4wz6_#b+z0&|H;Y+#jE%=@wdFP{Xwy`6&Fie+gL1byv94r8>?8XuP*aq zeRX^LnV5_PmQ#~gs;9L{s-6au?^RFVOn!8X0>>PA8mcg$J5uxl(#&#{YJw+a zyhbGd_w(SW$hn+~EVK={J{rm@f z$MNVWcDgUan8UlAYCR@gooJNm;?-SHb9Z-hx5H_8(A*n<4tnQJ8c2~aGZZYnfl5@7 z(Yg+cRCuOb1g1aW5J9GUy70K+WLaK3;KuFj-rb6rB1sgp2?A5gO=Hpl*_9wPk;y5Z z^60ENlrBie`_lAmB0H!QXoC=P-)Xm<81_|YK?3c!-5q7y2YzpJyPXLn;@XVQ81F`q z$IG~C4ML{JVCcO;PrVm?Ns7xrIJ_h;GD)}gcXyDf%TS;|@pvEAQumEk`JaoQJ%@Dm z_@W-d(RQc?Ok(Nlx37#GV6b8!FBi0K%hnWJFD0HAY=1)Fov?`3M zo(?jO3AQqk*Z*IyFS9k(c_hZaLq;BA-ZXui$BH4%sh!ETnvNX?=z_$4QNchlbWH1R6S#m;bu7`6J$++pt+y z7!^iy$Rzmk+SHYwjyC}5Anf(j!EFr2KQFpk^{R94PR+*v+Cugi5=PCLtwW&;>B|qN zHfxNtfsqrl6hE}1_VSGiV$hz!ckW*?c#DB8$?A*jF zj26{8RM3$R3SOs`xz9CPSLT=BXZdcx#_(n0acTSV>&t(g!po@XNN@S;=YIbp-rVMk zh?*8a;a))Twen||e^Sm)|L$21<+15RUuju>IX!dnv~lI%r>|b9L|A@1edU4d}^Hm@Zcr7ejkDAI4=uipDbo>& z?d8%nnJ&`S=1lj2&y%!?7`JSUdJ4D`ttsH8K1*g57t~`!#Gz0+rV5555FIYHUcFk* zJpU&i)7=~%0_))h7&+v!_{-9j@RRtha+o}DJP;_#7ip><#95r{YTKQQ=Aa&&nbR)V z2m^TF5T4V8vz!i?MIe?8;`9pVAUOItg0y8G29zv3V1?Tb`6wMYzWEEq9; z0RH>)FaB6Qdj7p%o-*+U_XKfySQukCfI)=?k2`^K3xX?;7>GkjXc=St_Ajv#zKLRk zwd~PsHs$R3nRU1vWCs&$uPohISzWz$z1@p)YZ|y~6UN$P3YvvuH$LJnkCg#3>y6q` F?FW%D8ma&Q diff --git a/src/components/results/types.ts b/src/components/results/types.ts index 0d0b3cb3..614ee6ec 100644 --- a/src/components/results/types.ts +++ b/src/components/results/types.ts @@ -1,37 +1,37 @@ -import { - GridColDef, - GridFilterItem, - GridRenderCellParams, -} from '@mui/x-data-grid' +import { CellContext, ColumnDef, FilterFn, Row } from '@tanstack/react-table' import { InstanceLevelSchema } from 'components/context/types' import { AirtableError } from 'components/explore/types' -export type LangColumn = GridColDef & { - field: keyof InstanceLevelSchema | 'actions-id' | 'actions-county' - title: string | React.ReactElement - hidden?: boolean - export?: boolean +export type LangColumnMeta = { + // Human-readable column title for export (PDF/CSV) and filter labels. + exportTitle?: string | React.ReactElement + // If true, exclude from CSV/PDF export. + excludeFromExport?: boolean + // Predefined value set, used to render a select dropdown filter. lookup?: { [key: string]: string } + // Render a "has media" checkbox filter instead of the default text input. + mediaFilter?: boolean + // Hide the per-column filter input. + unfilterable?: boolean +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type LangColumn = ColumnDef & { + meta?: LangColumnMeta } export type ColumnList = LangColumn[] export type InitialData = InstanceLevelSchema[] -export type CountryCodes = { [key: string]: string } -export type ResultsTableProps = { data: InstanceLevelSchema[] } - -export type ResultsToolbarProps = { - scrollToTop: () => void - clearBtnEnabled: boolean - setClearBtnEnabled: React.Dispatch - columns: ColumnList +// Used by exporting.ts after filtering out export-excluded columns. +export type ExportableColumn = LangColumn & { + accessorKey: keyof InstanceLevelSchema + header: string | React.ReactElement } -export type FilterComponentProps = { - item: GridFilterItem - applyValue: (item: GridFilterItem) => void -} +export type CountryCodes = { [key: string]: string } +export type ResultsTableProps = { data: InstanceLevelSchema[] } export type UseLocation = { state: null | { @@ -40,6 +40,31 @@ export type UseLocation = { pathname: string } +export type LangCellContext = CellContext +export type LangRow = Row +export type LangFilterFn = FilterFn + +export type ColumnToggle = { + id: string + label: string + isVisible: boolean + canHide: boolean + toggle: () => void +} + +export type ResultsToolbarProps = { + scrollToTop: () => void + clearBtnEnabled: boolean + setClearBtnEnabled: React.Dispatch + visibleRows: InstanceLevelSchema[] + globalFilter: string + setGlobalFilter: (v: string) => void + resetFilters: () => void + rowCount: number + columns: ColumnList + columnToggles: ColumnToggle[] +} + export type CountryListItemWithFlagProps = { name: string url: string @@ -66,5 +91,3 @@ export type CellProps = { export type MediaColumnCellProps = CellProps & { columnName: keyof InstanceLevelSchema } - -export type LangCellParams = GridRenderCellParams diff --git a/src/components/results/utils.tsx b/src/components/results/utils.tsx index c902cccf..4ea29236 100644 --- a/src/components/results/utils.tsx +++ b/src/components/results/utils.tsx @@ -6,14 +6,14 @@ import { FaMapMarkedAlt } from 'react-icons/fa' import { InstanceLevelSchema, InternalWithLang } from 'components/context/types' import { CountryListItemWithFlag } from './CountryListItemWithFlag' import { EndoImageModal } from './EndoImageModal' -import { LangCellParams } from './types' +import { LangCellContext } from './types' export const FILTER_CLASS = 'for-filter' export function renderCountryColumn( - params: LangCellParams + info: LangCellContext ): string | React.ReactNode { - const data = params.row + const data = info.row.original return (
    @@ -30,9 +30,9 @@ export function renderCountryColumn( } export function renderEndoColumn( - params: LangCellParams + info: LangCellContext ): string | React.ReactNode { - const data = params.row + const data = info.row.original if (!data['Font Image Alt']) { return data.Endonym diff --git a/yarn.lock b/yarn.lock index 21f6981c..99d686e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -178,7 +178,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.9", "@babel/runtime@^7.7.6": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.18.3", "@babel/runtime@^7.23.9", "@babel/runtime@^7.7.6": version "7.29.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.29.2.tgz#9a6e2d05f4b6692e1801cd4fb176ad823930ed5e" integrity sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g== @@ -815,7 +815,7 @@ resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.24.tgz#5eff63129d9c29d80bbf2d2e561bd0690314dec2" integrity sha512-3c8tRt/CbWZ+pEg7QpSwbdxOk36EfmhbKf6AGZsD1EcLDLTSZoxxJ86FVtcjxvjuhdyBiWKSTGZFaXCnidO2kw== -"@mui/utils@^5.14.16", "@mui/utils@^5.17.1": +"@mui/utils@^5.17.1": version "5.17.1" resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-5.17.1.tgz#72ba4ffa79f7bdf69d67458139390f18484b6e6b" integrity sha512-jEZ8FTqInt2WzxDV8bhImWBqeQRD99c/id/fq83H0ER9tFl+sfZlaAoCdznGvbSQQ9ividMxqSV2c7cC1vBcQg== @@ -827,17 +827,6 @@ prop-types "^15.8.1" react-is "^19.0.0" -"@mui/x-data-grid@^6": - version "6.20.4" - resolved "https://registry.yarnpkg.com/@mui/x-data-grid/-/x-data-grid-6.20.4.tgz#51120757078764dc8cccef50bc1257c2407e103d" - integrity sha512-I0JhinVV4e25hD2dB+R6biPBtpGeFrXf8RwlMPQbr9gUggPmPmNtWKo8Kk2PtBBMlGtdMAgHWe7PqhmucUxU1w== - dependencies: - "@babel/runtime" "^7.23.2" - "@mui/utils" "^5.14.16" - clsx "^2.0.0" - prop-types "^15.8.1" - reselect "^4.1.8" - "@popperjs/core@^2.11.8": version "2.11.8" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f" @@ -1141,6 +1130,18 @@ "@svgr/hast-util-to-babel-ast" "8.0.0" svg-parser "^2.0.4" +"@tanstack/react-table@^8.21.3": + version "8.21.3" + resolved "https://registry.yarnpkg.com/@tanstack/react-table/-/react-table-8.21.3.tgz#2c38c747a5731c1a07174fda764b9c2b1fb5e91b" + integrity sha512-5nNMTSETP4ykGegmVkhjcS8tTLW6Vl4axfEGQN3v0zdHYbK4UfoqfPChclTrJ4EoK9QynqAu9oUf8VEmrpZ5Ww== + dependencies: + "@tanstack/table-core" "8.21.3" + +"@tanstack/table-core@8.21.3": + version "8.21.3" + resolved "https://registry.yarnpkg.com/@tanstack/table-core/-/table-core-8.21.3.tgz#2977727d8fc8dfa079112d9f4d4c019110f1732c" + integrity sha512-ldZXEhOBb8Is7xLs01fR3YEc3DERiz5silj8tnGkFZytt1abEvl/GhUmCE0PMLaMPTa3Jk4HbKmRlHmu+gCftg== + "@testing-library/dom@^7.22.3": version "7.26.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.26.0.tgz#da4d052dc426a4ccc916303369c6e7552126f680" @@ -2144,7 +2145,7 @@ clsx@^1.1.1: resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== -clsx@^2.0.0, clsx@^2.1.0, clsx@^2.1.1: +clsx@^2.1.0, clsx@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== @@ -5879,11 +5880,6 @@ require-relative@^0.8.7: resolved "https://registry.yarnpkg.com/require-relative/-/require-relative-0.8.7.tgz#7999539fc9e047a37928fa196f8e1563dabd36de" integrity sha1-eZlTn8ngR6N5KPoZb44VY9q9Nt4= -reselect@^4.1.8: - version "4.1.8" - resolved "https://registry.yarnpkg.com/reselect/-/reselect-4.1.8.tgz#3f5dc671ea168dccdeb3e141236f69f02eaec524" - integrity sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" From 37084e75d474e73c0b911e963257aa699ed41343 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:51:53 -0400 Subject: [PATCH 09/11] Coerce undefined cell values to empty strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit React throws when a function passed to flexRender returns undefined. Several columns (Glottocode, ISO 639-3, Additional Neighborhoods, Endonym, etc.) are nullable in the dataset, and their default cell renderers were `info.getValue()` — which returns undefined for any row where the field is missing. Coerce all simple-text cells with ?? '' and add a guard in renderCountryColumn / renderEndoColumn for rows without those fields. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/results/config.tsx | 12 ++++++------ src/components/results/utils.tsx | 6 ++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/results/config.tsx b/src/components/results/config.tsx index eda15356..b76c8f27 100644 --- a/src/components/results/config.tsx +++ b/src/components/results/config.tsx @@ -68,7 +68,7 @@ export const columns: Types.ColumnList = [ }), ch.accessor('Language', { header: 'Language', - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'Language' }, }), ch.accessor('Endonym', { @@ -99,7 +99,7 @@ export const columns: Types.ColumnList = [ }), ch.accessor('Language Family', { header: 'Language Family', - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'Language Family' }, }), ch.accessor('Video', { @@ -118,7 +118,7 @@ export const columns: Types.ColumnList = [ }), ch.accessor('Primary Location', { header: () => , - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'Location' }, }), ch.accessor('Size', { @@ -141,17 +141,17 @@ export const columns: Types.ColumnList = [ }), ch.accessor('Glottocode', { header: 'Glottocode', - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'Glottocode' }, }), ch.accessor('ISO 639-3', { header: 'ISO 639-3', - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'ISO 639-3' }, }), ch.accessor('Additional Neighborhoods', { header: 'Additional Neighborhoods', - cell: (info) => info.getValue(), + cell: (info) => (info.getValue() as React.ReactNode) ?? '', meta: { exportTitle: 'Additional Neighborhoods' }, }), ] diff --git a/src/components/results/utils.tsx b/src/components/results/utils.tsx index 4ea29236..68000cef 100644 --- a/src/components/results/utils.tsx +++ b/src/components/results/utils.tsx @@ -15,13 +15,15 @@ export function renderCountryColumn( ): string | React.ReactNode { const data = info.row.original + if (!Array.isArray(data.Country) || data.Country.length === 0) return '' + return (
      {data.Country.map((countryWithFlag, i) => ( ))} @@ -35,7 +37,7 @@ export function renderEndoColumn( const data = info.row.original if (!data['Font Image Alt']) { - return data.Endonym + return data.Endonym ?? '' } return ( From 51fe9af3a9dd836cee10ab9f6f6a2a823fb0edc6 Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:52:14 -0400 Subject: [PATCH 10/11] Drop the redundant "Has" label next to Audio/Video filter checkboxes The column header already says "Audio" / "Video"; the checkbox in the filter row beneath it is unambiguous. Replace the labelled FormControlLabel with a bare Checkbox and put the explanatory text in the title attribute for hover discoverability. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/results/MediaColumnFilter.tsx | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/components/results/MediaColumnFilter.tsx b/src/components/results/MediaColumnFilter.tsx index 81330a7d..930e1260 100644 --- a/src/components/results/MediaColumnFilter.tsx +++ b/src/components/results/MediaColumnFilter.tsx @@ -1,5 +1,5 @@ import React, { FC } from 'react' -import { Checkbox, FormControlLabel } from '@mui/material' +import { Checkbox } from '@mui/material' import { Column } from '@tanstack/react-table' import { InstanceLevelSchema } from 'components/context/types' @@ -29,17 +29,13 @@ export const MediaColumnFilter: FC<{ const checked = (column.getFilterValue() as boolean) || false return ( - column.setFilterValue(e.target.checked || undefined)} - /> - } - label="Has" + column.setFilterValue(e.target.checked || undefined)} + sx={{ padding: 0.5 }} /> ) } From 1c98abb54e719f80faaec3663097292bdffd83ae Mon Sep 17 00:00:00 2001 From: Ankit Gupta Date: Mon, 27 Apr 2026 21:56:43 -0400 Subject: [PATCH 11/11] Exclude hidden columns from CSV/PDF exports The toolbar was passing the static column config to exportCsv/exportPdf regardless of which columns the user had hidden via the column visibility menu. Filter the config by columnVisibility before handing it to the export utilities so a downloaded CSV/PDF reflects exactly what's on screen. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/components/results/ResultsTable.tsx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/components/results/ResultsTable.tsx b/src/components/results/ResultsTable.tsx index b1f465d4..4a27df0d 100644 --- a/src/components/results/ResultsTable.tsx +++ b/src/components/results/ResultsTable.tsx @@ -160,6 +160,15 @@ export const ResultsTable: FC = (props) => { .getFilteredRowModel() .rows.map((r) => r.original) + // Static config filtered down to only currently-visible columns. Used for + // CSV/PDF export so hidden columns don't leak into downloads. + const visibleColumnConfig = columns.filter( + (col) => + columnVisibility[ + (col.id ?? (col as { accessorKey?: string }).accessorKey) as string + ] !== false + ) + const resetFilters = () => { setGlobalFilter('') setColumnFilters([]) @@ -203,7 +212,7 @@ export const ResultsTable: FC = (props) => { setGlobalFilter={setGlobalFilter} resetFilters={resetFilters} rowCount={table.getFilteredRowModel().rows.length} - columns={columns} + columns={visibleColumnConfig} columnToggles={table.getAllLeafColumns().map((column) => { const headerDef = column.columnDef.header const label = typeof headerDef === 'string' ? headerDef : column.id