mirror of
https://github.com/dsoaress/link-free.git
synced 2026-08-16 22:46:04 +01:00
refactor: imp some components
This commit is contained in:
56
data/data.json
Normal file
56
data/data.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"settings": {
|
||||
"avatar": "/avatar.jpeg",
|
||||
"name": "John Doe",
|
||||
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec euismod, nisl eget aliquam consectetur, nisl nunc aliquet nunc, euismod aliquam nunc nisl euismod.",
|
||||
"font": "baloo",
|
||||
"buttonsSchema": "rounded",
|
||||
"outline": true,
|
||||
"colors": {
|
||||
"texts": "neutral50",
|
||||
"socialLinks": "rose",
|
||||
"buttonLinks": "rose",
|
||||
"background": "neutral700"
|
||||
}
|
||||
},
|
||||
"socialLinks": [
|
||||
{
|
||||
"label": "Email",
|
||||
"href": "1"
|
||||
},
|
||||
{
|
||||
"label": "GitHub",
|
||||
"href": "2"
|
||||
},
|
||||
{
|
||||
"label": "LinkedIn",
|
||||
"href": "3"
|
||||
},
|
||||
{
|
||||
"label": "Dev",
|
||||
"href": "4"
|
||||
},
|
||||
{
|
||||
"label": "Instagram",
|
||||
"href": "5"
|
||||
},
|
||||
{
|
||||
"label": "WhatsApp",
|
||||
"href": "6"
|
||||
}
|
||||
],
|
||||
"buttonLinks": [
|
||||
{
|
||||
"label": "Home",
|
||||
"href": "#"
|
||||
},
|
||||
{
|
||||
"label": "About",
|
||||
"href": "/about"
|
||||
},
|
||||
{
|
||||
"label": "Contact",
|
||||
"href": "/contact"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,11 +1,9 @@
|
||||
import { ImageProps } from 'next/image'
|
||||
|
||||
import { useData } from '../../contexts/DataContext'
|
||||
import { Wrapper } from './styles'
|
||||
|
||||
type AvatarProps = ImageProps & {
|
||||
src?: string
|
||||
}
|
||||
export function Avatar() {
|
||||
const { data } = useData()
|
||||
const { avatar } = data.settings
|
||||
|
||||
export function Avatar({ src, ...rest }: AvatarProps) {
|
||||
return !!src ? <Wrapper src={src} width={84} height={84} quality={100} {...rest} /> : null
|
||||
return !!avatar ? <Wrapper src={avatar} width={84} height={84} quality={100} /> : null
|
||||
}
|
||||
|
||||
@@ -21,19 +21,15 @@ const colorVariantFn = (
|
||||
}
|
||||
})
|
||||
|
||||
const outlineVariantFn = (
|
||||
lightColor: ColorsType,
|
||||
regularColor: ColorsType,
|
||||
darkColor: ColorsType
|
||||
) => ({
|
||||
color: theme.colors[darkColor],
|
||||
const outlineVariantFn = (color: ColorsType) => ({
|
||||
color: theme.colors[color],
|
||||
|
||||
'&:hover': {
|
||||
background: theme.colors[lightColor]
|
||||
background: 'rgba(0, 0, 0, 0.05)'
|
||||
},
|
||||
|
||||
'&:active': {
|
||||
background: theme.colors[regularColor]
|
||||
background: 'rgba(0, 0, 0, 0.1)'
|
||||
}
|
||||
})
|
||||
|
||||
@@ -46,6 +42,7 @@ export const Wrapper = styled('button', {
|
||||
borderWidth: '2.5px',
|
||||
borderStyle: 'solid',
|
||||
fontSize: '1rem',
|
||||
fontWeight: 500,
|
||||
cursor: 'pointer',
|
||||
transition: 'all 0.25s ease-in-out',
|
||||
|
||||
@@ -91,6 +88,18 @@ export const Wrapper = styled('button', {
|
||||
}
|
||||
},
|
||||
|
||||
font: {
|
||||
baloo: {
|
||||
fontFamily: theme.fonts.baloo
|
||||
},
|
||||
montserrat: {
|
||||
fontFamily: theme.fonts.montserrat
|
||||
},
|
||||
roboto: {
|
||||
fontFamily: theme.fonts.roboto
|
||||
}
|
||||
},
|
||||
|
||||
outline: {
|
||||
true: {
|
||||
background: 'transparent'
|
||||
@@ -102,118 +111,119 @@ export const Wrapper = styled('button', {
|
||||
{
|
||||
color: 'slate',
|
||||
outline: true,
|
||||
css: outlineVariantFn('slate50', 'slate100', 'slate600')
|
||||
css: outlineVariantFn('slate600')
|
||||
},
|
||||
{
|
||||
color: 'gray',
|
||||
outline: true,
|
||||
css: outlineVariantFn('gray50', 'gray100', 'gray600')
|
||||
css: outlineVariantFn('gray600')
|
||||
},
|
||||
{
|
||||
color: 'zinc',
|
||||
outline: true,
|
||||
css: outlineVariantFn('zinc50', 'zinc100', 'zinc600')
|
||||
css: outlineVariantFn('zinc600')
|
||||
},
|
||||
{
|
||||
color: 'neutral',
|
||||
outline: true,
|
||||
css: outlineVariantFn('neutral50', 'neutral100', 'neutral600')
|
||||
css: outlineVariantFn('neutral600')
|
||||
},
|
||||
{
|
||||
color: 'stone',
|
||||
outline: true,
|
||||
css: outlineVariantFn('stone50', 'stone100', 'stone600')
|
||||
css: outlineVariantFn('stone600')
|
||||
},
|
||||
{
|
||||
color: 'red',
|
||||
outline: true,
|
||||
css: outlineVariantFn('red50', 'red100', 'red600')
|
||||
css: outlineVariantFn('red600')
|
||||
},
|
||||
{
|
||||
color: 'orange',
|
||||
outline: true,
|
||||
css: outlineVariantFn('orange50', 'orange100', 'orange600')
|
||||
css: outlineVariantFn('orange600')
|
||||
},
|
||||
{
|
||||
color: 'amber',
|
||||
outline: true,
|
||||
css: outlineVariantFn('amber50', 'amber100', 'amber600')
|
||||
css: outlineVariantFn('amber600')
|
||||
},
|
||||
{
|
||||
color: 'yellow',
|
||||
outline: true,
|
||||
css: outlineVariantFn('yellow50', 'yellow100', 'yellow600')
|
||||
css: outlineVariantFn('yellow600')
|
||||
},
|
||||
{
|
||||
color: 'lime',
|
||||
outline: true,
|
||||
css: outlineVariantFn('lime50', 'lime100', 'lime600')
|
||||
css: outlineVariantFn('lime600')
|
||||
},
|
||||
{
|
||||
color: 'green',
|
||||
outline: true,
|
||||
css: outlineVariantFn('green50', 'green100', 'green600')
|
||||
css: outlineVariantFn('green600')
|
||||
},
|
||||
{
|
||||
color: 'emerald',
|
||||
outline: true,
|
||||
css: outlineVariantFn('emerald50', 'emerald100', 'emerald600')
|
||||
css: outlineVariantFn('emerald600')
|
||||
},
|
||||
{
|
||||
color: 'teal',
|
||||
outline: true,
|
||||
css: outlineVariantFn('teal50', 'teal100', 'teal600')
|
||||
css: outlineVariantFn('teal600')
|
||||
},
|
||||
{
|
||||
color: 'cyan',
|
||||
outline: true,
|
||||
css: outlineVariantFn('cyan50', 'cyan100', 'cyan600')
|
||||
css: outlineVariantFn('cyan600')
|
||||
},
|
||||
{
|
||||
color: 'sky',
|
||||
outline: true,
|
||||
css: outlineVariantFn('sky50', 'sky100', 'sky600')
|
||||
css: outlineVariantFn('sky600')
|
||||
},
|
||||
{
|
||||
color: 'blue',
|
||||
outline: true,
|
||||
css: outlineVariantFn('blue50', 'blue100', 'blue600')
|
||||
css: outlineVariantFn('blue600')
|
||||
},
|
||||
{
|
||||
color: 'indigo',
|
||||
outline: true,
|
||||
css: outlineVariantFn('indigo50', 'indigo100', 'indigo600')
|
||||
css: outlineVariantFn('indigo600')
|
||||
},
|
||||
{
|
||||
color: 'violet',
|
||||
outline: true,
|
||||
css: outlineVariantFn('violet50', 'violet100', 'violet600')
|
||||
css: outlineVariantFn('violet600')
|
||||
},
|
||||
{
|
||||
color: 'purple',
|
||||
outline: true,
|
||||
css: outlineVariantFn('purple50', 'purple100', 'purple600')
|
||||
css: outlineVariantFn('purple600')
|
||||
},
|
||||
{
|
||||
color: 'fuchsia',
|
||||
outline: true,
|
||||
css: outlineVariantFn('fuchsia50', 'fuchsia100', 'fuchsia600')
|
||||
css: outlineVariantFn('fuchsia600')
|
||||
},
|
||||
{
|
||||
color: 'pink',
|
||||
outline: true,
|
||||
css: outlineVariantFn('pink50', 'pink100', 'pink600')
|
||||
css: outlineVariantFn('pink600')
|
||||
},
|
||||
{
|
||||
color: 'rose',
|
||||
outline: true,
|
||||
css: outlineVariantFn('rose50', 'rose100', 'rose600')
|
||||
css: outlineVariantFn('rose600')
|
||||
}
|
||||
],
|
||||
|
||||
defaultVariants: {
|
||||
color: 'teal',
|
||||
schema: 'pill',
|
||||
font: 'roboto',
|
||||
outline: false
|
||||
}
|
||||
})
|
||||
|
||||
34
src/components/Home/index.tsx
Normal file
34
src/components/Home/index.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useData } from '../../contexts/DataContext'
|
||||
import { theme } from '../../styles/stitches.config'
|
||||
import { Avatar } from '../Avatar'
|
||||
import { Button } from '../Button'
|
||||
import { SocialLinks } from '../SocialLinks'
|
||||
import { Content, Description, Name, Wrapper } from './styles'
|
||||
|
||||
export const Home = () => {
|
||||
const { data } = useData()
|
||||
const { colors, buttonsSchema, outline, font, name, description } = data.settings
|
||||
|
||||
return (
|
||||
<Wrapper
|
||||
css={{
|
||||
background: theme.colors[colors.background as keyof typeof theme.colors],
|
||||
color: theme.colors[colors.texts as keyof typeof theme.colors]
|
||||
}}
|
||||
>
|
||||
<Content>
|
||||
<Avatar />
|
||||
<Name>{name}</Name>
|
||||
<SocialLinks />
|
||||
<Description>{description}</Description>
|
||||
{data.buttonLinks?.map(link =>
|
||||
// @ts-ignore
|
||||
// prettier-ignore
|
||||
<Button color={colors.buttonLinks} schema={buttonsSchema} outline={outline} font={font} key={link.href}>
|
||||
{link.label}
|
||||
</Button>
|
||||
)}
|
||||
</Content>
|
||||
</Wrapper>
|
||||
)
|
||||
}
|
||||
29
src/components/Home/styles.ts
Normal file
29
src/components/Home/styles.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { styled } from '../../styles/stitches.config'
|
||||
|
||||
export const Wrapper = styled('main', {
|
||||
width: '100%',
|
||||
height: '100vh'
|
||||
})
|
||||
|
||||
export const Content = styled('div', {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: '1rem',
|
||||
margin: '0 auto',
|
||||
maxWidth: '640px',
|
||||
padding: '2rem 1rem'
|
||||
})
|
||||
|
||||
export const Name = styled('h1', {
|
||||
fontSize: '2rem',
|
||||
fontWeight: 500,
|
||||
margin: 0
|
||||
})
|
||||
|
||||
export const Description = styled('p', {
|
||||
fontSize: '1rem',
|
||||
textAlign: 'center',
|
||||
fontWeight: 400,
|
||||
lineHeight: '1.5'
|
||||
})
|
||||
@@ -7,19 +7,10 @@ import { BsEnvelope as Email } from 'react-icons/bs'
|
||||
import { FaDev as Dev, FaLinkedinIn as LinkedIn } from 'react-icons/fa'
|
||||
import { IconType } from 'react-icons/lib'
|
||||
|
||||
import { useData } from '../../contexts/DataContext'
|
||||
import { Link } from '../Link'
|
||||
import { LinkVariantProps } from '../Link/styles'
|
||||
import { SocialItem, Wrapper } from './styles'
|
||||
|
||||
type SocialLink = {
|
||||
label: string
|
||||
href: string
|
||||
}
|
||||
|
||||
type SocialLinksProps = LinkVariantProps & {
|
||||
socialLinks: SocialLink[]
|
||||
}
|
||||
|
||||
const Icons = {
|
||||
Email,
|
||||
GitHub,
|
||||
@@ -29,10 +20,12 @@ const Icons = {
|
||||
WhatsApp
|
||||
}
|
||||
|
||||
export function SocialLinks({ socialLinks, color }: SocialLinksProps) {
|
||||
export function SocialLinks() {
|
||||
const { data } = useData()
|
||||
|
||||
return (
|
||||
<Wrapper>
|
||||
{socialLinks.map(({ label, href }) => {
|
||||
{data.socialLinks?.map(({ label, href }) => {
|
||||
const Icon: IconType = Icons[label as keyof typeof Icons]
|
||||
return (
|
||||
<SocialItem key={href}>
|
||||
@@ -42,7 +35,7 @@ export function SocialLinks({ socialLinks, color }: SocialLinksProps) {
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
// @ts-ignore
|
||||
color={color}
|
||||
color={data.settings.colors.socialLinks}
|
||||
>
|
||||
<Icon size={22} />
|
||||
</Link>
|
||||
|
||||
24
src/contexts/DataContext.tsx
Normal file
24
src/contexts/DataContext.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { createContext, Dispatch, ReactNode, SetStateAction, useContext, useState } from 'react'
|
||||
|
||||
import initialData from '../../data/data.json'
|
||||
|
||||
type DataType = typeof initialData
|
||||
|
||||
type DataContextType = {
|
||||
data: DataType
|
||||
setData: Dispatch<SetStateAction<DataType>>
|
||||
}
|
||||
|
||||
type DataProviderProps = {
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const DataContext = createContext({} as DataContextType)
|
||||
|
||||
export const DataProvider = ({ children }: DataProviderProps) => {
|
||||
const [data, setData] = useState<DataType>(initialData)
|
||||
|
||||
return <DataContext.Provider value={{ data, setData }}>{children}</DataContext.Provider>
|
||||
}
|
||||
|
||||
export const useData = () => useContext(DataContext)
|
||||
@@ -1,8 +1,13 @@
|
||||
import type { AppProps } from 'next/app'
|
||||
|
||||
import { DataProvider } from '../contexts/DataContext'
|
||||
import { globalStyles } from '../styles/globals'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
globalStyles()
|
||||
return <Component {...pageProps} />
|
||||
return (
|
||||
<DataProvider>
|
||||
<Component {...pageProps} />
|
||||
</DataProvider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import NextDocument, { Head, Html, Main, NextScript } from 'next/document'
|
||||
|
||||
import { fonts, getCssText } from '../styles/stitches.config'
|
||||
import { getCssText } from '../styles/stitches.config'
|
||||
|
||||
export default class Document extends NextDocument {
|
||||
render() {
|
||||
@@ -9,7 +9,10 @@ export default class Document extends NextDocument {
|
||||
<Head>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
||||
<link href={fonts['baloo'].href} rel="stylesheet" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Baloo+Bhaijaan+2:wght@400;500&family=Montserrat:wght@400;500&family=Roboto:wght@400;500&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
|
||||
</Head>
|
||||
<body>
|
||||
|
||||
@@ -1,67 +1,5 @@
|
||||
import { Avatar } from '../components/Avatar'
|
||||
import { Button } from '../components/Button'
|
||||
import { SocialLinks } from '../components/SocialLinks'
|
||||
import { Home } from '../components/Home'
|
||||
|
||||
export default function Home() {
|
||||
const links = [
|
||||
{
|
||||
label: 'Home',
|
||||
href: '#'
|
||||
},
|
||||
{
|
||||
label: 'About',
|
||||
href: '/about'
|
||||
},
|
||||
{
|
||||
label: 'Contact',
|
||||
href: '/contact'
|
||||
}
|
||||
]
|
||||
|
||||
const socialLinks = [
|
||||
{
|
||||
label: 'Email',
|
||||
href: '1'
|
||||
},
|
||||
{
|
||||
label: 'GitHub',
|
||||
href: '2'
|
||||
},
|
||||
{
|
||||
label: 'LinkedIn',
|
||||
href: '3'
|
||||
},
|
||||
{
|
||||
label: 'Dev',
|
||||
href: '4'
|
||||
},
|
||||
{
|
||||
label: 'Instagram',
|
||||
href: '5'
|
||||
},
|
||||
{
|
||||
label: 'WhatsApp',
|
||||
href: '6'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
height: '100vh',
|
||||
gap: '1rem'
|
||||
}}
|
||||
>
|
||||
<Avatar src="/avatar.jpeg" />
|
||||
<SocialLinks socialLinks={socialLinks} color="rose" />
|
||||
{links.map(link => (
|
||||
<Button color="sky" schema="rounded" outline key={link.href}>
|
||||
{link.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
export default function HomePage() {
|
||||
return <Home />
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
export const fonts = {
|
||||
roboto: {
|
||||
href: 'https://fonts.googleapis.com/css2?family=Roboto:wght@500&display=swap',
|
||||
name: "'Roboto', sans-serif"
|
||||
},
|
||||
openSans: {
|
||||
href: 'https://fonts.googleapis.com/css2?family=Open+Sans:wght@500&display=swap',
|
||||
name: "'Open Sans', sans-serif"
|
||||
},
|
||||
poppins: {
|
||||
href: 'https://fonts.googleapis.com/css2?family=Poppins:wght@500&display=swap',
|
||||
name: "'Poppins', sans-serif"
|
||||
},
|
||||
baloo: {
|
||||
href: 'https://fonts.googleapis.com/css2?family=Baloo+Bhaijaan+2:wght@500&display=swap',
|
||||
name: "'Baloo Bhaijaan 2', cursive"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fonts, globalCss } from './stitches.config'
|
||||
import data from '../../data/data.json'
|
||||
import { globalCss, theme } from './stitches.config'
|
||||
|
||||
export const globalStyles = globalCss({
|
||||
'*': {
|
||||
@@ -6,8 +7,7 @@ export const globalStyles = globalCss({
|
||||
padding: 0,
|
||||
boxSizing: 'border-box'
|
||||
},
|
||||
'body, button, a': {
|
||||
fontFamily: fonts['baloo'].name,
|
||||
fontWeight: 500
|
||||
body: {
|
||||
fontFamily: theme.fonts[data.settings.font as keyof typeof theme.fonts]
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { createStitches, VariantProps } from '@stitches/react'
|
||||
|
||||
import { fonts } from './fonts'
|
||||
|
||||
export const { css, styled, globalCss, theme, keyframes, getCssText } = createStitches({
|
||||
theme: {
|
||||
fonts: {
|
||||
baloo: "'Baloo Bhaijaan 2', cursive",
|
||||
montserrat: "'Montserrat', sans-serif",
|
||||
roboto: "'Roboto', sans-serif"
|
||||
},
|
||||
colors: {
|
||||
slate50: '#f8fafc',
|
||||
slate100: '#f1f5f9',
|
||||
@@ -253,4 +256,3 @@ export const { css, styled, globalCss, theme, keyframes, getCssText } = createSt
|
||||
type ColorsType = keyof typeof theme.colors
|
||||
|
||||
export type { ColorsType, VariantProps }
|
||||
export { fonts }
|
||||
|
||||
Reference in New Issue
Block a user