dark mode first draft!

Hey wow this was not so hard, just set some global styles, removed some hardcoded colors, and walked through the remaining hardcoded colors to pick a dark mode variant :) neat!!
This commit is contained in:
Emi Matchu 2020-08-12 00:37:31 -07:00
parent 12bd9f6b17
commit 086cf8b335
15 changed files with 139 additions and 51 deletions

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { ApolloProvider } from "@apollo/client"; import { ApolloProvider } from "@apollo/client";
import { CSSReset, ChakraProvider } from "@chakra-ui/core"; import { CSSReset, ChakraProvider } from "@chakra-ui/core";
import theme from "@chakra-ui/theme"; import defaultTheme from "@chakra-ui/theme";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom"; import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import loadable from "@loadable/component"; import loadable from "@loadable/component";
@ -10,6 +10,19 @@ import apolloClient from "./apolloClient";
const WardrobePage = loadable(() => import("./WardrobePage")); const WardrobePage = loadable(() => import("./WardrobePage"));
const HomePage = loadable(() => import("./HomePage")); const HomePage = loadable(() => import("./HomePage"));
const theme = {
...defaultTheme,
styles: {
...defaultTheme.styles,
global: ({ colorMode, ...rest }) => ({
...defaultTheme.styles.global({ colorMode, ...rest }),
color: colorMode === "light" ? "green.800" : "green.50",
}),
},
};
console.log(defaultTheme.styles.global, defaultTheme.styles);
/** /**
* App is the entry point of our application. There's not a ton of exciting * App is the entry point of our application. There's not a ton of exciting
* stuff happening here, mostly just setting up some globals and theming! * stuff happening here, mostly just setting up some globals and theming!

View file

@ -1,7 +1,18 @@
import React from "react"; import React from "react";
import { css } from "emotion"; import { css } from "emotion";
import gql from "graphql-tag"; import gql from "graphql-tag";
import { Box, Button, Flex, Input, useTheme, useToast } from "@chakra-ui/core"; import {
Box,
Button,
Flex,
IconButton,
Input,
useColorMode,
useColorModeValue,
useTheme,
useToast,
} from "@chakra-ui/core";
import { MoonIcon, SunIcon } from "@chakra-ui/icons";
import { useHistory, useLocation } from "react-router-dom"; import { useHistory, useLocation } from "react-router-dom";
import { useLazyQuery } from "@apollo/client"; import { useLazyQuery } from "@apollo/client";
@ -19,13 +30,8 @@ function HomePage() {
const [previewState, setPreviewState] = React.useState(null); const [previewState, setPreviewState] = React.useState(null);
return ( return (
<Flex <Flex direction="column" p="6" align="center" textAlign="center">
color="green.800" <ColorModeToggleButton />
direction="column"
p="6"
align="center"
textAlign="center"
>
<Box height="8" /> <Box height="8" />
<Box <Box
width="200px" width="200px"
@ -93,6 +99,9 @@ function StartOutfitForm({ onChange }) {
history.push(`/outfits/new?${params}`); history.push(`/outfits/new?${params}`);
}; };
const buttonBgColor = useColorModeValue("green.600", "green.300");
const buttonBgColorHover = useColorModeValue("green.700", "green.200");
return ( return (
<form onSubmit={onSubmit}> <form onSubmit={onSubmit}>
<Flex> <Flex>
@ -121,8 +130,8 @@ function StartOutfitForm({ onChange }) {
type="submit" type="submit"
colorScheme="green" colorScheme="green"
disabled={!isValid} disabled={!isValid}
backgroundColor="green.600" // for AA contrast backgroundColor={buttonBgColor}
_hover={{ backgroundColor: "green.700" }} _hover={{ backgroundColor: buttonBgColorHover }}
> >
Start Start
</Button> </Button>
@ -192,6 +201,11 @@ function SubmitPetForm() {
import("./WardrobePage"); import("./WardrobePage");
}; };
const inputBorderColor = useColorModeValue("green.600", "green.500");
const inputBorderColorHover = useColorModeValue("green.400", "green.300");
const buttonBgColor = useColorModeValue("green.600", "green.300");
const buttonBgColorHover = useColorModeValue("green.700", "green.200");
return ( return (
<form onSubmit={onSubmit}> <form onSubmit={onSubmit}>
<Flex> <Flex>
@ -201,8 +215,8 @@ function SubmitPetForm() {
isDisabled={loading} isDisabled={loading}
placeholder="Enter a pet's name" placeholder="Enter a pet's name"
aria-label="Enter a pet's name" aria-label="Enter a pet's name"
borderColor="green.600" borderColor={inputBorderColor}
_hover={{ borderColor: "green.400" }} _hover={{ borderColor: inputBorderColorHover }}
boxShadow="md" boxShadow="md"
width="14em" width="14em"
className={css` className={css`
@ -217,8 +231,8 @@ function SubmitPetForm() {
colorScheme="green" colorScheme="green"
isDisabled={!petName} isDisabled={!petName}
isLoading={loading} isLoading={loading}
backgroundColor="green.600" // for AA contrast backgroundColor={buttonBgColor} // for AA contrast
_hover={{ backgroundColor: "green.700" }} _hover={{ backgroundColor: buttonBgColorHover }}
> >
Start Start
</Button> </Button>
@ -227,6 +241,21 @@ function SubmitPetForm() {
); );
} }
function ColorModeToggleButton() {
const { colorMode, toggleColorMode } = useColorMode();
return (
<IconButton
icon={colorMode === "light" ? <MoonIcon /> : <SunIcon />}
onClick={toggleColorMode}
variant="ghost"
position="absolute"
bottom="3"
right="3"
/>
);
}
/** /**
* useSupportSetup helps our support staff get set up with special access. * useSupportSetup helps our support staff get set up with special access.
* If you provide ?supportSecret=... in the URL, we'll save it in a cookie and * If you provide ?supportSecret=... in the URL, we'll save it in a cookie and

View file

@ -7,6 +7,7 @@ import {
Image, Image,
Skeleton, Skeleton,
Tooltip, Tooltip,
useColorModeValue,
useTheme, useTheme,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
import { EditIcon, DeleteIcon, InfoIcon } from "@chakra-ui/icons"; import { EditIcon, DeleteIcon, InfoIcon } from "@chakra-ui/icons";
@ -120,6 +121,21 @@ function ItemSkeleton() {
function ItemContainer({ children }) { function ItemContainer({ children }) {
const theme = useTheme(); const theme = useTheme();
const focusBackgroundColor = useColorModeValue(
theme.colors.gray["100"],
theme.colors.gray["700"]
);
const activeBorderColor = useColorModeValue(
theme.colors.green["400"],
theme.colors.green["500"]
);
const focusCheckedBorderColor = useColorModeValue(
theme.colors.green["800"],
theme.colors.green["300"]
);
return ( return (
<Box <Box
p="1" p="1"
@ -135,15 +151,15 @@ function ItemContainer({ children }) {
css` css`
&:hover, &:hover,
input:focus + & { input:focus + & {
background-color: ${theme.colors.gray["100"]}; background-color: ${focusBackgroundColor};
} }
input:active + & { input:active + & {
border-color: ${theme.colors.green["400"]}; border-color: ${activeBorderColor};
} }
input:checked:focus + & { input:checked:focus + & {
border-color: ${theme.colors.green["800"]}; border-color: ${focusCheckedBorderColor};
} }
`, `,
])} ])}
@ -159,6 +175,17 @@ function ItemContainer({ children }) {
*/ */
function ItemThumbnail({ src, isWorn }) { function ItemThumbnail({ src, isWorn }) {
const theme = useTheme(); const theme = useTheme();
const borderColor = useColorModeValue(
theme.colors.green["700"],
"transparent"
);
const focusBorderColor = useColorModeValue(
theme.colors.green["600"],
"transparent"
);
return ( return (
<Box <Box
borderRadius="lg" borderRadius="lg"
@ -171,14 +198,14 @@ function ItemThumbnail({ src, isWorn }) {
transformOrigin="center" transformOrigin="center"
className={css([ className={css([
{ {
borderColor: theme.colors.green["700"], borderColor: `${borderColor} !important`,
transform: "scale(0.8)", transform: "scale(0.8)",
}, },
!isWorn && { !isWorn && {
[containerHasFocus]: { [containerHasFocus]: {
opacity: "0.9", opacity: "0.9",
transform: "scale(0.9)", transform: "scale(0.9)",
borderColor: theme.colors.green["600"], borderColor: `${focusBorderColor} !important`,
}, },
}, },
isWorn && { isWorn && {
@ -202,7 +229,6 @@ function ItemName({ children, ...props }) {
return ( return (
<Box <Box
fontSize="md" fontSize="md"
color="green.800"
transition="all 0.15s" transition="all 0.15s"
className={css` className={css`
${containerHasFocus} { ${containerHasFocus} {
@ -228,6 +254,15 @@ function ItemName({ children, ...props }) {
function ItemActionButton({ icon, label, href, onClick }) { function ItemActionButton({ icon, label, href, onClick }) {
const theme = useTheme(); const theme = useTheme();
const focusBackgroundColor = useColorModeValue(
theme.colors.gray["300"],
theme.colors.gray["800"]
);
const focusColor = useColorModeValue(
theme.colors.gray["700"],
theme.colors.gray["200"]
);
return ( return (
<Tooltip label={label} placement="top"> <Tooltip label={label} placement="top">
<IconButton <IconButton
@ -250,8 +285,8 @@ function ItemActionButton({ icon, label, href, onClick }) {
&:focus, &:focus,
&:hover { &:hover {
opacity: 1; opacity: 1;
background-color: ${theme.colors.gray["300"]}; background-color: ${focusBackgroundColor};
color: ${theme.colors.gray["700"]}; color: ${focusColor};
} }
/* On touch devices, always show the buttons! This avoids having to /* On touch devices, always show the buttons! This avoids having to

View file

@ -7,6 +7,7 @@ import {
InputGroup, InputGroup,
InputLeftElement, InputLeftElement,
InputRightElement, InputRightElement,
useColorModeValue,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
import { CloseIcon, SearchIcon } from "@chakra-ui/icons"; import { CloseIcon, SearchIcon } from "@chakra-ui/icons";
@ -103,6 +104,8 @@ function SearchToolbar({
} }
}; };
const focusBorderColor = useColorModeValue("green.600", "green.400");
return ( return (
<InputGroup> <InputGroup>
<InputLeftElement> <InputLeftElement>
@ -111,8 +114,7 @@ function SearchToolbar({
<Input <Input
placeholder="Search for items to add…" placeholder="Search for items to add…"
aria-label="Search for items to add…" aria-label="Search for items to add…"
focusBorderColor="green.600" focusBorderColor={focusBorderColor}
color="green.800"
value={query} value={query}
ref={searchQueryRef} ref={searchQueryRef}
onChange={(e) => onChange(e.target.value)} onChange={(e) => onChange(e.target.value)}

View file

@ -33,7 +33,7 @@ function ItemsPanel({ outfitState, loading, dispatchToOutfit }) {
const { zonesAndItems } = outfitState; const { zonesAndItems } = outfitState;
return ( return (
<Box color="green.800"> <Box>
<Box px="1"> <Box px="1">
<OutfitHeading <OutfitHeading
outfitState={outfitState} outfitState={outfitState}
@ -202,7 +202,6 @@ function OutfitHeading({ outfitState, dispatchToOutfit }) {
<IconButton <IconButton
icon={<EditIcon />} icon={<EditIcon />}
variant="link" variant="link"
color="green.600"
aria-label="Edit outfit name" aria-label="Edit outfit name"
title="Edit outfit name" title="Edit outfit name"
/> />

View file

@ -2,6 +2,7 @@ import React from "react";
import { css, cx } from "emotion"; import { css, cx } from "emotion";
import { import {
Box, Box,
DarkMode,
Flex, Flex,
IconButton, IconButton,
Stack, Stack,
@ -155,13 +156,14 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
*/} */}
<Box flex="1 1 0" /> <Box flex="1 1 0" />
<Box flex="0 0 auto"> <Box flex="0 0 auto">
<DarkMode>
<SpeciesColorPicker <SpeciesColorPicker
speciesId={outfitState.speciesId} speciesId={outfitState.speciesId}
colorId={outfitState.colorId} colorId={outfitState.colorId}
idealPose={outfitState.pose} idealPose={outfitState.pose}
dark
onChange={onSpeciesColorChange} onChange={onSpeciesColorChange}
/> />
</DarkMode>
</Box> </Box>
<Flex flex="1 1 0" align="center" pl="4"> <Flex flex="1 1 0" align="center" pl="4">
<PosePicker <PosePicker

View file

@ -12,6 +12,7 @@ import {
PopoverTrigger, PopoverTrigger,
Portal, Portal,
VisuallyHidden, VisuallyHidden,
useColorModeValue,
useTheme, useTheme,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
@ -258,6 +259,11 @@ function PoseOption({ poseInfo, onChange, inputRef }) {
label += ` (not modeled yet)`; label += ` (not modeled yet)`;
} }
const borderColor = useColorModeValue(
theme.colors.green["600"],
theme.colors.green["300"]
);
return ( return (
<Box <Box
as="label" as="label"
@ -316,7 +322,7 @@ function PoseOption({ poseInfo, onChange, inputRef }) {
zIndex="2" zIndex="2"
className={cx( className={cx(
css` css`
border: 0px solid ${theme.colors.green["600"]}; border: 0px solid ${borderColor};
transition: border-width 0.2s; transition: border-width 0.2s;
&.not-available { &.not-available {

View file

@ -39,7 +39,6 @@ function SearchPanel({
return ( return (
<Box <Box
color="green.800"
onKeyDown={(e) => { onKeyDown={(e) => {
// This will catch any Escape presses when the user's focus is inside // This will catch any Escape presses when the user's focus is inside
// the SearchPanel. // the SearchPanel.
@ -125,7 +124,7 @@ function SearchResults({
); );
} else if (error) { } else if (error) {
return ( return (
<Text color="green.500"> <Text>
We hit an error trying to load your search results{" "} We hit an error trying to load your search results{" "}
<span role="img" aria-label="(sweat emoji)"> <span role="img" aria-label="(sweat emoji)">
😓 😓
@ -135,7 +134,7 @@ function SearchResults({
); );
} else if (items.length === 0) { } else if (items.length === 0) {
return ( return (
<Text color="green.500"> <Text>
We couldn't find any matching items{" "} We couldn't find any matching items{" "}
<span role="img" aria-label="(thinking emoji)"> <span role="img" aria-label="(thinking emoji)">
🤔 🤔

View file

@ -122,7 +122,7 @@ function ItemLayerSupportModal({
return ( return (
<Modal size="xl" isOpen={isOpen} onClose={onClose}> <Modal size="xl" isOpen={isOpen} onClose={onClose}>
<ModalOverlay> <ModalOverlay>
<ModalContent color="green.800"> <ModalContent>
<ModalHeader> <ModalHeader>
Layer {itemLayer.id}: {item.name} Layer {itemLayer.id}: {item.name}
</ModalHeader> </ModalHeader>

View file

@ -144,7 +144,7 @@ function ItemLayerSupportUploadModal({ item, itemLayer, isOpen, onClose }) {
onClose={onClose} onClose={onClose}
> >
<ModalOverlay> <ModalOverlay>
<ModalContent color="green.800"> <ModalContent>
<ModalHeader textAlign="center"> <ModalHeader textAlign="center">
Upload PNG for {item.name} Upload PNG for {item.name}
</ModalHeader> </ModalHeader>

View file

@ -21,6 +21,7 @@ import {
Spinner, Spinner,
Stack, Stack,
useBreakpointValue, useBreakpointValue,
useColorModeValue,
useDisclosure, useDisclosure,
} from "@chakra-ui/core"; } from "@chakra-ui/core";
import { CheckCircleIcon, EditIcon, ExternalLinkIcon } from "@chakra-ui/icons"; import { CheckCircleIcon, EditIcon, ExternalLinkIcon } from "@chakra-ui/icons";
@ -66,13 +67,13 @@ function ItemSupportDrawer({ item, isOpen, onClose }) {
overflow="auto" overflow="auto"
> >
<DrawerCloseButton /> <DrawerCloseButton />
<DrawerHeader color="green.800"> <DrawerHeader>
{item.name} {item.name}
<Badge colorScheme="pink" marginLeft="3"> <Badge colorScheme="pink" marginLeft="3">
Support <span aria-hidden="true">💖</span> Support <span aria-hidden="true">💖</span>
</Badge> </Badge>
</DrawerHeader> </DrawerHeader>
<DrawerBody color="green.800"> <DrawerBody>
<Box paddingBottom="5"> <Box paddingBottom="5">
<Stack spacing="8"> <Stack spacing="8">
<ItemSupportSpecialColorFields item={item} /> <ItemSupportSpecialColorFields item={item} />
@ -156,6 +157,8 @@ function ItemSupportSpecialColorFields({ item }) {
colorsData?.allColors?.filter((c) => !c.isStandard) || []; colorsData?.allColors?.filter((c) => !c.isStandard) || [];
nonStandardColors.sort((a, b) => a.name.localeCompare(b.name)); nonStandardColors.sort((a, b) => a.name.localeCompare(b.name));
const linkColor = useColorModeValue("green.500", "green.300");
return ( return (
<FormControl <FormControl
isInvalid={colorsError || itemError || mutationError ? true : false} isInvalid={colorsError || itemError || mutationError ? true : false}
@ -217,7 +220,7 @@ function ItemSupportSpecialColorFields({ item }) {
href={`https://impress.openneo.net/items/${ href={`https://impress.openneo.net/items/${
item.id item.id
}-${item.name.replace(/ /g, "-")}`} }-${item.name.replace(/ /g, "-")}`}
color="green.500" color={linkColor}
isExternal isExternal
> >
item page <ExternalLinkIcon /> item page <ExternalLinkIcon />

View file

@ -82,7 +82,7 @@ function HangerSpinner(props) {
} }
`} `}
> >
<HangerIcon {...props} /> <HangerIcon color="green.300" {...props} />
</Box> </Box>
</> </>
); );

View file

@ -176,7 +176,7 @@ export function OutfitLayers({
/> />
</FullScreenCenter> </FullScreenCenter>
<FullScreenCenter zIndex="9001"> <FullScreenCenter zIndex="9001">
<HangerSpinner color="green.300" boxSize="48px" /> <HangerSpinner boxSize="48px" />
</FullScreenCenter> </FullScreenCenter>
</Box> </Box>
</Box> </Box>

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import gql from "graphql-tag"; import gql from "graphql-tag";
import { useQuery } from "@apollo/client"; import { useQuery } from "@apollo/client";
import { Box, Flex, Select, Text } from "@chakra-ui/core"; import { Box, Flex, Select, Text, useColorModeValue } from "@chakra-ui/core";
import { Delay, useFetch } from "../util"; import { Delay, useFetch } from "../util";
@ -55,9 +55,10 @@ function SpeciesColorPicker({
const allSpecies = (meta && [...meta.allSpecies]) || []; const allSpecies = (meta && [...meta.allSpecies]) || [];
allSpecies.sort((a, b) => a.name.localeCompare(b.name)); allSpecies.sort((a, b) => a.name.localeCompare(b.name));
const backgroundColor = dark ? "gray.600" : "white"; const backgroundColor = useColorModeValue("white", "gray.600");
const borderColor = dark ? "transparent" : "green.600"; const borderColor = useColorModeValue("green.600", "transparent");
const textColor = dark ? "gray.50" : "inherit"; const textColor = useColorModeValue("inherit", "green.50");
const SpeciesColorSelect = ({ isDisabled, isLoading, ...props }) => { const SpeciesColorSelect = ({ isDisabled, isLoading, ...props }) => {
const loadingProps = isLoading const loadingProps = isLoading
? { ? {

View file

@ -34,9 +34,9 @@ export function Delay({ children, ms = 300 }) {
export function Heading1({ children, ...props }) { export function Heading1({ children, ...props }) {
return ( return (
<Heading <Heading
size="2xl"
fontFamily="Delicious, sans-serif" fontFamily="Delicious, sans-serif"
fontWeight="800" fontWeight="800"
size="2xl"
{...props} {...props}
> >
{children} {children}
@ -52,7 +52,6 @@ export function Heading2({ children, ...props }) {
return ( return (
<Heading <Heading
size="xl" size="xl"
color="green.800"
fontFamily="Delicious, sans-serif" fontFamily="Delicious, sans-serif"
fontWeight="700" fontWeight="700"
{...props} {...props}