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

improve footer layout [skip ci]

This commit is contained in:
checktheroads
2020-12-29 02:07:42 -07:00
parent 4961d1dd78
commit 7cb445d9e7
8 changed files with 138 additions and 77 deletions

View File

@@ -1,24 +1,32 @@
import { Button, Menu, MenuButton, MenuList } from '@chakra-ui/react';
import { Markdown } from '~/components';
import { useColorValue, useBreakpointValue } from '~/context';
import { useOpposingColor } from '~/hooks';
import type { TFooterButton } from './types';
export const FooterButton = (props: TFooterButton) => {
const { content, title, side, ...rest } = props;
const placement = side === 'left' ? 'top-end' : side === 'right' ? 'top-start' : undefined;
const placement = side === 'left' ? 'top' : side === 'right' ? 'top-start' : undefined;
const bg = useColorValue('white', 'gray.900');
const color = useOpposingColor(bg);
const size = useBreakpointValue({ base: 'xs', lg: 'sm' });
return (
<Menu placement={placement}>
<MenuButton
as={Button}
size="xs"
size={size}
variant="ghost"
aria-label={typeof title === 'string' ? title : undefined}>
{title}
</MenuButton>
<MenuList
bg={bg}
boxShadow="2xl"
color={color}
px={6}
py={4}
textAlign={side}
textAlign="left"
mx={{ base: 1, lg: 2 }}
maxW={{ base: '100vw', lg: '50vw' }}
{...rest}>

View File

@@ -1,7 +1,7 @@
import dynamic from 'next/dynamic';
import { Button, Flex, Link } from '@chakra-ui/react';
import { If } from '~/components';
import { useConfig, useColorValue } from '~/context';
import { Button, Flex, Link, HStack, useToken } from '@chakra-ui/react';
import { If, ColorModeToggle } from '~/components';
import { useConfig, useMobile, useColorValue, useBreakpointValue } from '~/context';
import { useStrf } from '~/hooks';
import { FooterButton } from './button';
@@ -16,41 +16,45 @@ export const Footer = () => {
const extUrl = useStrf(web.external_link.url, { primary_asn }) ?? '/';
const size = useBreakpointValue({ base: useToken('sizes', 4), lg: useToken('sizes', 6) });
const btnSize = useBreakpointValue({ base: 'xs', lg: 'sm' });
const isMobile = useMobile();
return (
<Flex
<HStack
px={6}
py={4}
w="100%"
zIndex={1}
as="footer"
bg={footerBg}
flexWrap="wrap"
textAlign="center"
alignItems="center"
color={footerColor}
py={{ base: 4, lg: 2 }}
justifyContent="space-between">
spacing={{ base: 8, lg: 6 }}
justifyContent={{ base: 'center', lg: 'space-between' }}>
<If c={web.terms.enable}>
<FooterButton side="left" content={content.terms} title={web.terms.title} />
</If>
<If c={web.help_menu.enable}>
<FooterButton side="left" content={content.help_menu} title={web.help_menu.title} />
</If>
<Flex p={0} flexGrow={0} flexShrink={0} maxWidth="100%" flexBasis="auto" marginRight="auto" />
<If c={web.credit.enable}>
<FooterButton side="right" content={content.credit} title={<CodeIcon />} />
</If>
<If c={web.external_link.enable}>
<Button
size="xs"
as={Link}
isExternal
href={extUrl}
size={btnSize}
variant="ghost"
rightIcon={<ExtIcon />}
aria-label={web.external_link.title}>
{web.external_link.title}
</Button>
</If>
</Flex>
{!isMobile && <Flex p={0} flex="0 0 auto" maxWidth="100%" mr="auto" />}
<If c={web.credit.enable}>
<FooterButton side="right" content={content.credit} title={<CodeIcon />} />
</If>
<ColorModeToggle size={size} />
</HStack>
);
};

View File

@@ -1,44 +1,43 @@
import { forwardRef } from 'react';
import dynamic from 'next/dynamic';
import { Button, Icon } from '@chakra-ui/react';
import { Button, Icon, Tooltip } from '@chakra-ui/react';
import { If } from '~/components';
import { useColorMode, useColorValue } from '~/context';
import { useColorMode, useColorValue, useBreakpointValue } from '~/context';
import { useOpposingColor } from '~/hooks';
import type { TColorModeToggle } from './types';
const Sun = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiSun));
const Moon = dynamic<MeronexIcon>(() => import('@meronex/icons/hi').then(i => i.HiMoon));
const outlineColor = { dark: 'primary.300', light: 'primary.600' };
export const ColorModeToggle = forwardRef<HTMLButtonElement, TColorModeToggle>((props, ref) => {
const { size = '1.5rem', ...rest } = props;
const { colorMode, toggleColorMode } = useColorMode();
const bg = useColorValue('primary.500', 'yellow.300');
const color = useOpposingColor(bg);
const label = useColorValue('Switch to dark mode', 'Switch to light mode');
const btnSize = useBreakpointValue({ base: 'xs', lg: 'sm' });
return (
<Button
ref={ref}
aria-label={label}
title={label}
onClick={toggleColorMode}
variant="ghost"
borderWidth="1px"
borderColor="transparent"
_hover={{
backgroundColor: 'unset',
borderColor: outlineColor[colorMode],
}}
color="currentColor"
px={4}
{...rest}>
<If c={colorMode === 'light'}>
<Icon as={Moon} boxSize={size} />
</If>
<If c={colorMode === 'dark'}>
<Icon as={Sun} boxSize={size} />
</If>
</Button>
<Tooltip hasArrow placement="top-end" label={label} bg={bg} color={color}>
<Button
ref={ref}
size={btnSize}
title={label}
variant="ghost"
aria-label={label}
_hover={{ color: bg }}
color="currentColor"
onClick={toggleColorMode}
{...rest}>
<If c={colorMode === 'light'}>
<Icon as={Moon} boxSize={size} />
</If>
<If c={colorMode === 'dark'}>
<Icon as={Sun} boxSize={size} />
</If>
</Button>
</Tooltip>
);
});

