mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
166 lines
4.4 KiB
TypeScript
166 lines
4.4 KiB
TypeScript
![]() |
import { Flex } from '@chakra-ui/react';
|
||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||
|
import { useColorValue, useConfig, useGlobalState, useBreakpointValue } from '~/context';
|
||
|
import { AnimatedDiv, Title, ResetButton, ColorModeToggle } from '~/components';
|
||
|
import { useBooleanValue } from '~/hooks';
|
||
|
|
||
|
import type { ResponsiveValue } from '@chakra-ui/react';
|
||
|
import type { THeader, TTitleMode } from './types';
|
||
|
|
||
|
const headerTransition = {
|
||
|
type: 'spring',
|
||
|
ease: 'anticipate',
|
||
|
damping: 15,
|
||
|
stiffness: 100,
|
||
|
};
|
||
|
|
||
|
function getWidth(mode: TTitleMode): ResponsiveValue<string> {
|
||
|
let width = '100%' as ResponsiveValue<string>;
|
||
|
|
||
|
switch (mode) {
|
||
|
case 'text_only':
|
||
|
width = '100%';
|
||
|
break;
|
||
|
case 'logo_only':
|
||
|
width = { base: '90%', lg: '50%' };
|
||
|
break;
|
||
|
case 'logo_subtitle':
|
||
|
width = { base: '90%', lg: '50%' };
|
||
|
break;
|
||
|
case 'all':
|
||
|
width = { base: '90%', lg: '50%' };
|
||
|
break;
|
||
|
}
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
export const Header = (props: THeader) => {
|
||
|
const { resetForm, ...rest } = props;
|
||
|
const bg = useColorValue('white', 'black');
|
||
|
|
||
|
const { web } = useConfig();
|
||
|
const { isSubmitting } = useGlobalState();
|
||
|
|
||
|
const mlResetButton = useBooleanValue(isSubmitting.value, { base: 0, md: 2 }, undefined);
|
||
|
const titleHeight = useBooleanValue(isSubmitting.value, undefined, { md: '20vh' });
|
||
|
|
||
|
const titleVariant = useBreakpointValue({
|
||
|
base: {
|
||
|
fullSize: { scale: 1, marginLeft: 0 },
|
||
|
smallLogo: { marginLeft: 'auto' },
|
||
|
smallText: { marginLeft: 'auto' },
|
||
|
},
|
||
|
md: {
|
||
|
fullSize: { scale: 1 },
|
||
|
smallLogo: { scale: 0.5 },
|
||
|
smallText: { scale: 0.8 },
|
||
|
},
|
||
|
lg: {
|
||
|
fullSize: { scale: 1 },
|
||
|
smallLogo: { scale: 0.5 },
|
||
|
smallText: { scale: 0.8 },
|
||
|
},
|
||
|
xl: {
|
||
|
fullSize: { scale: 1 },
|
||
|
smallLogo: { scale: 0.5 },
|
||
|
smallText: { scale: 0.8 },
|
||
|
},
|
||
|
});
|
||
|
|
||
|
const titleJustify = useBooleanValue(
|
||
|
isSubmitting.value,
|
||
|
{ base: 'flex-end', md: 'center' },
|
||
|
{ base: 'flex-start', md: 'center' },
|
||
|
);
|
||
|
const resetButton = (
|
||
|
<AnimatePresence key="resetButton">
|
||
|
<AnimatedDiv
|
||
|
layoutTransition={headerTransition}
|
||
|
initial={{ opacity: 0, x: -50 }}
|
||
|
animate={{ opacity: 1, x: 0, width: 'unset' }}
|
||
|
exit={{ opacity: 0, x: -50 }}
|
||
|
alignItems="center"
|
||
|
mb={{ md: 'auto' }}
|
||
|
ml={mlResetButton}
|
||
|
display={isSubmitting ? 'flex' : 'none'}>
|
||
|
<motion.div>
|
||
|
<ResetButton onClick={resetForm} />
|
||
|
</motion.div>
|
||
|
</AnimatedDiv>
|
||
|
</AnimatePresence>
|
||
|
);
|
||
|
const title = (
|
||
|
<AnimatedDiv
|
||
|
key="title"
|
||
|
px={1}
|
||
|
alignItems={isSubmitting ? 'center' : ['center', 'center', 'flex-end', 'flex-end']}
|
||
|
positionTransition={headerTransition}
|
||
|
initial={{ scale: 0.5 }}
|
||
|
animate={
|
||
|
isSubmitting && web.text.title_mode === 'text_only'
|
||
|
? 'smallText'
|
||
|
: isSubmitting && web.text.title_mode !== 'text_only'
|
||
|
? 'smallLogo'
|
||
|
: 'fullSize'
|
||
|
}
|
||
|
variants={titleVariant}
|
||
|
justifyContent={titleJustify}
|
||
|
mt={[null, isSubmitting ? null : 'auto']}
|
||
|
maxW={getWidth(web.text.title_mode)}
|
||
|
flex="1 0 0"
|
||
|
minH={titleHeight}>
|
||
|
<Title onClick={resetForm} />
|
||
|
</AnimatedDiv>
|
||
|
);
|
||
|
const colorModeToggle = (
|
||
|
<AnimatedDiv
|
||
|
layoutTransition={headerTransition}
|
||
|
key="colorModeToggle"
|
||
|
alignItems="center"
|
||
|
initial={{ opacity: 0 }}
|
||
|
animate={{ opacity: 1 }}
|
||
|
mb={[null, 'auto']}
|
||
|
mr={isSubmitting ? undefined : 2}>
|
||
|
<ColorModeToggle />
|
||
|
</AnimatedDiv>
|
||
|
);
|
||
|
|
||
|
const layout = useBooleanValue(
|
||
|
isSubmitting.value,
|
||
|
{
|
||
|
sm: [resetButton, colorModeToggle, title],
|
||
|
md: [resetButton, title, colorModeToggle],
|
||
|
lg: [resetButton, title, colorModeToggle],
|
||
|
xl: [resetButton, title, colorModeToggle],
|
||
|
},
|
||
|
{
|
||
|
sm: [title, resetButton, colorModeToggle],
|
||
|
md: [resetButton, title, colorModeToggle],
|
||
|
lg: [resetButton, title, colorModeToggle],
|
||
|
xl: [resetButton, title, colorModeToggle],
|
||
|
},
|
||
|
);
|
||
|
|
||
|
return (
|
||
|
<Flex
|
||
|
px={2}
|
||
|
zIndex="4"
|
||
|
as="header"
|
||
|
width="full"
|
||
|
flex="0 1 auto"
|
||
|
bg={bg}
|
||
|
color="gray.500"
|
||
|
{...rest}>
|
||
|
<Flex
|
||
|
w="100%"
|
||
|
mx="auto"
|
||
|
pt={6}
|
||
|
justify="space-between"
|
||
|
flex="1 0 auto"
|
||
|
alignItems={isSubmitting ? 'center' : 'flex-start'}>
|
||
|
{layout}
|
||
|
</Flex>
|
||
|
</Flex>
|
||
|
);
|
||
|
};
|