Skip to content

Commit

Permalink
[Footer/header] feat: new color scheme toggle and cleaner footer design
Browse files Browse the repository at this point in the history
  • Loading branch information
dgattey committed Dec 31, 2023
1 parent 5b65f54 commit 6d0a72e
Show file tree
Hide file tree
Showing 11 changed files with 138 additions and 176 deletions.
14 changes: 8 additions & 6 deletions apps/web/src/components/Footer.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Container } from '@mui/material';
import { Container, Divider } from '@mui/material';
import { Section } from 'ui/core/Section';
import { Nav, NavGroup, NavItem } from 'ui/core/Nav';
import { HorizontalStack } from 'ui/core/HorizontalStack';
Expand All @@ -20,14 +20,16 @@ function FooterLink({ link }: { link: LinkType }) {
layout="icon" // the ones that have no icon will resolve to just text
linkProps={{
color: 'secondary',
variant: 'caption',
}}
sx={{
// Min tap target size
minWidth: 48,
minHeight: 48,
minWidth: 40,
minHeight: 40,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: link.icon ? '1.25em' : undefined,
}}
title={link.title}
/>
Expand All @@ -44,14 +46,14 @@ export function Footer() {
const nonIconFooterLinks = footerLinks?.filter((link) => !link.icon);
const iconFooterLinks = footerLinks?.filter((link) => link.icon);
return (
<Container component={Section} sx={{ padding: 0 }}>
<Container component={Section} sx={{ padding: 0, marginTop: 12 }}>
<footer>
<Divider sx={{ marginBottom: 3 }} />
<Nav
sx={(theme) => ({
flexDirection: 'row',
flexWrap: 'wrap-reverse',
columnGap: 3,
marginTop: 8,
[theme.breakpoints.down('sm')]: {
flexDirection: 'column-reverse',
},
Expand All @@ -72,7 +74,7 @@ export function Footer() {
padding: 0,
margin: 0,
flex: 1,
marginLeft: -1.5,
marginLeft: -2.5,
marginRight: -1.5,
justifyContent: 'space-between',
}}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function Header({ headerRef }: HeaderProps) {
>
<Nav>
<NavGroup>
<NavItem>
<NavItem variant="body2">
<Logo />
</NavItem>
<NavItem>
Expand Down
8 changes: 2 additions & 6 deletions apps/web/src/components/strava/ActivityTypeWithIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { faBicycle } from '@fortawesome/free-solid-svg-icons/faBicycle';
import { faRunning } from '@fortawesome/free-solid-svg-icons/faRunning';
import { Typography } from '@mui/material';
import { HorizontalStack } from 'ui/core/HorizontalStack';
import { FaIcon } from 'ui/icons/FaIcon';
import { Bike, Dumbbell } from 'lucide-react';
import { useData } from 'api/useData';

/**
Expand All @@ -19,9 +17,7 @@ export function ActivityTypeWithIcon() {
const typeText = activity.type.includes('Ride')
? activity.type.replace(/(?<rideType>[A-Z][a-z]+)/g, ' $1')
: 'Run';
const icon = (
<FaIcon icon={activity.type.includes('Ride') ? faBicycle : faRunning} size="1.25em" />
);
const icon = activity.type.includes('Ride') ? <Bike size="1.25em" /> : <Dumbbell size="1.25em" />;

return (
<Typography
Expand Down
23 changes: 23 additions & 0 deletions packages/ui/core/ButtonWithTooltip.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type { ButtonProps, TooltipProps } from '@mui/material';
import { Button, Tooltip } from '@mui/material';

/**
* Handles weird layout problems with buttons and tooltips by wrapping it in a div
*/
export function ButtonWithTooltip({
tooltipProps,
buttonProps,
children,
}: {
tooltipProps: Partial<Omit<TooltipProps, 'children'>> & Pick<TooltipProps, 'title'>;
buttonProps: Partial<Omit<ButtonProps, 'children'>>;
children: React.ReactNode;
}) {
return (
<Tooltip {...tooltipProps}>
<div>
<Button {...buttonProps}>{children}</Button>
</div>
</Tooltip>
);
}
84 changes: 84 additions & 0 deletions packages/ui/core/ColorSchemeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { Moon, Sun, Monitor } from 'lucide-react';
import type { Theme } from '@mui/material';
import { useColorScheme } from '../theme/useColorScheme';
import type { ColorSchemeMode } from '../theme/useColorScheme';
import { ButtonWithTooltip } from './ButtonWithTooltip';

type Mode = ColorSchemeMode | 'system';

type ColorSchemeButtonProps = {
/**
* The color scheme mode to switch to on click
*/
mode: Mode;
};

const ICON_SIZE = 13;
const DELAY_MS = 200;

const ICONS: Record<Mode, JSX.Element> = {
light: <Sun size={ICON_SIZE} />,
dark: <Moon size={ICON_SIZE} />,
system: <Monitor size={ICON_SIZE} />,
} as const;

function getColor(mode: Mode, theme: Theme) {
switch (mode) {
case 'light':
return theme.vars.palette.warning.main;
case 'dark':
return theme.vars.palette.secondary.light;
case 'system':
return theme.vars.palette.primary.dark;
}
}

/**
* Creates an icon that is clickable to update to a preferred color scheme
* if we have one that's set already. Otherwise, renders a disabled icon.
*/
export function ColorSchemeButton({ mode }: ColorSchemeButtonProps) {
const { updatePreferredMode } = useColorScheme();
const tooltip = (() => {
switch (mode) {
case 'light':
return 'Use light color mode';
case 'dark':
return 'Use dark color mode';
case 'system':
return `Use system color mode`;
}
})();

return (
<ButtonWithTooltip
buttonProps={{
size: 'small',
'aria-label': tooltip,
onClick: () => {
updatePreferredMode(mode === 'system' ? null : mode);
},
sx: (theme) => ({
paddingY: 0.75,
paddingX: 0.25,
'& svg': {
transition: theme.transitions.create('transform'),
transformOrigin: 'center',
},
'&:hover svg': {
color: getColor(mode, theme),
transform: mode === 'system' ? undefined : 'rotate(45deg)',
},
}),
}}
tooltipProps={{
enterDelay: DELAY_MS,
enterNextDelay: DELAY_MS,
enterTouchDelay: DELAY_MS,
title: tooltip,
}}
>
{ICONS[mode]}
</ButtonWithTooltip>
);
}
84 changes: 0 additions & 84 deletions packages/ui/core/ColorSchemeIcon.tsx

This file was deleted.

77 changes: 7 additions & 70 deletions packages/ui/core/ColorSchemeToggle.tsx
Original file line number Diff line number Diff line change
@@ -1,81 +1,18 @@
import { Stack, Switch, switchClasses } from '@mui/material';
import { useColorScheme } from '../theme/useColorScheme';
import { ColorSchemeIcon } from './ColorSchemeIcon';

const HEIGHT_PX = 24;
const WIDTH_PX = 48;
const PADDING = 0.5;
const PADDING_PX = PADDING * 8;
const TRACK_SIZE_PX = HEIGHT_PX - 2 * PADDING_PX;
import { ButtonGroup, Stack } from '@mui/material';
import { ColorSchemeButton } from './ColorSchemeButton';

/**
* Provides the ability to toggle the page's color scheme between
* system, light, and dark. Prerendered, `mode` is `light`.
*/
export function ColorSchemeToggle() {
const { colorScheme, updatePreferredMode } = useColorScheme();
const setInvertedScheme = () => {
updatePreferredMode(colorScheme.mode === 'dark' ? 'light' : 'dark');
};

return (
<Stack sx={{ flexDirection: 'row', alignItems: 'center' }}>
<ColorSchemeIcon mode="light" />
<Switch
aria-hidden
aria-label="Change color scheme mode"
checked={colorScheme.isInitialized ? colorScheme.mode === 'dark' : false}
onChange={setInvertedScheme}
sx={(theme) => ({
// Overrides our "animations off" for color scheme changes since we do always want the switch to animate
'& *': {
transition: `${theme.transitions.create('all', {
duration: theme.transitions.duration.complex,
})} !important`,
},
height: HEIGHT_PX,
width: WIDTH_PX,
margin: 0,
padding: 0,

[`&& .${switchClasses.switchBase}`]: {
cursor: colorScheme.isInitialized ? 'pointer' : 'not-allowed',
margin: PADDING,
padding: 0,

[`&.${switchClasses.checked}`]: {
transform: `translateX(${WIDTH_PX - TRACK_SIZE_PX - 2 * PADDING_PX}px)`,
[`&& + .${switchClasses.track}`]: {
opacity: 1,
backgroundColor: colorScheme.isCustomized
? theme.vars.palette.active.main
: theme.vars.palette.card.border,
},
},
},
[`&& .${switchClasses.input}`]: {
width: WIDTH_PX * 2 + TRACK_SIZE_PX,
height: HEIGHT_PX,
left: -WIDTH_PX - TRACK_SIZE_PX / 2,
top: -PADDING_PX,
},
[`& .${switchClasses.thumb}`]: {
backgroundColor: theme.vars.palette.common.white,
width: TRACK_SIZE_PX,
height: TRACK_SIZE_PX,
},
[`&&& .${switchClasses.track}`]: {
opacity: 1,
backgroundColor: colorScheme.isCustomized
? theme.vars.palette.active.main
: theme.vars.palette.card.border,
borderRadius: HEIGHT_PX / 2,
transition: theme.transitions.create('background-color'),
},
})}
tabIndex={-1}
/>
<ColorSchemeIcon mode="dark" />
<ButtonGroup aria-label="outlined primary button group" size="small" variant="outlined">
<ColorSchemeButton mode="light" />
<ColorSchemeButton mode="dark" />
<ColorSchemeButton mode="system" />
</ButtonGroup>
</Stack>
);
}
2 changes: 1 addition & 1 deletion packages/ui/core/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export function NavItem({ sx, children, ...props }: TypographyProps) {
return (
<Typography
component="li"
variant="body2"
variant="caption"
{...props}
sx={mixinSx(
(theme) => ({
Expand Down
8 changes: 4 additions & 4 deletions packages/ui/core/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@ import { mixinSx } from '../helpers/mixinSx';

export const sectionSx: SxProps = (theme) => ({
[theme.breakpoints.up('sm')]: {
marginBottom: 5.3125,
marginBottom: 3,
},
[theme.breakpoints.up('md')]: {
marginBottom: 6.375,
marginBottom: 3.6,
},
[theme.breakpoints.up('lg')]: {
marginBottom: 7.4375,
marginBottom: 4.32,
},
[theme.breakpoints.up('xl')]: {
marginBottom: 8.5,
marginBottom: 5.184,
},
});

Expand Down
Loading

0 comments on commit 6d0a72e

Please sign in to comment.