Skip to content

Commit

Permalink
feat: add styled components theme provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Gustavohps10 committed Aug 18, 2024
1 parent 2d2f6d1 commit 517e52b
Show file tree
Hide file tree
Showing 15 changed files with 240 additions and 6 deletions.
5 changes: 4 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@
"extends": [
"@rocketseat/eslint-config/next",
"next/core-web-vitals"
]
],
"rules": {
"@typescript-eslint/no-empty-interface": "off"
}
}
9 changes: 6 additions & 3 deletions next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export', // Outputs a Single-Page Application (SPA).
distDir: './build', // Changes the build output directory to `./dist`.
output: 'export', // Outputs a Single-Page Application (SPA).
distDir: './build', // Changes the build output directory to `./dist`.
compiler: {
styledComponents: true,
},
}

export default nextConfig
export default nextConfig
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
]
},
"dependencies": {
"@sapuris-ui/tokens": "^1.1.0",
"firebase": "^10.4.0",
"next": "14.2.5",
"react": "^18",
Expand Down
17 changes: 17 additions & 0 deletions src/@types/styled.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import 'styled-components'
import { defaultTheme } from '../styles/themes/default'
import { colors } from '@sapuris-ui/tokens'

export type Colors = typeof colors & {
background500: string
background600: string
text500: string
}

type ITheme = typeof defaultTheme & {
colors: Colors
}

declare module 'styled-components' {
export interface DefaultTheme extends ITheme {}
}
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Metadata } from 'next'
import { ThemeWrapper } from '@/lib/theme-wrapper'

export const metadata: Metadata = {
title: 'Portifólio',
Expand All @@ -20,7 +21,7 @@ export default function RootLayout({
<meta name="description" content="Web site created..." />
</head>
<body>
<div id="root">{children}</div>
<ThemeWrapper>{children}</ThemeWrapper>
</body>
</html>
)
Expand Down
10 changes: 9 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Button } from '@/components/button'

export default async function Page() {
const res = await fetch('https://api.github.com/users/Gustavohps10/repos', {
next: { revalidate: 3600 },
Expand All @@ -6,5 +8,11 @@ export default async function Page() {

console.log(data)

return <></>
return (
<>
<Button $outline="outlined" $color="danger">
Test Theme
</Button>
</>
)
}
17 changes: 17 additions & 0 deletions src/components/button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use client'

import React, { ButtonHTMLAttributes } from 'react'
import * as S from './styled'

export type ButtonProps = S.ButtonContainerProps &
ButtonHTMLAttributes<HTMLButtonElement>

export const Button = React.forwardRef<
HTMLButtonElement,
React.PropsWithChildren<ButtonProps>
>(({ children, ...props }: ButtonProps, forwardedRef) => (
<S.ButtonContainer {...props} ref={forwardedRef}>
{children}
</S.ButtonContainer>
))
Button.displayName = 'Button'
65 changes: 65 additions & 0 deletions src/components/button/styled.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import styled, { DefaultTheme, css } from 'styled-components'
import { ButtonProps } from '.'

export interface ButtonContainerProps {
$color?: 'primary' | 'danger'
$outline?: 'filled' | 'outlined'
}

const BUTTON_COLORS = (
theme: DefaultTheme,
color: ButtonContainerProps['$color'] = 'primary',
) =>
({
primary: theme.colors.sapuris500,
danger: theme.colors.wine500,
})[color]

const variantStyles = (
theme: DefaultTheme,
outline: ButtonContainerProps['$outline'] = 'filled',
color: ButtonContainerProps['$color'] = 'primary',
) =>
({
filled: css`
color: ${theme.colors.white};
background: ${BUTTON_COLORS(theme, color)};
border: none;
&:hover {
filter: brightness(85%);
}
`,
outlined: css`
color: ${BUTTON_COLORS(theme, color)};
background: transparent;
border: 1px solid ${BUTTON_COLORS(theme, color)};
&:hover {
color: ${theme.colors.white};
background: ${BUTTON_COLORS(theme, color)};
}
`,
})[outline]

export const ButtonContainer = styled.button<ButtonProps>`
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
border-radius: ${(props) => props.theme.radii.md};
transition: all 0.2s ease;
cursor: pointer;
padding: 1.6rem;
font-weight: bold;
&:disabled {
opacity: 0.7;
cursor: not-allowed;
}
//variants
${({ theme, $outline, $color }) => variantStyles(theme, $outline, $color)}
`
29 changes: 29 additions & 0 deletions src/lib/registry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use client'

import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'

export default function StyledComponentsRegistry({
children,
}: {
children: React.ReactNode
}) {
// Only create stylesheet once with lazy initial state
// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())

useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})

if (typeof window !== 'undefined') return <>{children}</>

return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}
13 changes: 13 additions & 0 deletions src/lib/theme-wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use client'

import { theme } from '@/styles/themes/default'
import StyledComponentsRegistry from './registry'
import { ThemeProvider } from 'styled-components'

export function ThemeWrapper({ children }: { children: React.ReactNode }) {
return (
<StyledComponentsRegistry>
<ThemeProvider theme={theme.light}>{children}</ThemeProvider>
</StyledComponentsRegistry>
)
}
24 changes: 24 additions & 0 deletions src/styles/global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createGlobalStyle } from 'styled-components'

export const GlobalStyle = createGlobalStyle`
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
:focus{
outline: 0;
}
body {
background-color: ${({ theme }) => theme.colors.background600};
color: ${({ theme }) => theme.colors.white};
-webkit-font-smoothing: antialiased;
font-size: 1.6rem;
}
body, input, textarea, button{
font-weight: 400;
}
`
9 changes: 9 additions & 0 deletions src/styles/themes/dark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Colors } from '@/@types/styled'
import { colors } from '@sapuris-ui/tokens'

export const darkTheme: Colors = {
...colors,
background500: '',
background600: '',
text500: '',
}
30 changes: 30 additions & 0 deletions src/styles/themes/default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {
fontSizes,
fontWeights,
fonts,
lineHeights,
radii,
space,
} from '@sapuris-ui/tokens'
import { darkTheme } from './dark'
import { lightTheme } from './light'

export const defaultTheme = {
fontSizes,
fontWeights,
fonts,
lineHeights,
radii,
space,
} as const

export const theme = {
light: {
colors: lightTheme,
...defaultTheme,
},
dark: {
colors: darkTheme,
...defaultTheme,
},
}
9 changes: 9 additions & 0 deletions src/styles/themes/light.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Colors } from '@/@types/styled'
import { colors } from '@sapuris-ui/tokens'

export const lightTheme: Colors = {
...colors,
'background-500': '',
'background-600': '',
'text-500': '',
}
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2478,6 +2478,11 @@
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz#427d5549943a9c6fce808e39ea64dbe60d4047f1"
integrity sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==

"@sapuris-ui/tokens@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@sapuris-ui/tokens/-/tokens-1.1.0.tgz#98e8ecf83911b977055a47f5be22a3e5762b58c7"
integrity sha512-uAgswxaU+4Qm1f7pK+SGso/WrWeBHZaHFgQDQSIoAwovXGlOu0GDj9XJcBm7UzYJOuZMf8yCOGclDrNqUgD3rw==

"@sinclair/typebox@^0.24.1":
version "0.24.51"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f"
Expand Down

0 comments on commit 517e52b

Please sign in to comment.