mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
137 lines
3.5 KiB
JavaScript
137 lines
3.5 KiB
JavaScript
import React from "react";
|
|
import { Button, Heading, Image, Stack, useColorMode } from "@chakra-ui/core";
|
|
import { Textfit } from "react-textfit";
|
|
import { motion, AnimatePresence } from "framer-motion";
|
|
import useConfig from "~/components/HyperglassProvider";
|
|
import useMedia from "~/components/MediaProvider";
|
|
|
|
const subtitleAnimation = {
|
|
transition: { duration: 0.2, type: "tween" },
|
|
initial: { opacity: 1, scale: 1 },
|
|
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]}
|
|
>
|
|
<Textfit mode="single">{text}</Textfit>
|
|
</Heading>
|
|
);
|
|
|
|
const SubtitleOnly = React.forwardRef(
|
|
({ text, mediaSize, size = "md", ...props }, ref) => (
|
|
<Heading ref={ref} as="h3" size={size} {...props}>
|
|
<Textfit mode="single" max={mediaSize === "sm" ? 13 : 25}>
|
|
{text}
|
|
</Textfit>
|
|
</Heading>
|
|
)
|
|
);
|
|
|
|
const AnimatedSubtitle = motion.custom(SubtitleOnly);
|
|
|
|
const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => (
|
|
<Stack
|
|
spacing={2}
|
|
maxW="100%"
|
|
textAlign={textAlignment[showSubtitle]}
|
|
{...props}
|
|
>
|
|
<Textfit mode="single" max={20}>
|
|
<TitleOnly text={text.title} showSubtitle={showSubtitle} />
|
|
</Textfit>
|
|
<AnimatePresence>
|
|
{showSubtitle && (
|
|
<AnimatedSubtitle
|
|
text={text.subtitle}
|
|
mediaSize={mediaSize}
|
|
{...subtitleAnimation}
|
|
/>
|
|
)}
|
|
</AnimatePresence>
|
|
</Stack>
|
|
);
|
|
|
|
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, mediaSize }) => (
|
|
<>
|
|
<Logo
|
|
text={text}
|
|
logo={logo}
|
|
showSubtitle={showSubtitle}
|
|
mediaSize={mediaSize}
|
|
/>
|
|
<AnimatePresence>
|
|
{showSubtitle && (
|
|
<AnimatedSubtitle mt={6} text={text.subtitle} {...subtitleAnimation} />
|
|
)}
|
|
</AnimatePresence>
|
|
</>
|
|
);
|
|
|
|
const All = ({ text, logo, mediaSize, showSubtitle }) => (
|
|
<>
|
|
<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 justifyMap = {
|
|
true: ["flex-end", "center", "center", "center"],
|
|
false: ["flex-start", "center", "center", "center"]
|
|
};
|
|
|
|
const Title = React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
|
const { web } = useConfig();
|
|
const { mediaSize } = useMedia();
|
|
const titleMode = web.text.title_mode;
|
|
const MatchedMode = modeMap[titleMode];
|
|
return (
|
|
<Button
|
|
ref={ref}
|
|
variant="link"
|
|
onClick={onClick}
|
|
flexWrap="wrap"
|
|
_focus={{ boxShadow: "none" }}
|
|
_hover={{ textDecoration: "none" }}
|
|
px={0}
|
|
justifyContent={justifyMap[isSubmitting]}
|
|
{...props}
|
|
>
|
|
<MatchedMode
|
|
mediaSize={mediaSize}
|
|
showSubtitle={!isSubmitting}
|
|
text={web.text}
|
|
logo={web.logo}
|
|
/>
|
|
</Button>
|
|
);
|
|
});
|
|
|
|
Title.displayName = "Title";
|
|
export default Title;
|