@mui/material#useMediaQuery TypeScript Examples
The following examples show how to use
@mui/material#useMediaQuery.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useMobile.tsx From frontend with MIT License | 6 votes |
export default function useMobile() {
const mobile = useMediaQuery('(max-width:900px)')
const small = useMediaQuery('(max-width:600px)')
return {
mobile,
small,
}
}
Example #2
Source File: useSidebar.ts From usehooks-ts with MIT License | 6 votes |
function useSidebar(): ReturnType {
const { breakpoints } = useTheme()
const isMobile = useMediaQuery(breakpoints.down('lg'))
const [isOpen, setOpen] = useState(false)
const closeSidebar = () => {
if (isMobile) {
setOpen(false)
}
}
const openSidebar = () => setOpen(true)
useEffect(() => {
// Hide sidebar by default on small screen
if (isMobile && isOpen) {
closeSidebar()
}
// Show sidebar by default on large screen
if (!isMobile && !isOpen) {
openSidebar()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isMobile])
return [
isOpen,
{
openSidebar,
closeSidebar,
},
]
}
Example #3
Source File: ModeState.tsx From firecms with MIT License | 6 votes |
ModeProvider: React.FC<ModeProviderProps> = ({ children }) => {
const prefersDarkModeQuery = useMediaQuery("(prefers-color-scheme: dark)");
const prefersDarkModeStorage: boolean | null = localStorage.getItem("prefers-dark-mode") != null ? localStorage.getItem("prefers-dark-mode") === "true" : null;
const prefersDarkMode = prefersDarkModeStorage ?? prefersDarkModeQuery;
const [mode, setMode] = useState<"light" | "dark">(prefersDarkMode ? "dark" : "light");
useEffect(() => {
setMode(prefersDarkMode ? "dark" : "light");
}, [prefersDarkMode]);
const toggleMode = () => {
if (mode === "light") {
if (!prefersDarkModeQuery)
localStorage.setItem("prefers-dark-mode", "true");
else
localStorage.removeItem("prefers-dark-mode");
setMode("dark");
} else {
if (prefersDarkModeQuery)
localStorage.setItem("prefers-dark-mode", "false");
else
localStorage.removeItem("prefers-dark-mode");
setMode("light");
}
};
return (
<ModeStateContext.Provider
value={{
mode,
setMode,
toggleMode
}}
>
{children}
</ModeStateContext.Provider>
);
}
Example #4
Source File: Header.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
export default function Header({ left, title, subtitle, hideInterval }: HeaderProps) {
const dispatch = useAppDispatch();
const intervalDetail = useSelector(selectIntervalDetail);
const showSider = !useMediaQuery('(max-width: 900px)');
const changeInterval = useCallback(
(newInterval: IntervalDetail) => {
dispatch(setDataInterval(intervalDetailToRedux(newInterval)));
},
[dispatch],
);
return (
<div className={s.root}>
<div className={s.left}>
{left}
<div className={s.texts}>
<Text element="h1">{title}</Text>
{showSider && <Text>{subtitle}</Text>}
</div>
</div>
{!hideInterval && (
<div>
<IntervalSelector value={intervalDetail} onChange={changeInterval} />
</div>
)}
</div>
);
}
Example #5
Source File: App.tsx From NekoMaid with MIT License | 6 votes |
AppWrap: React.FC = () => {
const isDark = useMediaQuery('(prefers-color-scheme: dark)')
const mode = localStorage.getItem('NekoMaid:colorMode')
const [darkMode, setDarkMode] = useState(mode ? mode === 'dark' : isDark)
const primary = (colors as any)[localStorage.getItem('NekoMaid:color') || 'blue']
;(document.getElementById('theme-color-meta') as HTMLMetaElement)?.setAttribute('content', primary[500])
const theme = React.useMemo(() => createTheme({
typography,
components: {
MuiCssBaseline: {
styleOverrides: {
body: darkMode ? darkScrollbar() : null
}
}
},
palette: {
primary,
mode: darkMode ? 'dark' : 'light',
background: darkMode ? { default: '#212121', paper: '#212121' } : { default: '#f4f6f8', paper: '#ffffff' }
}
}, (muiLanguages as any)[lang.muiName]), [darkMode])
return <ThemeProvider theme={theme}>
<DialogWrapper />
<Snackbars />
<App darkMode={darkMode} setDarkMode={setDarkMode} />
</ThemeProvider>
}
Example #6
Source File: useMediaQueryUp.tsx From genshin-optimizer with MIT License | 6 votes |
export default function useMediaQueryUp() {
const theme = useTheme();
const sm = useMediaQuery(theme.breakpoints.up('sm'));
const md = useMediaQuery(theme.breakpoints.up('md'));
const lg = useMediaQuery(theme.breakpoints.up('lg'));
const xl = useMediaQuery(theme.breakpoints.up('xl'));
if (xl) return "xl"
if (lg) return "lg"
if (md) return "md"
if (sm) return "sm"
return "xs"
}
Example #7
Source File: Theme.tsx From GTAV-NativeDB with MIT License | 6 votes |
function Theme({ children }: { children: ReactNode }) {
const settings = useSettings()
const systemIsDark = useMediaQuery('(prefers-color-scheme: dark)')
const dark = settings.theme === 'dark' || (settings.theme === 'system' && systemIsDark)
const theme = useMemo(
() => createTheme(dark ? darkTheme : lightTheme),
[dark]
)
useEffect(() => {
document.querySelector('meta[name="theme-color"]')
?.setAttribute('content', dark ? '#272727' :'#0e752e')
}, [dark])
return (
<ThemeProvider theme={theme}>
{children}
</ThemeProvider>
)
}
Example #8
Source File: layout.tsx From usehooks-ts with MIT License | 6 votes |
Layout: FC = ({ children }) => {
const { title } = useSiteMetadata()
const [isSidebarOpen, { openSidebar, closeSidebar }] = useSidebar()
const [isModalOpen, { openModal, closeModal }] = useSearchModal()
const theme = useTheme()
const isLarge = useMediaQuery(theme.breakpoints.up('md'))
return (
<Root>
<CustomScrollbar theme={theme} />
<Header
siteTitle={title}
openSidebar={openSidebar}
openSearch={openModal}
/>
<Sidebar open={isSidebarOpen} onClose={closeSidebar} />
<Main
sx={{ paddingLeft: isLarge && isSidebarOpen ? `${drawerWidth}px` : 0 }}
>
{children}
<Footer />
</Main>
<SearchModal open={isModalOpen} onClose={closeModal} />
<BackToTop />
</Root>
)
}
Example #9
Source File: EmptyView.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 6 votes |
export default function EmptyView({ message, messageExtra }: IProps) {
const theme = useTheme();
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
return (
<Box sx={{
position: 'absolute',
left: `calc(50% + ${isMobileWidth ? '0px' : theme.spacing(8 / 2)})`,
top: '50%',
transform: 'translate(-50%, -50%)',
textAlign: 'center',
}}
>
<Typography variant="h3" gutterBottom>
{getRandomErrorFace()}
</Typography>
<Typography variant="h5">
{message}
</Typography>
{messageExtra}
</Box>
);
}
Example #10
Source File: Layout.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
export default function Layout({ children }: LayoutProps) {
const [open, setOpen] = useState(false);
const showSider = !useMediaQuery('(max-width: 900px)');
const publicToken = useSelector(selectPublicToken);
const drawer = useCallback(() => {
setOpen((old) => !old);
}, []);
return (
<div className={s.root}>
{!showSider && (
<Drawer open={open} anchor="left" onClose={() => setOpen(false)}>
<Sider />
</Drawer>
)}
<section className={s.sider}>{showSider && <Sider />}</section>
<section
className={clsx({
[s.content]: true,
[s.contentdrawer]: showSider,
})}>
{publicToken && (
<div className={s.publictoken}>
<Text>You are viewing as guest</Text>
</div>
)}
{!showSider && (
<IconButton onClick={drawer} className={s.drawerbutton}>
<Menu />
</IconButton>
)}
{children}
</section>
</div>
);
}
Example #11
Source File: Footer.tsx From frontend with MIT License | 6 votes |
SocialIcons = () => {
const theme = useTheme()
const sm = useMediaQuery(theme.breakpoints.up('sm'))
return (
<Grid direction="row" container spacing={2} justifyContent={sm ? 'flex-start' : 'center'}>
<Grid item>
<ExternalLink href={socialUrls.facebook}>
<Facebook />
</ExternalLink>
</Grid>
<Grid item>
<ExternalLink href={socialUrls.linkedin}>
<LinkedIn />
</ExternalLink>
</Grid>
<Grid item>
<ExternalLink href={socialUrls.youtube}>
<YouTube />
</ExternalLink>
</Grid>
<Grid item>
<ExternalLink href={socialUrls.instagram}>
<Instagram />
</ExternalLink>
</Grid>
</Grid>
)
}
Example #12
Source File: Artist.tsx From your_spotify with GNU General Public License v3.0 | 6 votes |
export default function Artist(props: ArtistProps | HeaderArtistProps) {
const upmd = useMediaQuery('(min-width: 1150px)');
const upmobile = useMediaQuery('(min-width: 600px)');
if (props.line) {
return (
<div className={s.root}>
<Text className={s.artistname}>Artist name</Text>
{upmobile && <Text className={clsx(s.genres, s.header)}>Genres</Text>}
<Text className={clsx(s.sumcount, s.header)}>Count</Text>
<Text className={clsx(s.sumduration, s.header)}>Total duration</Text>
</div>
);
}
const { artist, duration, totalDuration, count, totalCount } = props;
return (
<div className={s.root}>
<img className={s.artistcover} src={getImage(artist)} alt="Artist cover" />
<Text className={s.artistname}>
<InlineArtist artist={artist} />
</Text>
{upmobile && <Text className={s.genres}>{artist.genres.join(', ')}</Text>}
<Text className={s.sumcount}>
{count} {upmd && <Text>({Math.floor((count / totalCount) * 10000) / 100})</Text>}
</Text>
<Text className={s.sumduration}>
{msToMinutesAndSeconds(duration)}{' '}
{upmd && <Text>({Math.floor((duration / totalDuration) * 10000) / 100})</Text>}
</Text>
</div>
);
}
Example #13
Source File: layout.tsx From usehooks-ts with MIT License | 6 votes |
TopLayout: FC = ({ children }) => {
const matches = useMediaQuery('(prefers-color-scheme: dark)')
const theme = themes[matches ? 'dark' : 'light']
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Layout>{children}</Layout>
</ThemeProvider>
)
}
Example #14
Source File: Track.tsx From your_spotify with GNU General Public License v3.0 | 5 votes |
export default function Track(props: TrackProps | HeaderTrackProps) {
const trackId = props.line ? null : props.track.id;
const play = useCallback(async () => {
if (!trackId) return;
try {
await api.play(trackId);
} catch (e) {
console.error(e);
}
}, [trackId]);
const upmd = useMediaQuery('(min-width: 1150px)');
if (props.line) {
return (
<div className={s.root}>
<div className={clsx(s.name, s.header)}>
<Text className={s.trackname}>Track name / Artist</Text>
</div>
{upmd && <Text className={clsx(s.albumname, s.header)}>Album name</Text>}
{upmd && <Text className={clsx(s.duration, s.header)}>Duration</Text>}
<Text className={clsx(s.sumcount, s.header)}>Count</Text>
<Text className={clsx(s.sumduration, s.header)}>Total duration</Text>
</div>
);
}
const { track, album, artists, playable, duration, totalDuration, count, totalCount } = props;
return (
<div className={s.root}>
{playable && (
<IconButton className={s.play} size="small" onClick={play}>
<PlayArrow />
</IconButton>
)}
<img className={s.albumcover} src={getImage(album)} alt="Album cover" />
<div className={s.name}>
<Text className={s.trackname}>{track.name}</Text>
<Text className={s.artistname}>
{artists.map((art) => (
<React.Fragment key={art.id}>
<InlineArtist key={art.id} artist={art} />{' '}
</React.Fragment>
))}
</Text>
</div>
{upmd && <Text className={s.albumname}>{album.name}</Text>}
{upmd && <Text className={s.duration}>{msToMinutesAndSeconds(track.duration_ms)}</Text>}
<Text className={s.sumcount}>
{count} {upmd && <Text>({Math.floor((count / totalCount) * 10000) / 100})</Text>}
</Text>
<Text className={s.sumduration}>
{msToMinutesAndSeconds(duration)}{' '}
{upmd && <Text>({Math.floor((duration / totalDuration) * 10000) / 100})</Text>}
</Text>
</div>
);
}
Example #15
Source File: DefaultNavBar.tsx From Tachidesk-WebUI with Mozilla Public License 2.0 | 5 votes |
export default function DefaultNavBar() {
const { title, action, override } = useContext(NavBarContext);
const { darkTheme } = useContext(DarkTheme);
const theme = useTheme();
const history = useHistory();
const isMobileWidth = useMediaQuery(theme.breakpoints.down('sm'));
const isMainRoute = navbarItems.some(({ path }) => path === history.location.pathname);
// Allow default navbar to be overrided
if (override.status) return override.value;
let navbar = <></>;
if (isMobileWidth) {
if (isMainRoute) {
navbar = <MobileBottomBar navBarItems={navbarItems.filter((it) => it.show !== 'desktop')} />;
}
} else {
navbar = <DesktopSideBar navBarItems={navbarItems.filter((it) => it.show !== 'mobile')} />;
}
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="fixed" color={darkTheme ? 'default' : 'primary'}>
<Toolbar>
{
!navbarItems.some(({ path }) => path === history.location.pathname)
&& (
<IconButton
edge="start"
sx={{ marginRight: theme.spacing(2) }}
color="inherit"
aria-label="menu"
disableRipple
// when page is opened in new tab backbutton will
// take you to the library
onClick={() => (history.length === 1 ? history.push('/library') : history.goBack())}
size="large"
>
<ArrowBack />
</IconButton>
)
}
<Typography variant={isMobileWidth ? 'h6' : 'h5'} sx={{ flexGrow: 1 }}>
{title}
</Typography>
{action}
</Toolbar>
</AppBar>
{navbar}
</Box>
);
}
Example #16
Source File: theme.ts From your_spotify with GNU General Public License v3.0 | 5 votes |
useTheme = () => {
const dark = useSelector(selectDarkMode);
const prefersDarkMode = useMediaQuery('(prefers-color-scheme: dark)');
const isDark = dark === 'dark' || (dark === 'follow' && prefersDarkMode);
const theme = useMemo(
() =>
createTheme({
palette: {
mode: isDark ? 'dark' : 'light',
primary: {
main: isDark ? '#ffffff' : '#000000',
},
},
components: {
MuiPaper: {
styleOverrides: {
root: {
backgroundImage: 'unset',
},
},
},
MuiCheckbox: {
styleOverrides: {
root: {
color: 'var(--primary) !important',
},
},
},
MuiSkeleton: {
styleOverrides: {
rectangular: {
borderRadius: '6px',
},
},
},
},
shape: {
borderRadius: 6,
},
}),
[isDark],
);
return theme;
}
Example #17
Source File: AppTheme.tsx From airmessage-web with Apache License 2.0 | 5 votes |
export default function AppTheme(props: {children: React.ReactNode}) {
const prefersDarkMode = useMediaQuery("(prefers-color-scheme: dark)");
const theme = React.useMemo(() => createTheme({
typography: {
fontFamily: [
"-apple-system",
"BlinkMacSystemFont",
'"Segoe UI"',
"Roboto",
'"Helvetica Neue"',
"Arial",
"sans-serif",
'"Apple Color Emoji"',
'"Segoe UI Emoji"',
'"Segoe UI Symbol"',
].join(","),
},
palette: {
mode: prefersDarkMode ? "dark" : "light",
primary: {
main: "#448AFF",
dark: "#366FCC",
light: "#52A7FF",
},
messageIncoming: prefersDarkMode ? {
main: "#393939",
contrastText: "#FFF"
} : {
main: "#EDEDED",
contrastText: "rgba(0, 0, 0, 0.87)"
},
messageOutgoing: {
main: "#448AFF",
contrastText: "#FFF",
},
messageOutgoingTextMessage: {
main: "#2ECC71",
contrastText: "#FFF",
},
divider: prefersDarkMode ? "rgba(255, 255, 255, 0.1)" : "#EEEEEE",
background: {
default: prefersDarkMode ? "#1E1E1E" : "#FFFFFF",
sidebar: prefersDarkMode ? "#272727" : "#FAFAFA"
}
},
components: {
MuiCssBaseline: {
styleOverrides: {
"@global": {
html: {
scrollbarColor: prefersDarkMode ? "#303030 #424242" : undefined
}
}
}
}
}
}), [prefersDarkMode]);
return (
<ThemeProvider theme={theme}>
<CssBaseline />
{props.children}
</ThemeProvider>
);
}
Example #18
Source File: ItemViewer.tsx From NekoMaid with MIT License | 5 votes |
GlobalItems: React.FC<{ open: boolean, onClose: () => void }> = ({ open, onClose }) => {
const matches = useMediaQuery((theme: any) => theme.breakpoints.down('md'))
const [flag, update] = useState(0)
const [copyItemLeft, setCopyItemLeft] = useState<Item | undefined>()
const [copyItemRight, setCopyItemRight] = useState<Item | undefined>()
const items: Array<Item | undefined> = JSON.parse(localStorage.getItem('NekoMaid:items') || '[]')
const save = () => {
localStorage.setItem('NekoMaid:items', JSON.stringify(items))
process.nextTick(update, flag + 1)
}
return <Drawer anchor='bottom' variant='persistent' elevation={16} open={open} PaperProps={{ elevation: 16 }}>
<Box sx={{ padding: 2, display: 'flex', justifyContent: 'center', paddingBottom: 0, alignItems: 'center' }}>
<ItemViewer
item={copyItemLeft}
data={{ type: InvType.GLOBAL_ITEMS }}
onDrag={() => process.nextTick(setCopyItemLeft)}
onDrop={it => {
setCopyItemLeft(it)
setCopyItemRight(it)
}}
/> {`< ${lang.itemEditor.clone} >`} <ItemViewer
item={copyItemRight}
data={{ type: InvType.GLOBAL_ITEMS }}
onDrag={() => process.nextTick(setCopyItemRight)}
onDrop={it => {
setCopyItemLeft(it)
setCopyItemRight(it)
}}
/>
</Box>
<Box sx={{ padding: 2, display: 'flex', justifyContent: 'center', flexWrap: 'wrap' }}>
{Array.from({ length: 14 }, (_, i) => <ItemViewer
key={i}
item={items[i]}
data={{ type: InvType.GLOBAL_ITEMS }}
onDrag={() => {
items[i] = undefined
save()
if (matches) process.nextTick(onClose)
}}
onDrop={it => {
items[i] = it
save()
}}
onEdit={item => {
if (item === false) return
items[i] = item || undefined
save()
}}
/>)}
</Box>
<ItemEditor />
</Drawer>
}
Example #19
Source File: Header.tsx From genshin-optimizer with MIT License | 5 votes |
function HeaderContent({ anchor }) {
const theme = useTheme();
const isLarge = useMediaQuery(theme.breakpoints.up('lg'));
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const { t } = useTranslation("ui")
const { params: { currentTab } } = useMatch({ path: "/:currentTab", end: false }) ?? { params: { currentTab: "" } };
if (isMobile) return <MobileHeader anchor={anchor} currentTab={currentTab} />
return <AppBar position="static" sx={{ bgcolor: "#343a40", display: "flex", flexWrap: "nowrap" }} elevation={0} id={anchor} >
<Tabs
value={currentTab}
variant="scrollable"
scrollButtons="auto"
sx={{
"& .MuiTab-root": {
px: 1,
flexDirection: "row",
minWidth: 40,
minHeight: "auto",
},
"& .MuiTab-root:hover": {
transition: "background-color 0.5s ease",
backgroundColor: "rgba(255,255,255,0.1)"
},
"& .MuiTab-root > .MuiTab-iconWrapper": {
mb: 0,
mr: 0.5
},
}}
>
<Tab value="" component={RouterLink} to="/" label={<Typography variant="h6" sx={{ px: 1 }}>
<Trans t={t} i18nKey="pageTitle">Genshin Optimizer</Trans>
</Typography>} />
{content.map(({ i18Key, value, to, svg }) => <Tab key={value} value={value} component={RouterLink} to={to} icon={<FontAwesomeIcon icon={svg} />} label={t(i18Key)} />)}
<Box flexGrow={1} />
{links.map(({ i18Key, href, label, svg }) => <Tab key={label} component="a" href={href} target="_blank" icon={<FontAwesomeIcon icon={svg} />} onClick={e => ReactGA.outboundLink({ label }, () => { })} label={isLarge && t(i18Key)} />)}
</Tabs>
</AppBar>
}
Example #20
Source File: OneTimeDonationPage.tsx From frontend with MIT License | 5 votes |
export default function OneTimeDonation({ slug }: { slug: string }) {
const { data } = useViewCampaign(slug)
if (!data || !data.campaign) return <NotFoundPage />
const { campaign } = data
const matches = useMediaQuery('sm')
const bannerSource = backgroundCampaignPictureUrl(campaign)
const beneficiaryAvatarSource = beneficiaryCampaignPictureUrl(campaign)
return (
<StyledLayout maxWidth={false}>
<Grid
container
component="section"
maxWidth="lg"
justifyContent="center"
m="0 auto"
marginTop={theme.spacing(matches ? 20 : 25)}>
<Box className={classes.bannerWrapper}>
<Image
src={bannerSource}
alt="Campaign banner image"
layout="fill"
objectFit="cover"
className={classes.banner}
/>
</Box>
<Grid
item
xs={12}
justifyContent="center"
p={4}
className={classes.beneficiaryAvatarWrapper}>
<Image
src={beneficiaryAvatarSource}
alt={campaign.title}
width={250}
height={250}
className={classes.beneficiaryAvatar}
/>
</Grid>
<Grid className={classes.stepperWrapper}>
<Typography variant="h4" sx={{ textAlign: 'center', marginBottom: theme.spacing(4) }}>
{campaign.title}
</Typography>
<DonationStepper />
</Grid>
</Grid>
</StyledLayout>
)
}
Example #21
Source File: App.tsx From abrechnung with GNU Affero General Public License v3.0 | 5 votes |
export default function App() {
const darkModeSystem = useMediaQuery("(prefers-color-scheme: dark)");
const userThemeSettings = useRecoilValue(themeSettings);
const useDarkMode: PaletteMode =
userThemeSettings.darkMode === "browser" ? (darkModeSystem ? "dark" : "light") : userThemeSettings.darkMode;
const theme = useMemo(
() =>
createTheme({
palette: {
mode: useDarkMode,
},
}),
[useDarkMode]
);
return (
<StyledEngineProvider injectFirst>
<ThemeProvider theme={theme}>
<CssBaseline />
<LocalizationProvider dateAdapter={DateAdapter}>
<ToastContainer
position="top-right"
autoClose={5000}
hideProgressBar={false}
newestOnTop={false}
closeOnClick
rtl={false}
pauseOnFocusLoss
draggable
pauseOnHover
/>
<Router>
<Switch>
{routes.map((route) => {
const authRoute = route.auth ? (
<AuthenticatedRoute>{route.component}</AuthenticatedRoute>
) : (
route.component
);
const layoutRoute =
route.layout === undefined || route.layout ? (
<Layout>
<Suspense fallback={<Loading />}>{authRoute}</Suspense>
</Layout>
) : (
<Suspense fallback={<Loading />}>{authRoute}</Suspense>
);
return (
<Route
key={route.path}
exact={route.exact !== undefined && route.exact}
path={route.path}
>
{layoutRoute}
</Route>
);
})}
</Switch>
</Router>
</LocalizationProvider>
</ThemeProvider>
</StyledEngineProvider>
);
}
Example #22
Source File: add-button.tsx From tams-club-cal with MIT License | 5 votes |
AddButton = (props: AddButtonProps) => {
const router = useRouter();
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down('md'));
const redirectTo = () => {
router.push(props.path || '#');
};
// Change position of button to the left side if it's the edit history button
const leftOrRight = props.editHistory ? { left: { lg: 32, xs: 12 } } : { right: { lg: 32, xs: 12 } };
return (
<Tooltip
title={
props.editHistory ? 'Show Edit History' : `${props.edit ? 'Edit' : 'Add'} ${props.label || 'resource'}`
}
>
<Fab
variant={props.editHistory ? 'extended' : 'circular'}
size={matches ? 'small' : 'large'}
color={props.editHistory ? 'primary' : props.color || 'default'}
aria-label={props.editHistory ? 'edit history' : props.edit ? 'edit' : 'add'}
onClick={redirectTo}
sx={{
display: 'flex',
margin: props.editHistory ? '12px auto' : 'auto',
position: 'fixed',
bottom: { lg: 32, xs: 12 },
zIndex: (theme) => theme.zIndex.appBar + 1,
color: (theme) => theme.palette.common.white,
...leftOrRight,
}}
>
{props.editHistory ? (
<AccessTimeRoundedIcon sx={{ marginRight: 1 }} width="16" />
) : props.edit ? (
<EditIcon width="16" />
) : (
<AddIcon htmlColor="white" width="16" />
)}
{props.editHistory ? 'Show Edit History' : null}
</Fab>
</Tooltip>
);
}
Example #23
Source File: useIsSmallDisplay.ts From GTAV-NativeDB with MIT License | 5 votes |
export default function useIsSmallDisplay() {
const theme = useTheme()
return useMediaQuery(theme.breakpoints.down('md'))
}
Example #24
Source File: ProductCard.tsx From Cromwell with MIT License | 5 votes |
ProductCard = (props?: ProductCardProps & {
className?: string;
}) => {
const { product } = props ?? {};
const router = useRouter();
const isMobile = useMediaQuery<Theme>((theme) => theme.breakpoints.down('sm'));
const variant = (props?.variant === 'horizontal' && !isMobile) ? 'horizontal' : 'vertical';
const handleOpenQuickView = () => {
if (!product?.id) return;
appState.isQuickViewOpen = true;
appState.quickViewProductId = product?.id;
}
if (!product) return null;
return (
<MuiProductCard
product={product}
attributes={props?.attributes}
classes={{
root: clsx(props?.className, commonStyles.onHoverLinkContainer, styles.Product),
title: commonStyles.onHoverLink,
}}
onOpenCart={() => appState.isCartOpen = true}
onOpenWishlist={() => appState.isWishlistOpen = true}
noImagePlaceholderUrl={'/themes/@cromwell/theme-store/no-photos.png'}
variant={variant}
onFailedAddToCart={(item, result) => {
if (result.code === 4) {
handleOpenQuickView();
}
}}
elements={{
OtherActions: () => {
return (
<Tooltip title="Quick view">
<IconButton
aria-label="Open product in quick view"
className={styles.actionBtn}
onClick={handleOpenQuickView}>
<SearchIcon />
</IconButton>
</Tooltip>
)
},
}}
onProductLinkClick={(event, link) => router?.push(link)}
imageProps={{ unoptimized: true }}
/>
);
}
Example #25
Source File: SearchResultModule.tsx From ui-schema with MIT License | 5 votes |
SearchResultModule: React.FC<{
match: any
term: string | undefined
}> = (
{
match, term,
},
) => {
const {setOpen} = useSearch()
const {setOpen: setDrawerOpen} = useDrawer()
const {breakpoints} = useTheme()
const isMd = useMediaQuery(breakpoints.up('md'))
return <Box mb={1}>
<SearchLink
to={match.pagePath + '#doc-module--' + match.module}
onClick={() => {
setOpen(false)
if (!isMd) {
setDrawerOpen(false)
}
}}
// style={{textDecoration: 'none'}}
>
<Paper variant={'outlined'} style={{borderRadius: 5}}>
<Box p={1}>
<Typography>
<Highlighter
searchWords={term?.split(' ') || []}
textToHighlight={match.module}
autoEscape
highlightTag={SearchHighlight}
/>
</Typography>
<Box style={{display: 'flex'}}>
<Typography variant={'body2'}>{match.package}</Typography>
<Typography variant={'caption'} style={{marginLeft: 'auto', opacity: 0.6}}>Score: {match.score.toFixed(2)}</Typography>
</Box>
</Box>
</Paper>
</SearchLink>
</Box>
}
Example #26
Source File: DonationTab.tsx From frontend with MIT License | 4 votes |
export default function DonationTab() {
const router = useRouter()
const { t } = useTranslation()
const matches = useMediaQuery(theme.breakpoints.down('md'))
const { data: user } = getCurrentPerson(!!router.query?.register)
if (router.query?.register) {
delete router.query.register
router.replace({ pathname: router.pathname, query: router.query }, undefined, { shallow: true })
}
const { data: userDonations, isLoading: isUserDonationLoading } = useUserDonations()
const { data: campaigns, isLoading: isCampaignLoading } = useCampaignList()
return (
<StyledProfileTab name={ProfileTabs.donations}>
<Typography className={classes.h1}>{user?.user ? user.user.firstName + ',' : ''}</Typography>
<Typography variant="h5" fontWeight={'medium'}>
{t('profile:donations.helpThanks')} ❤️
</Typography>
<Grid
container
spacing={theme.spacing(2)}
marginTop={theme.spacing(1)}
alignItems={'flex-end'}>
<Grid order={matches ? 3 : 1} item xs={12} md={4}>
<Card>
{!isCampaignLoading && campaigns ? (
<CardActionArea>
<CardMedia
component="img"
height="193"
image={campaignListPictureUrl(campaigns[0])}
alt={campaigns[0].title}
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div">
{campaigns[0].title}
</Typography>
<Typography variant="body2" color="text.secondary">
{truncate(campaigns[0].description, { length: 120 })}
</Typography>
</CardContent>
</CardActionArea>
) : (
<CircularProgress />
)}
<CardActions>
<Button variant="contained" size="medium" color="secondary">
{t('profile:donations.donateNow')} ❤️
</Button>
</CardActions>
</Card>
</Grid>
<Grid order={matches ? 1 : 2} item xs={12} md={8}>
{!isUserDonationLoading && userDonations ? (
<Card className={classes.donationsBox}>
<Box className={classes.donationsBoxRow}>
<Typography fontWeight="medium" variant="h5">
{t('profile:donations.totalDonations')}
</Typography>
<Typography fontWeight="medium" variant="h5">
{money(userDonations.total)}
</Typography>
</Box>
<Box className={classes.donationsBoxRow}>
<Box>
<Typography variant="h5">{t('profile:donations.recurringDonations')}</Typography>
{/* TODO: Use date-fns to format and localize the months,
that the user has recurring donations when that is possible */}
{/* <Typography>Я, Ф, М, А 2022</Typography> */}
</Box>
<Typography fontWeight="medium" variant="h5">
{money(sumBy(userDonations.donations, 'amount'))}
</Typography>
</Box>
<Box className={classes.donationsBoxRow}>
<Typography variant="h5">{t('profile:donations.cardDonations')}</Typography>
<Typography fontWeight="medium" variant="h5">
{money(userDonations.total)}
</Typography>
</Box>
<Box className={classes.donationsBoxRow}>
<Typography variant="h5">{t('profile:donations.bankDonations')}</Typography>
<Typography fontWeight="medium" variant="h5">
{money(userDonations.total)}
</Typography>
</Box>
</Card>
) : (
<CircularProgress />
)}
</Grid>
<Grid order={matches ? 2 : 3} item xs={12}>
<DonationTable donations={userDonations?.donations} />
</Grid>
</Grid>
</StyledProfileTab>
)
}
Example #27
Source File: LinearGraphWidget.tsx From console with GNU Affero General Public License v3.0 | 4 votes |
LinearGraphWidget = ({
classes,
title,
timeStart,
timeEnd,
propLoading,
panelItem,
apiPrefix,
hideYAxis = false,
areaWidget = false,
yAxisFormatter = (item: string) => item,
xAxisFormatter = (item: string) => item,
zoomActivated = false,
}: ILinearGraphWidget) => {
const dispatch = useDispatch();
const [loading, setLoading] = useState<boolean>(true);
const [data, setData] = useState<object[]>([]);
const [dataMax, setDataMax] = useState<number>(0);
const [result, setResult] = useState<IDashboardPanel | null>(null);
useEffect(() => {
if (propLoading) {
setLoading(true);
}
}, [propLoading]);
useEffect(() => {
if (loading) {
let stepCalc = 0;
if (timeStart !== null && timeEnd !== null) {
const secondsInPeriod = timeEnd.unix() - timeStart.unix();
const periods = Math.floor(secondsInPeriod / 60);
stepCalc = periods < 1 ? 15 : periods;
}
api
.invoke(
"GET",
`/api/v1/${apiPrefix}/info/widgets/${
panelItem.id
}/?step=${stepCalc}&${
timeStart !== null ? `&start=${timeStart.unix()}` : ""
}${timeStart !== null && timeEnd !== null ? "&" : ""}${
timeEnd !== null ? `end=${timeEnd.unix()}` : ""
}`
)
.then((res: any) => {
const widgetsWithValue = widgetDetailsToPanel(res, panelItem);
setData(widgetsWithValue.data);
setResult(widgetsWithValue);
setLoading(false);
let maxVal = 0;
for (const dp of widgetsWithValue.data) {
for (const key in dp) {
if (key === "name") {
continue;
}
let val = parseInt(dp[key]);
if (isNaN(val)) {
val = 0;
}
if (maxVal < val) {
maxVal = val;
}
}
}
setDataMax(maxVal);
})
.catch((err: ErrorResponseHandler) => {
dispatch(setErrorSnackMessage(err));
setLoading(false);
});
}
}, [loading, panelItem, timeEnd, timeStart, dispatch, apiPrefix]);
let intervalCount = Math.floor(data.length / 5);
const linearConfiguration = result
? (result?.widgetConfiguration as ILinearGraphConfiguration[])
: [];
const CustomizedDot = (prop: any) => {
const { cx, cy, index } = prop;
if (index % 3 !== 0) {
return null;
}
return <circle cx={cx} cy={cy} r={3} strokeWidth={0} fill="#07264A" />;
};
const theme = useTheme();
const biggerThanMd = useMediaQuery(theme.breakpoints.up("md"));
return (
<Box className={zoomActivated ? "" : classes.singleValueContainer}>
{!zoomActivated && (
<div className={classes.titleContainer}>
{title} <ExpandGraphLink panelItem={panelItem} />
</div>
)}
<Box
sx={
zoomActivated
? { flexDirection: "column" }
: {
height: "100%",
display: "grid",
gridTemplateColumns: {
md: "1fr 1fr",
sm: "1fr",
},
}
}
style={areaWidget ? { gridTemplateColumns: "1fr" } : {}}
>
{loading && <Loader className={classes.loadingAlign} />}
{!loading && (
<React.Fragment>
<div
className={
zoomActivated ? classes.zoomChartCont : classes.chartCont
}
>
<ResponsiveContainer width="99%">
<AreaChart
data={data}
margin={{
top: 5,
right: 20,
left: hideYAxis ? 20 : 5,
bottom: 0,
}}
>
{areaWidget && (
<defs>
<linearGradient id="colorUv" x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor="#2781B0" stopOpacity={1} />
<stop
offset="100%"
stopColor="#ffffff"
stopOpacity={0}
/>
<stop
offset="95%"
stopColor="#ffffff"
stopOpacity={0.8}
/>
</linearGradient>
</defs>
)}
<CartesianGrid
strokeDasharray={areaWidget ? "2 2" : "5 5"}
strokeWidth={1}
strokeOpacity={1}
stroke={"#eee0e0"}
vertical={!areaWidget}
/>
<XAxis
dataKey="name"
tickFormatter={(value: any) => xAxisFormatter(value)}
interval={intervalCount}
tick={{
fontSize: "68%",
fontWeight: "normal",
color: "#404143",
}}
tickCount={10}
stroke={"#082045"}
/>
<YAxis
type={"number"}
domain={[0, dataMax * 1.1]}
hide={hideYAxis}
tickFormatter={(value: any) => yAxisFormatter(value)}
tick={{
fontSize: "68%",
fontWeight: "normal",
color: "#404143",
}}
stroke={"#082045"}
/>
{linearConfiguration.map((section, index) => {
return (
<Area
key={`area-${section.dataKey}-${index.toString()}`}
type="monotone"
dataKey={section.dataKey}
isAnimationActive={false}
stroke={!areaWidget ? section.lineColor : "#D7E5F8"}
fill={areaWidget ? "url(#colorUv)" : section.fillColor}
fillOpacity={areaWidget ? 0.65 : 0}
strokeWidth={!areaWidget ? 3 : 0}
strokeLinecap={"round"}
dot={areaWidget ? <CustomizedDot /> : false}
/>
);
})}
<Tooltip
content={
<LineChartTooltip
linearConfiguration={linearConfiguration}
yAxisFormatter={yAxisFormatter}
/>
}
wrapperStyle={{
zIndex: 5000,
}}
/>
</AreaChart>
</ResponsiveContainer>
</div>
{!areaWidget && (
<Fragment>
{zoomActivated && (
<Fragment>
<strong>Series</strong>
<br />
<br />
</Fragment>
)}
{biggerThanMd && (
<div className={classes.legendChart}>
{linearConfiguration.map((section, index) => {
return (
<div
className={classes.singleLegendContainer}
key={`legend-${section.keyLabel}-${index.toString()}`}
>
<div
className={classes.colorContainer}
style={{ backgroundColor: section.lineColor }}
/>
<div className={classes.legendLabel}>
{section.keyLabel}
</div>
</div>
);
})}
</div>
)}
</Fragment>
)}
</React.Fragment>
)}
</Box>
</Box>
);
}
Example #28
Source File: DocsDetails.tsx From ui-schema with MIT License | 4 votes |
DocContent: React.FC<{
content: string | undefined
id: string
progress: string
doc?: DocRouteModule
}> = ({content, id, progress, doc}) => {
const {palette} = useTheme()
const [loadingModuleDocs, setLoadingModuleDocs] = React.useState<boolean>(false)
const [fullWidth, setFullWidth] = React.useState(window.localStorage.getItem('docs-details--fullWidth') === 'yes')
const [modules, setModules] = React.useState<any>(undefined)
const {breakpoints} = useTheme()
const isLg = useMediaQuery(breakpoints.up('lg'))
const module = doc?.docModule
React.useEffect(() => {
if (!module || (module && moduleDocsCache.current[module.modulePath])) {
setModules(module ? moduleDocsCache.current[module.modulePath] : undefined)
setLoadingModuleDocs(false)
return
}
setLoadingModuleDocs(true)
fetch('/docs/' + module.package + '/' + module.fromPath + '.json')
.then((res) => res.status !== 200 ? Promise.reject(res) : res.json())
.then((data) => {
moduleDocsCache.current[module.modulePath] = data
setModules(data)
setLoadingModuleDocs(false)
})
.catch(e => {
console.error('error loading module-api docs', module, e)
setLoadingModuleDocs(false)
})
return () => setModules(undefined)
}, [module])
const mdData = React.useMemo(() => {
if (!content) return undefined
const lines: string[] = content.split('\n')
// todo: add correct front-matter extraction, but e.g. `front-matter` is no longer maintained/browser-optimized
if (lines[0] === '---') {
const i = lines.slice(1).findIndex((l: string) => l === '---')
if (i !== -1) {
lines.splice(0, i + 2)
}
}
return lines.join('\n')
}, [content])
return <>
<PageContent maxWidth={isLg && fullWidth ? 'xl' : 'md'} style={{flexGrow: 1}}>
<div style={{display: 'flex', alignItems: 'center', margin: '4px 12px'}}>
{isLg ?
<Button
onClick={() => {
setFullWidth(f => {
const n = !f
window.localStorage.setItem('docs-details--fullWidth', n ? 'yes' : 'no')
return n
})
}}
color={'secondary'} size={'small'}
>
{fullWidth ? <IcShowCompact style={{transform: 'rotate(90deg)'}}/> : <IcShowFull style={{transform: 'rotate(90deg)'}}/>}
</Button> : null}
<Typography variant={'body2'} style={{marginLeft: 'auto'}}>
<Link
target={'_blank'} rel="noreferrer noopener nofollow"
href={'https://github.com/ui-schema/ui-schema/tree/develop/packages/docs/src/content/' + id + '.md'}
>Edit Page</Link>
</Typography>
</div>
<Paper style={{margin: '0 0 12px 0', padding: 24, display: 'flex', flexDirection: 'column', borderRadius: 5}} variant={'outlined'}>
{progress === 'start' || progress === 'progress' || loadingModuleDocs ?
<LoadingCircular title={'Loading Docs'}/> :
progress === 'error' ?
'error' :
progress === 'not-found' ?
<PageNotFound
title={'Not Available'}
error={'This document seems to be vanished - or not yet created.'}
/> :
<Markdown source={mdData}/>}
</Paper>
{progress === 'success' && !loadingModuleDocs ?
<>
{doc?.demos?.schema ?
<div style={{display: 'block', textAlign: 'right', margin: '0 12px 4px 12px'}}>
<Typography variant={'body2'} style={{marginLeft: 'auto'}}>
<Link
target={'_blank'} rel="noreferrer noopener nofollow"
href={'https://github.com/ui-schema/ui-schema/tree/develop/packages/docs/src/content/' + id + 'Demo.js'}
>Edit Demos</Link>
</Typography>
</div> : null}
{doc?.demos?.schema ?
<Paper style={{marginBottom: 12, padding: 24, display: 'flex', flexDirection: 'column', borderRadius: 5}} variant={'outlined'}>
<Markdown
source={`
## Demo UI Generator
Examples of this widget, using \`ds-material\`. Type in/change the input and check the data or change the schema (e.g. add specific keywords from above), the demo generators are showing invalid directly.
`}/>
{doc?.demos?.schema.map(([demoText, demoSchema], i) =>
<React.Fragment key={i}>
<Markdown source={demoText}/>
<DemoUIGenerator activeSchema={demoSchema} id={'i-' + i}/>
</React.Fragment>)}
</Paper>
: null}
{doc?.docModule ?
<Paper style={{margin: '12px 0', padding: 24, display: 'flex', flexDirection: 'column', borderRadius: 5}} variant={'outlined'}>
<DocsDetailsModules modules={modules}/>
</Paper> : null}
</> : null}
</PageContent>
<Paper
style={{
margin: '0 12px',
// padding: '0 12px',
display: 'flex',
flexDirection: 'column',
overflowX: 'auto',
opacity: progress === 'success' ? 1 : 0,
transition: '0.32s opacity ease-out',
flexShrink: 0,
position: 'sticky',
bottom: 12,
left: 0,
right: 0,
zIndex: 10,
maxHeight: '85vh',
maxWidth: 375,
borderRadius: 5,
//borderTop: '1px solid ' + palette.primary.main,
//background: palette.primary.main,
boxShadow: '0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12)',
}}
// elevation={4}
variant={'outlined'}
>
<LinkableHeadlineMenu
disableNavLink
//style={{margin: 0, padding: 0}}
startIcon={<IcToc/>}
titleStyle={{color: palette.background.paper, fontWeight: 'bold', background: palette.primary.main}}
btnVariant={'contained'}
disablePadding
bindKey={'m'}
linkListStyle={{display: 'flex', flexDirection: 'column', overflow: 'auto'}}
// collapseStyle={{overflow: 'auto'}}
//linkItemStyle={{color: palette.background.paper}}
/>
</Paper>
</>
}
Example #29
Source File: ProfilePage.tsx From frontend with MIT License | 4 votes |
export default function ProfilePage() {
const { t } = useTranslation()
const { status } = useSession()
const router = useRouter()
const matches = useMediaQuery(theme.breakpoints.down('sm'))
const currentTab = router.query.slug ?? ProfileTabs.donations
const tab = useMemo<ProfileTab>(() => {
return tabs.find((tab) => tab.slug === currentTab) ?? tabs[0]
}, [currentTab])
if (status === 'loading') {
return <LinearProgress />
}
if (status !== 'authenticated') {
return (
<StyledLayout
title={t('nav.profile')}
githubUrl="https://github.com/podkrepi-bg/frontend/tree/master/src/components/auth/profile/ProfilePage.tsx"
figmaUrl="https://www.figma.com/file/MmvFKzUv6yE5U2wrOpWtwS/Podkrepi.bg?node-id=5987%3A21094">
Not authenticated
</StyledLayout>
)
}
const { Component: SelectedTab } = tab
return (
<Layout profilePage={true}>
<Box sx={{ width: '100%' }}>
<Box
sx={{
backgroundColor: 'white',
borderRadius: '25px 25px 0px 0px',
padding: '10px 30px',
boxShadow: 3,
}}>
<h1 className={classes.h1}>Дарителски профил</h1>
<Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
<Tabs value={tab.slug}>
<Tab
className={matches ? classes.tabMobile : ''}
value={ProfileTabs.donations}
label={matches ? undefined : t('profile:donations.index')}
aria-label={matches ? t('profile:donations.index') : undefined}
onClick={() => router.push(routes.profile.donations)}
icon={matches ? <DonationIcon /> : undefined}
/>
<Tab
className={matches ? classes.tabMobile : ''}
value={ProfileTabs.personalInformation}
label={matches ? undefined : t('profile:personalInformation')}
aria-label={matches ? t('profile:personalInformation') : undefined}
onClick={() => router.push(routes.profile.personalInformation)}
icon={matches ? <AccountBoxIcon /> : undefined}
/>
<Tab
className={matches ? classes.tabMobile : ''}
value={ProfileTabs.certificates}
label={matches ? undefined : t('profile:certificates')}
aria-label={matches ? t('profile:certificates') : undefined}
onClick={() => router.push(routes.profile.certificates)}
icon={matches ? <CertificateIcon /> : undefined}
/>
<Tab
className={matches ? classes.tabMobile : ''}
value={ProfileTabs.contractDonation}
label={matches ? undefined : t('profile:donationsContract')}
aria-label={matches ? t('profile:donationsContract') : undefined}
onClick={() => router.push(routes.profile.contractDonation)}
icon={matches ? <ContractIcon /> : undefined}
/>
</Tabs>
</Box>
</Box>
{SelectedTab && <SelectedTab />}
</Box>
</Layout>
)
}