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 { ApolloProvider } from "@apollo/client";
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 loadable from "@loadable/component";
@ -10,6 +10,19 @@ import apolloClient from "./apolloClient";
const WardrobePage = loadable(() => import("./WardrobePage"));
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
* stuff happening here, mostly just setting up some globals and theming!

View file

@ -1,7 +1,18 @@
import React from "react";
import { css } from "emotion";
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 { useLazyQuery } from "@apollo/client";
@ -19,13 +30,8 @@ function HomePage() {
const [previewState, setPreviewState] = React.useState(null);
return (
<Flex
color="green.800"
direction="column"
p="6"
align="center"
textAlign="center"
>
<Flex direction="column" p="6" align="center" textAlign="center">
<ColorModeToggleButton />
<Box height="8" />
<Box
width="200px"
@ -93,6 +99,9 @@ function StartOutfitForm({ onChange }) {
history.push(`/outfits/new?${params}`);
};
const buttonBgColor = useColorModeValue("green.600", "green.300");
const buttonBgColorHover = useColorModeValue("green.700", "green.200");
return (
<form onSubmit={onSubmit}>
<Flex>
@ -121,8 +130,8 @@ function StartOutfitForm({ onChange }) {
type="submit"
colorScheme="green"
disabled={!isValid}
backgroundColor="green.600" // for AA contrast
_hover={{ backgroundColor: "green.700" }}
backgroundColor={buttonBgColor}
_hover={{ backgroundColor: buttonBgColorHover }}
>
Start
</Button>
@ -192,6 +201,11 @@ function SubmitPetForm() {
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 (
<form onSubmit={onSubmit}>
<Flex>
@ -201,8 +215,8 @@ function SubmitPetForm() {
isDisabled={loading}
placeholder="Enter a pet's name"
aria-label="Enter a pet's name"
borderColor="green.600"
_hover={{ borderColor: "green.400" }}
borderColor={inputBorderColor}
_hover={{ borderColor: inputBorderColorHover }}
boxShadow="md"
width="14em"
className={css`
@ -217,8 +231,8 @@ function SubmitPetForm() {
colorScheme="green"
isDisabled={!petName}
isLoading={loading}
backgroundColor="green.600" // for AA contrast
_hover={{ backgroundColor: "green.700" }}
backgroundColor={buttonBgColor} // for AA contrast
_hover={{ backgroundColor: buttonBgColorHover }}
>
Start
</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.
* If you provide ?supportSecret=... in the URL, we'll save it in a cookie and

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,7 +1,7 @@
import React from "react";
import gql from "graphql-tag";
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";
@ -55,9 +55,10 @@ function SpeciesColorPicker({
const allSpecies = (meta && [...meta.allSpecies]) || [];
allSpecies.sort((a, b) => a.name.localeCompare(b.name));
const backgroundColor = dark ? "gray.600" : "white";
const borderColor = dark ? "transparent" : "green.600";
const textColor = dark ? "gray.50" : "inherit";
const backgroundColor = useColorModeValue("white", "gray.600");
const borderColor = useColorModeValue("green.600", "transparent");
const textColor = useColorModeValue("inherit", "green.50");
const SpeciesColorSelect = ({ isDisabled, isLoading, ...props }) => {
const loadingProps = isLoading
? {

View file

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