feat: layout
This commit is contained in:
parent
52eee36e4b
commit
075168a5d2
4
NOTE.md
4
NOTE.md
@ -33,5 +33,5 @@
|
||||
# Layout Components
|
||||
|
||||
* Layout
|
||||
* Header
|
||||
* Footer
|
||||
* [x] Header
|
||||
* [x] Footer
|
||||
|
@ -1,11 +1,13 @@
|
||||
import React from 'react';
|
||||
import { BreakpointProvider } from './components/Breakpoint'
|
||||
import { Button } from './components/Button'
|
||||
import { Header } from './components/Layout/Header'
|
||||
import { Footer } from './components/Layout/Footer'
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<BreakpointProvider>
|
||||
<Button>iHealth</Button>
|
||||
<Header showActiveKit showMenu />
|
||||
<Footer />
|
||||
</BreakpointProvider>
|
||||
);
|
||||
}
|
||||
|
11
src/branding/logo.svg
Normal file
11
src/branding/logo.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<svg width="171" height="41" viewBox="0 0 171 41" fill="none" xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<rect width="171" height="41" fill="url(#pattern0)"/>
|
||||
<defs>
|
||||
<pattern id="pattern0" patternContentUnits="objectBoundingBox" width="1" height="1">
|
||||
<use xlink:href="#image0_630_2269" transform="matrix(0.005 0 0 0.0208537 0 -0.0213415)"/>
|
||||
</pattern>
|
||||
<image id="image0_630_2269" width="200" height="50"
|
||||
xlink:href="data:image/png;base64,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"/>
|
||||
</defs>
|
||||
</svg>
|
After Width: | Height: | Size: 4.1 KiB |
@ -1,13 +1,6 @@
|
||||
import React, { FC, PropsWithChildren } from 'react'
|
||||
import { Size, useSize } from './useSize'
|
||||
|
||||
export const breakpointList = {
|
||||
xs: 0,
|
||||
s: 576,
|
||||
m: 768,
|
||||
l: 992,
|
||||
xl: 1200,
|
||||
}
|
||||
import { breakpointList } from '../../theme'
|
||||
|
||||
export interface BreakpointContextProps {
|
||||
size: Size,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useContext } from 'react';
|
||||
import { BreakpointContext } from './BreakpointProvider'
|
||||
import { uaParser } from '../../utils/uaParser'
|
||||
import { currentDeviceType } from '../../utils/uaParser'
|
||||
|
||||
export interface DeviceType {
|
||||
mobile?: boolean;
|
||||
@ -33,8 +33,6 @@ export type BreakpointProps = DeviceType & Breakpoints & OrientationType
|
||||
|
||||
const deviceType = ['mobile', 'tablet', 'desktop']
|
||||
|
||||
const currentDeviceType = ['mobile', 'tablet'].includes(uaParser.device.model || '') ? uaParser.device.model : 'desktop'
|
||||
|
||||
function matchWidth(width: number, min?: number, max?: number): boolean {
|
||||
if (typeof min === 'number' && typeof max === 'number') {
|
||||
return width >= min && width <= max
|
||||
|
155
src/components/Layout/Footer.tsx
Normal file
155
src/components/Layout/Footer.tsx
Normal file
@ -0,0 +1,155 @@
|
||||
import React, { FC, PropsWithChildren } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Breakpoint } from '../Breakpoint'
|
||||
import { ButtonText } from '../Typography'
|
||||
|
||||
const CompanyLink = {
|
||||
title: 'iHealth Labs Inc',
|
||||
href: 'https://ihealthlabs.com/'
|
||||
}
|
||||
|
||||
const FooterLinks = [{
|
||||
title: 'FAQs',
|
||||
href: 'https://ihealthlabs.com/products/checkmesafe-home-collection-kit-C2-detail',
|
||||
}, {
|
||||
title: 'Contact Us',
|
||||
href: 'mailto:support@ihealthlabs.com'
|
||||
}, {
|
||||
title: 'Terms of Use',
|
||||
href: 'https://www.iHealthCheckMeSafe.com/TermsOfUse'
|
||||
}, {
|
||||
title: 'Privacy Policy',
|
||||
href: 'https://www.iHealthCheckMSafe.com/PrivacyPolicy'
|
||||
}]
|
||||
|
||||
const Links = styled.div`
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
font-weight: 500;
|
||||
`
|
||||
const LinkItem = styled.div`
|
||||
padding: 0 10px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 1px;
|
||||
height: 14px;
|
||||
border-left: 1px solid #000;
|
||||
}
|
||||
|
||||
> a {
|
||||
color: ${props => props.theme.brandPrimary};
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&:last-child:after {
|
||||
display: none;
|
||||
}
|
||||
`
|
||||
const CopyRight = styled(ButtonText)`
|
||||
padding-left: 3px;
|
||||
line-height: 16px;
|
||||
|
||||
> a {
|
||||
color: inherit;
|
||||
text-decoration: underline;
|
||||
|
||||
&:hover, &:focus, &:visited {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const LargeFooter = styled.footer`
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
align-items: center;
|
||||
padding: 47px 28px 41px;
|
||||
`
|
||||
const TinyFooter = styled.footer`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding: 12px 0 10px 0;
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
width: 73px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: ${props => props.theme.brandPrimary};
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 50%;
|
||||
transform: translate3d(-50%, 0, 0);
|
||||
}
|
||||
|
||||
${Links} {
|
||||
font-size: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
${LinkItem} {
|
||||
color: #5B5B5B;
|
||||
padding: 0 8px;
|
||||
|
||||
&:after {
|
||||
top: -2px;
|
||||
height: 20px;
|
||||
border-color: #8F9296;
|
||||
transform: scale(0.5);
|
||||
}
|
||||
|
||||
> a {
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
${CopyRight} {
|
||||
line-height: 1;
|
||||
padding-left: 0;
|
||||
color: #5B5B5B;
|
||||
}
|
||||
`
|
||||
const StyledFooter: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<>
|
||||
<Breakpoint s down>
|
||||
<TinyFooter>
|
||||
{children}
|
||||
</TinyFooter>
|
||||
</Breakpoint>
|
||||
<Breakpoint s up>
|
||||
<LargeFooter>
|
||||
{children}
|
||||
</LargeFooter>
|
||||
</Breakpoint>
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
export const Footer: FC = () => {
|
||||
return (
|
||||
<StyledFooter>
|
||||
<Links>
|
||||
{
|
||||
FooterLinks.map((link, index) => (
|
||||
<LinkItem key={index}>
|
||||
<a target="_blank" rel="noopener noreferrer" href={link.href}>{link.title}</a>
|
||||
</LinkItem>
|
||||
))
|
||||
}
|
||||
</Links>
|
||||
<CopyRight level={2}>
|
||||
© {new Date().getFullYear()}, <a target="_blank" rel="noopener noreferrer"
|
||||
href={CompanyLink.href}>{CompanyLink.title}</a> All rights
|
||||
reserved.
|
||||
</CopyRight>
|
||||
</StyledFooter>
|
||||
)
|
||||
}
|
124
src/components/Layout/Header.tsx
Normal file
124
src/components/Layout/Header.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
import React, { FC } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import Icon from '@ant-design/icons'
|
||||
import { Button } from '../Button'
|
||||
import { Breakpoint } from '../Breakpoint'
|
||||
import { ReactComponent as Cart } from '../../icons/cart.svg'
|
||||
import { ReactComponent as Menu } from '../../icons/menu.svg'
|
||||
import { ReactComponent as Logo } from '../../branding/logo.svg'
|
||||
|
||||
const StyledHeader = styled.header`
|
||||
display: flex;
|
||||
position: relative;
|
||||
padding: 55px 40px 52px;
|
||||
justify-content: flex-start;
|
||||
border-bottom: 3px solid ${props => props.theme.brandPrimary};
|
||||
|
||||
${props => props.theme.breakpoints.down('s')} {
|
||||
padding: 20px 25px;
|
||||
justify-content: center;
|
||||
border-bottom: 2px solid #000022;
|
||||
}
|
||||
`
|
||||
|
||||
const StyledLogo = styled(Logo)`
|
||||
width: 171px;
|
||||
height: 41px;
|
||||
|
||||
${props => props.theme.breakpoints.down('s')} {
|
||||
width: 111px;
|
||||
height: 24px;
|
||||
}
|
||||
`
|
||||
|
||||
const StyledText = styled.span`
|
||||
padding-left: 4px;
|
||||
display: inline-block;
|
||||
font-weight: 400;
|
||||
vertical-align: middle;
|
||||
`
|
||||
|
||||
const StyledCartWrapper = styled.a`
|
||||
right: 45px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate3d(0, -50%, 0);
|
||||
color: #000;
|
||||
font-size: 20px;
|
||||
line-height: 128%;
|
||||
|
||||
|
||||
&:hover, &:focus, &:visited {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.anticon {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
${props => props.theme.breakpoints.down('s')} {
|
||||
right: 20px;
|
||||
|
||||
.anticon {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
${StyledText} {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
position: absolute;
|
||||
right: 156px;
|
||||
top: 45px;
|
||||
width: 216px;
|
||||
height: 58px;
|
||||
|
||||
${props => props.theme.breakpoints.down(600)} {
|
||||
width: 160px;
|
||||
}
|
||||
`
|
||||
|
||||
export interface HeaderProps {
|
||||
showMenu?: boolean
|
||||
onClickMenu?: () => void
|
||||
showActiveKit?: boolean;
|
||||
activeKitHref?: string
|
||||
}
|
||||
|
||||
const StyledMenuIcon = styled(Icon)`
|
||||
font-size: 22px;
|
||||
left: 20px;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translate3d(0, -50%, 0);
|
||||
`
|
||||
|
||||
export const Header: FC<HeaderProps> = ({
|
||||
showMenu,
|
||||
onClickMenu,
|
||||
showActiveKit,
|
||||
activeKitHref
|
||||
}) => {
|
||||
return (
|
||||
<StyledHeader>
|
||||
{showMenu &&
|
||||
<Breakpoint s down>
|
||||
<StyledMenuIcon component={Menu} onClick={onClickMenu} />
|
||||
</Breakpoint>
|
||||
}
|
||||
<StyledLogo />
|
||||
{showActiveKit &&
|
||||
<Breakpoint s up>
|
||||
<StyledButton href={activeKitHref}>Activate Kit</StyledButton>
|
||||
</Breakpoint>}
|
||||
<StyledCartWrapper target="_blank" rel="noopener noreferrer">
|
||||
<Icon component={Cart} />
|
||||
<StyledText>SHOP</StyledText>
|
||||
</StyledCartWrapper>
|
||||
</StyledHeader>
|
||||
)
|
||||
}
|
3
src/icons/cart.svg
Normal file
3
src/icons/cart.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12 27C12 27.3956 11.8827 27.7822 11.6629 28.1111C11.4432 28.44 11.1308 28.6964 10.7654 28.8478C10.3999 28.9991 9.99778 29.0387 9.60982 28.9616C9.22186 28.8844 8.86549 28.6939 8.58579 28.4142C8.30608 28.1345 8.1156 27.7781 8.03843 27.3902C7.96126 27.0022 8.00087 26.6001 8.15224 26.2346C8.30362 25.8692 8.55996 25.5568 8.88886 25.3371C9.21776 25.1173 9.60444 25 10 25C10.5304 25 11.0391 25.2107 11.4142 25.5858C11.7893 25.9609 12 26.4696 12 27ZM23 25C22.6044 25 22.2178 25.1173 21.8889 25.3371C21.56 25.5568 21.3036 25.8692 21.1522 26.2346C21.0009 26.6001 20.9613 27.0022 21.0384 27.3902C21.1156 27.7781 21.3061 28.1345 21.5858 28.4142C21.8655 28.6939 22.2219 28.8844 22.6098 28.9616C22.9978 29.0387 23.3999 28.9991 23.7654 28.8478C24.1308 28.6964 24.4432 28.44 24.6629 28.1111C24.8827 27.7822 25 27.3956 25 27C25 26.4696 24.7893 25.9609 24.4142 25.5858C24.0391 25.2107 23.5304 25 23 25ZM28.9562 9.29375L25.39 20.8825C25.2032 21.4968 24.8234 22.0346 24.3068 22.416C23.7903 22.7975 23.1646 23.0022 22.5225 23H10.5087C9.85747 22.9976 9.2245 22.7842 8.70463 22.3919C8.18477 21.9996 7.80598 21.4494 7.625 20.8237L3.1025 5H1C0.734784 5 0.48043 4.89464 0.292893 4.70711C0.105357 4.51957 0 4.26522 0 4C0 3.73478 0.105357 3.48043 0.292893 3.29289C0.48043 3.10536 0.734784 3 1 3H3.1025C3.53676 3.00144 3.95888 3.14349 4.30567 3.40487C4.65246 3.66626 4.90526 4.03293 5.02625 4.45L6.04 8H28C28.1565 7.99994 28.3108 8.03661 28.4505 8.10706C28.5903 8.17751 28.7115 8.27976 28.8045 8.40561C28.8976 8.53145 28.9597 8.67737 28.9861 8.83163C29.0124 8.98588 29.0022 9.14417 28.9562 9.29375ZM26.6462 10H6.61125L9.5475 20.275C9.60724 20.4839 9.73336 20.6676 9.90679 20.7984C10.0802 20.9292 10.2915 21 10.5087 21H22.5225C22.7365 21.0001 22.9448 20.9315 23.117 20.8044C23.2891 20.6773 23.4159 20.4983 23.4788 20.2938L26.6462 10Z" fill="black"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
3
src/icons/menu.svg
Normal file
3
src/icons/menu.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 8C4 7.44772 4.44772 7 5 7H27C27.5523 7 28 7.44772 28 8C28 8.55228 27.5523 9 27 9H5C4.44772 9 4 8.55228 4 8ZM4 16C4 15.4477 4.44772 15 5 15H27C27.5523 15 28 15.4477 28 16C28 16.5523 27.5523 17 27 17H5C4.44772 17 4 16.5523 4 16ZM4 24C4 23.4477 4.44772 23 5 23H27C27.5523 23 28 23.4477 28 24C28 24.5523 27.5523 25 27 25H5C4.44772 25 4 24.5523 4 24Z" fill="#000022"/>
|
||||
</svg>
|
After Width: | Height: | Size: 519 B |
@ -2,6 +2,7 @@ import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import { ConfigProvider } from 'antd'
|
||||
import { Theme } from './theme'
|
||||
import { ThemeProvider } from './theme/ThemeProvider'
|
||||
import App from './App';
|
||||
import 'typeface-lato'
|
||||
import 'antd/dist/reset.css';
|
||||
@ -13,7 +14,9 @@ const root = ReactDOM.createRoot(
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<ConfigProvider theme={Theme}>
|
||||
<ThemeProvider>
|
||||
<App />
|
||||
</ThemeProvider>
|
||||
</ConfigProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
1
src/styles/antd.min.css
vendored
Normal file
1
src/styles/antd.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -1,3 +1,8 @@
|
||||
html, body {
|
||||
font-family: Lato, Helvetica, Arial, sans-serif;
|
||||
background: #FDFDFD;
|
||||
}
|
||||
|
||||
.ant-btn:not(.ant-btn-link):not(.ant-btn-text) {
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
@ -181,6 +186,7 @@
|
||||
line-height: 1;
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.ant-form-item {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
32
src/theme/ThemeProvider.tsx
Normal file
32
src/theme/ThemeProvider.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React, { FC, PropsWithChildren } from 'react'
|
||||
import { ThemeProvider as PureThemeProvider } from 'styled-components'
|
||||
import { brandPrimary, breakpointList } from './index'
|
||||
|
||||
|
||||
type BreakpointKey = keyof typeof breakpointList
|
||||
const breakpoints = {
|
||||
up(key: BreakpointKey | number) {
|
||||
return `@media (min-width:${typeof key === 'number' ? key : breakpointList[key]}px)`
|
||||
},
|
||||
down(key: BreakpointKey | number) {
|
||||
return `@media (max-width:${typeof key === 'number' ? key : breakpointList[key]}px)`
|
||||
},
|
||||
}
|
||||
|
||||
declare module 'styled-components' {
|
||||
export interface DefaultTheme {
|
||||
brandPrimary: string;
|
||||
breakpoints: typeof breakpoints
|
||||
}
|
||||
}
|
||||
|
||||
export const ThemeProvider: FC<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<PureThemeProvider
|
||||
theme={{
|
||||
brandPrimary,
|
||||
breakpoints
|
||||
}}
|
||||
>{children}</PureThemeProvider>
|
||||
)
|
||||
}
|
@ -1,6 +1,12 @@
|
||||
import { ThemeConfig } from 'antd'
|
||||
|
||||
const brandPrimary = '#FF5200';
|
||||
export const breakpointList = {
|
||||
xs: 0,
|
||||
s: 500,
|
||||
m: 900,
|
||||
l: 1200,
|
||||
xl: 1536,
|
||||
}
|
||||
export const brandPrimary = '#FF5200';
|
||||
const textPrimary = '#1E1D1F'
|
||||
const textDarker = '#000022'
|
||||
const textLighter = '#8F9296'
|
||||
|
@ -1,3 +1,6 @@
|
||||
import UAParser from 'ua-parser-js'
|
||||
|
||||
export const uaParser = UAParser()
|
||||
|
||||
type DeviceType = 'mobile' | 'tablet' | 'desktop'
|
||||
export const currentDeviceType: DeviceType = ['mobile', 'tablet'].includes(uaParser.device.model || '') ? uaParser.device.model as DeviceType : 'desktop'
|
||||
|
Loading…
Reference in New Issue
Block a user