1
0
mirror of https://github.com/checktheroads/hyperglass synced 2024-05-11 05:55:08 +00:00

144 lines
3.6 KiB
TypeScript
Raw Normal View History

2020-12-29 02:05:28 -07:00
import { Flex, Button, VStack } from '@chakra-ui/react';
import { motion } from 'framer-motion';
import { If } from '~/components';
import { useConfig, useMobile } from '~/context';
import { useBooleanValue, useLGState } from '~/hooks';
import { Logo } from './logo';
import { TitleOnly } from './titleOnly';
import { useHeaderCtx } from './context';
import { SubtitleOnly } from './subtitleOnly';
import type { StackProps } from '@chakra-ui/react';
import type { TTitle, TTitleWrapper, TDWrapper } from './types';
const AnimatedVStack = motion.custom(VStack);
/**
* Title wrapper for mobile devices, breakpoints sm & md.
*/
const MWrapper = (props: StackProps) => <VStack spacing={1} alignItems="flex-start" {...props} />;
/**
* Title wrapper for desktop devices, breakpoints lg & xl.
*/
const DWrapper = (props: TDWrapper) => {
const { showSubtitle } = useHeaderCtx();
return (
<AnimatedVStack
spacing={1}
initial="main"
alignItems="center"
animate={showSubtitle ? 'main' : 'submitting'}
transition={{ damping: 15, type: 'spring', stiffness: 100 }}
variants={{ submitting: { scale: 0.5 }, main: { scale: 1 } }}
{...props}
/>
);
};
/**
* Universal wrapper for title sub-components, which will be different depending on the
* `title_mode` configuration variable.
*/
const TitleWrapper = (props: TDWrapper | StackProps) => {
const isMobile = useMobile();
return (
<>
{isMobile ? <MWrapper {...(props as StackProps)} /> : <DWrapper {...(props as TDWrapper)} />}
</>
);
};
/**
* Title sub-component if `title_mode` is set to `text_only`.
*/
const TextOnly = (props: TTitleWrapper) => {
return (
<TitleWrapper {...props}>
<TitleOnly />
<SubtitleOnly />
</TitleWrapper>
);
};
/**
* Title sub-component if `title_mode` is set to `logo_only`. Renders only the logo.
*/
const LogoOnly = () => (
<TitleWrapper>
<Logo />
</TitleWrapper>
);
/**
* Title sub-component if `title_mode` is set to `logo_subtitle`. Renders the logo with the
* subtitle underneath.
*/
const LogoSubtitle = () => (
<TitleWrapper>
<Logo />
<SubtitleOnly />
</TitleWrapper>
);
/**
* Title sub-component if `title_mode` is set to `all`. Renders the logo, title, and subtitle.
*/
const All = () => (
<TitleWrapper>
<Logo />
<TextOnly mt={2} />
</TitleWrapper>
);
/**
* Title component which renders sub-components based on the `title_mode` configuration variable.
*/
export const Title = (props: TTitle) => {
const { fontSize, ...rest } = props;
const { web } = useConfig();
const titleMode = web.text.title_mode;
const { isSubmitting, resetForm } = useLGState();
const titleHeight = useBooleanValue(isSubmitting.value, undefined, { md: '20vh' });
function handleClick(): void {
isSubmitting.set(false);
resetForm();
}
return (
<Flex
px={0}
flexWrap="wrap"
flexDir="column"
minH={titleHeight}
justifyContent="center"
mt={[null, isSubmitting.value ? null : 'auto']}
{...rest}>
<Button
px={0}
variant="link"
flexWrap="wrap"
flexDir="column"
onClick={handleClick}
_focus={{ boxShadow: 'none' }}
_hover={{ textDecoration: 'none' }}>
<If c={titleMode === 'text_only'}>
<TextOnly />
</If>
<If c={titleMode === 'logo_only'}>
<LogoOnly />
</If>
<If c={titleMode === 'logo_subtitle'}>
<LogoSubtitle />
</If>
<If c={titleMode === 'all'}>
<All />
</If>
</Button>
</Flex>
);
};