View File

@@ -1,50 +1,48 @@
import dynamic from 'next/dynamic';
import {
IconButton,
Modal,
ScaleFade,
ModalBody,
IconButton,
ModalHeader,
ModalOverlay,
ModalContent,
ModalHeader,
ModalBody,
ModalCloseButton,
useDisclosure,
ModalCloseButton,
} from '@chakra-ui/react';
import { motion, AnimatePresence } from 'framer-motion';
import { Markdown } from '~/components';
import { useColorValue } from '~/context';
import { isQueryContent } from '~/types';
import type { THelpModal } from './types';
const Info = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiInfo));
export const HelpModal = (props: THelpModal) => {
const { item, name, ...rest } = props;
const { visible, item, name, ...rest } = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const bg = useColorValue('whiteFaded.50', 'blackFaded.800');
const color = useColorValue('black', 'white');
if (!isQueryContent(item)) {
return null;
}
return (
<>
<AnimatePresence>
<motion.div
transition={{ duration: 0.2 }}
exit={{ opacity: 0, scale: 0.3 }}
animate={{ opacity: 1, scale: 1 }}
initial={{ opacity: 0, scale: 0.3 }}>
<IconButton
mb={1}
ml={1}
minH={3}
minW={3}
size="md"
variant="link"
icon={<Info />}
onClick={onOpen}
colorScheme="blue"
aria-label={`${name}_help`}
/>
</motion.div>
</AnimatePresence>
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ScaleFade in={visible} unmountOnExit>
<IconButton
mb={1}
ml={1}
minH={3}
minW={3}
size="md"
variant="link"
icon={<Info />}
onClick={onOpen}
colorScheme="blue"
aria-label={`${name}_help`}
/>
</ScaleFade>
<Modal isOpen={isOpen} onClose={onClose} size="xl" motionPreset="slideInRight">
<ModalOverlay />
<ModalContent bg={bg} color={color} py={4} borderRadius="md" {...rest}>
<ModalHeader>{item.params.title}</ModalHeader>

View File

@@ -2,6 +2,7 @@ import type { ModalContentProps } from '@chakra-ui/react';
import type { TQueryContent, TQueryFields } from '~/types';
export interface THelpModal extends ModalContentProps {
item: TQueryContent;
item: TQueryContent | null;
name: TQueryFields;
visible: boolean;
}

View File

@@ -1,8 +1,9 @@
import { useRef } from 'react';
import { Flex } from '@chakra-ui/react';
import { useConfig, useColorValue } from '~/context';
import { If, Debugger, Greeting, Footer, Header } from '~/components';
import { useConfig, useColorValue } from '~/context';
import { useLGState } from '~/hooks';
import { ResetButton } from './resetButton';
import type { TFrame } from './types';
@@ -23,10 +24,15 @@ export const Frame = (props: TFrame) => {
return (
<>
<Flex bg={bg} w="100%" color={color} flexDir="column" minHeight="100vh" ref={containerRef}>
<Flex px={2} flex="0 1 auto" flexDirection="column">
<Header resetForm={handleReset} />
</Flex>
<Flex
bg={bg}
w="100%"
id="__hyperglass"
color={color}
flexDir="column"
minHeight="100vh"
ref={containerRef}>
<Header resetForm={handleReset} />
<Flex
px={2}
py={0}
@@ -43,6 +49,7 @@ export const Frame = (props: TFrame) => {
<If c={developer_mode}>
<Debugger />
</If>
<ResetButton developerMode={developer_mode} resetForm={handleReset} />
</Flex>
<Greeting />
</>

View File

@@ -0,0 +1,39 @@
import dynamic from 'next/dynamic';
import { Box, Flex, Icon, IconButton, Slide } from '@chakra-ui/react';
import { useColorValue } from '~/context';
import { useLGState, useOpposingColor } from '~/hooks';
import type { TResetButton } from './types';
const LeftArrow = dynamic<MeronexIcon>(() => import('@meronex/icons/fa').then(i => i.FaAngleLeft));
export const ResetButton = (props: TResetButton) => {
const { developerMode, resetForm, ...rest } = props;
const { isSubmitting } = useLGState();
const bg = useColorValue('primary.500', 'primary.300');
const color = useOpposingColor(bg);
return (
<Slide direction="left" in={isSubmitting.value} unmountOnExit style={{ width: 'auto' }}>
<Box
bg={bg}
left={0}
zIndex={4}
bottom={24}
boxSize={12}
color={color}
position="fixed"
borderRightRadius="md"
mb={developerMode ? 14 : undefined}>
<Flex boxSize="100%" justifyContent="center" alignItems="center" {...rest}>
<IconButton
color="current"
variant="ghost"
aria-label="Reset"
onClick={resetForm}
icon={<Icon as={LeftArrow} boxSize={8} />}
/>
</Flex>
</Box>
</Slide>
);
};

View File

@@ -1,3 +1,8 @@
import type { FlexProps } from '@chakra-ui/react';
export interface TFrame extends FlexProps {}
export interface TResetButton extends FlexProps {
developerMode: boolean;
resetForm(): void;
}