diff --git a/hyperglass/ui/components/Header.js b/hyperglass/ui/components/Header.js index 47f6f18..e4ab523 100644 --- a/hyperglass/ui/components/Header.js +++ b/hyperglass/ui/components/Header.js @@ -3,6 +3,7 @@ import { Flex, IconButton, useColorMode } from "@chakra-ui/core"; import { motion, AnimatePresence } from "framer-motion"; import ResetButton from "~/components/ResetButton"; import useMedia from "~/components/MediaProvider"; +import useConfig from "~/components/HyperglassProvider"; import Title from "~/components/Title"; const AnimatedFlex = motion.custom(Flex); @@ -11,19 +12,23 @@ const AnimatedResetButton = motion.custom(ResetButton); const titleVariants = { sm: { fullSize: { scale: 1, marginLeft: 0 }, - small: { marginLeft: "auto" } + smallLogo: { marginLeft: "auto" }, + smallText: { marginLeft: "auto" } }, md: { fullSize: { scale: 1 }, - small: { scale: 1 } + smallLogo: { scale: 0.5 }, + smallText: { scale: 0.8 } }, lg: { fullSize: { scale: 1 }, - small: { scale: 1 } + smallLogo: { scale: 0.5 }, + smallText: { scale: 0.8 } }, xl: { fullSize: { scale: 1 }, - small: { scale: 1 } + smallLogo: { scale: 0.5 }, + smallText: { scale: 0.8 } } }; @@ -35,9 +40,22 @@ const titleJustify = { true: ["flex-end", "flex-end", "center", "center"], false: ["flex-start", "flex-start", "center", "center"] }; +const titleHeight = { + true: null, + false: [null, "20vh", "20vh", "20vh"] +}; +const resetButtonMl = { true: [null, 2, 2, 2], false: null }; -export default ({ height, isSubmitting, handleFormReset, ...props }) => { +const widthMap = { + text_only: "100%", + logo_only: ["90%", "90%", "25%", "25%"], + logo_subtitle: ["90%", "90%", "25%", "25%"], + all: ["90%", "90%", "25%", "25%"] +}; + +export default ({ isSubmitting, handleFormReset, ...props }) => { const { colorMode, toggleColorMode } = useColorMode(); + const { web } = useConfig(); const { mediaSize } = useMedia(); const resetButton = ( @@ -48,7 +66,8 @@ export default ({ height, isSubmitting, handleFormReset, ...props }) => { exit={{ opacity: 0, x: -50 }} alignItems="center" mb={[null, "auto"]} - ml={isSubmitting ? 2 : null} + ml={resetButtonMl[isSubmitting]} + display={isSubmitting ? "flex" : "none"} > @@ -61,13 +80,20 @@ export default ({ height, isSubmitting, handleFormReset, ...props }) => { alignItems={isSubmitting ? "center" : ["center", "center", "flex-end", "flex-end"]} positionTransition={headerTransition} initial={{ scale: 0.5 }} - animate={isSubmitting ? "small" : "fullSize"} + animate={ + isSubmitting && web.text.title_mode === "text_only" + ? "smallText" + : isSubmitting && web.text.title_mode !== "text_only" + ? "smallLogo" + : "fullSize" + } variants={titleVariants[mediaSize]} justifyContent={titleJustify[isSubmitting]} mb={[null, isSubmitting ? "auto" : null]} mt={[null, isSubmitting ? null : "auto"]} - maxW="100%" + maxW={widthMap[web.text.title_mode]} flex="1 0 0" + minH={titleHeight[isSubmitting]} > </AnimatedFlex> @@ -86,7 +112,8 @@ export default ({ height, isSubmitting, handleFormReset, ...props }) => { aria-label={colorSwitch[colorMode]} variant="ghost" color="current" - pl={0} + px={4} + p={null} fontSize="20px" onClick={toggleColorMode} icon={icon[colorMode]} @@ -110,24 +137,20 @@ export default ({ height, isSubmitting, handleFormReset, ...props }) => { return ( <Flex px={2} - top="0" - left="0" - right="0" zIndex="4" as="header" width="full" - flex="1 0 auto" - position="fixed" + flex="0 1 auto" bg={bg[colorMode]} color="gray.500" - height={height} {...props} > <Flex w="100%" mx="auto" - py={6} + pt={6} justify="space-between" + flex="1 0 auto" alignItems={isSubmitting ? "center" : "flex-start"} > {layout[isSubmitting][mediaSize]} diff --git a/hyperglass/ui/components/Layout.js b/hyperglass/ui/components/Layout.js index d9f588e..5300605 100644 --- a/hyperglass/ui/components/Layout.js +++ b/hyperglass/ui/components/Layout.js @@ -13,8 +13,6 @@ const AnimatedForm = motion.custom(HyperglassForm); const bg = { light: "white", dark: "black" }; const color = { light: "black", dark: "white" }; -const headerHeightDefault = { true: [16, 16, 32, 32], false: [24, 64, 64, 64] }; -const headerHeightAll = { true: [32, 32, 32, 32], false: [48, "20rem", "20rem", "20rem"] }; const Layout = () => { const config = useConfig(); @@ -26,10 +24,6 @@ const Layout = () => { containerRef.current.scrollIntoView({ behavior: "smooth", block: "start" }); setSubmitting(false); }; - const headerHeight = - config.web.text.title_mode === "all" - ? headerHeightAll[isSubmitting] - : headerHeightDefault[isSubmitting]; return ( <> <Meta /> @@ -41,19 +35,14 @@ const Layout = () => { flexDirection="column" color={color[colorMode]} > - <Flex px={2} flex="1 1 auto" flexGrow={0} flexDirection="column"> - <Header - isSubmitting={isSubmitting} - handleFormReset={handleFormReset} - height={headerHeight} - /> + <Flex px={2} flex="0 1 auto" flexDirection="column"> + <Header isSubmitting={isSubmitting} handleFormReset={handleFormReset} /> </Flex> <Flex px={2} py={0} w="100%" as="main" - mt={headerHeight} flex="1 1 auto" textAlign="center" alignItems="center" diff --git a/hyperglass/ui/components/Title.js b/hyperglass/ui/components/Title.js index 29adef1..feeb651 100644 --- a/hyperglass/ui/components/Title.js +++ b/hyperglass/ui/components/Title.js @@ -11,9 +11,9 @@ const subtitleAnimation = { animate: { opacity: 1, scale: 1 }, exit: { opacity: 0, scale: 0.3 } }; - const titleSize = { true: "2xl", false: "lg" }; const titleMargin = { true: 2, false: 0 }; +const textAlignment = { false: ["right", "center"], true: ["left", "center"] }; const TitleOnly = ({ text, showSubtitle }) => ( <Heading as="h1" mb={titleMargin[showSubtitle]} size={titleSize[showSubtitle]}> @@ -31,8 +31,6 @@ const SubtitleOnly = React.forwardRef(({ text, mediaSize, size = "md", ...props const AnimatedSubtitle = motion.custom(SubtitleOnly); -const textAlignment = { false: ["right", "center"], true: ["left", "center"] }; - const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => ( <Stack spacing={2} maxW="100%" textAlign={textAlignment[showSubtitle]} {...props}> <Textfit mode="single" max={20}> @@ -50,16 +48,16 @@ const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => ( </Stack> ); -const Logo = ({ text, logo }) => { +const Logo = ({ text, logo, showSubtitle }) => { const { colorMode } = useColorMode(); const logoColor = { light: logo.dark, dark: logo.light }; const logoPath = logoColor[colorMode]; return <Image src={logoPath} alt={text.title} width={logo.width ?? "auto"} />; }; -const LogoSubtitle = ({ text, logo, showSubtitle }) => ( +const LogoSubtitle = ({ text, logo, showSubtitle, mediaSize }) => ( <> - <Logo text={text} logo={logo} /> + <Logo text={text} logo={logo} showSubtitle={showSubtitle} mediaSize={mediaSize} /> <AnimatePresence> {showSubtitle && ( <AnimatedSubtitle mt={2} text={text.subtitle} {...subtitleAnimation} /> @@ -70,17 +68,15 @@ const LogoSubtitle = ({ text, logo, showSubtitle }) => ( const All = ({ text, logo, mediaSize, showSubtitle }) => ( <> - <Logo text={text} logo={logo} /> + <Logo text={text} logo={logo} showSubtitle={showSubtitle} /> <TextOnly mediaSize={mediaSize} showSubtitle={showSubtitle} mt={2} text={text} /> </> ); const modeMap = { text_only: TextOnly, logo_only: Logo, logo_subtitle: LogoSubtitle, all: All }; -const widthMap = { - text_only: "100%", - logo_only: ["90%", "90%", "25%", "25%"], - logo_subtitle: ["90%", "90%", "25%", "25%"], - all: ["90%", "90%", "25%", "25%"] +const justifyMap = { + true: ["flex-end", "center", "center", "center"], + false: ["flex-start", "center", "center", "center"] }; export default React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => { @@ -97,7 +93,7 @@ export default React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => { _focus={{ boxShadow: "none" }} _hover={{ textDecoration: "none" }} px={0} - maxW={widthMap[titleMode]} + justifyContent={justifyMap[isSubmitting]} {...props} > <MatchedMode