chore: remove usage of styled-jsx

This commit is contained in:
Divlo 2022-12-13 22:31:32 +01:00
parent e8a9ce4e69
commit 67a1699102
No known key found for this signature in database
GPG Key ID: 8F9478F220CE65E9
23 changed files with 345 additions and 454 deletions

View File

@ -10,8 +10,6 @@
"editorconfig.editorconfig", "editorconfig.editorconfig",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"divlo.vscode-styled-jsx-syntax",
"divlo.vscode-styled-jsx-languageserver",
"bradlc.vscode-tailwindcss", "bradlc.vscode-tailwindcss",
"mikestead.dotenv", "mikestead.dotenv",
"davidanson.vscode-markdownlint", "davidanson.vscode-markdownlint",

View File

@ -3,8 +3,6 @@
"editorconfig.editorconfig", "editorconfig.editorconfig",
"esbenp.prettier-vscode", "esbenp.prettier-vscode",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"divlo.vscode-styled-jsx-syntax",
"divlo.vscode-styled-jsx-languageserver",
"bradlc.vscode-tailwindcss", "bradlc.vscode-tailwindcss",
"mikestead.dotenv", "mikestead.dotenv",
"davidanson.vscode-markdownlint", "davidanson.vscode-markdownlint",

View File

@ -16,96 +16,88 @@ export const UserProfile: React.FC<UserProfileProps> = (props) => {
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<> <div className='relative flex h-full flex-col items-center justify-center'>
<div className='relative flex h-full flex-col items-center justify-center'> <div className='transition'>
<div className='transition'> <div className='max-w-[1000px] px-12'>
<div className='max-w-[1000px] px-12'> <div className='flex items-center justify-between'>
<div className='flex items-center justify-between'> <div className='flex w-max flex-col items-center gap-7 md:flex-row'>
<div className='flex w-max flex-col items-center gap-7 md:flex-row'> <div className='relative flex items-center justify-center overflow-hidden rounded-full shadow-lg transition-all'>
<div className='relative flex items-center justify-center overflow-hidden rounded-full shadow-lg transition-all'> <Image
<Image quality={100}
quality={100} className='rounded-full'
className='rounded-full' src={
src={ user.logo != null
user.logo != null ? user.logo
? user.logo : '/images/data/user-default.png'
: '/images/data/user-default.png' }
} alt='Profil Picture'
alt='Profil Picture' draggable='false'
draggable='false' height={125}
height={125} width={125}
width={125} />
/> </div>
<div className='ml-10 flex flex-col'>
<div className='mb-2 flex items-center'>
<p
className='space text-dark text-3xl font-bold tracking-wide dark:text-white'
data-cy='user-name'
>
{user.name}
</p>
<p
className='ml-8 select-none text-sm tracking-widest text-white opacity-40'
data-cy='user-createdAt'
>
{date.format(new Date(user.createdAt), 'DD/MM/YYYY')}
</p>
</div> </div>
<div className='ml-10 flex flex-col'> <div className='my-2 text-left'>
<div className='mb-2 flex items-center'> {user.email != null && (
<p <p className='font-bold'>
className='space text-dark text-3xl font-bold tracking-wide dark:text-white' Email:{' '}
data-cy='user-name' <a
> href={`mailto:${user.email}`}
{user.name} target='_blank'
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-1px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
rel='noreferrer'
data-cy='user-email'
>
{user.email}
</a>
</p> </p>
<p )}
className='ml-8 select-none text-sm tracking-widest text-white opacity-40' {user.website != null && (
data-cy='user-createdAt' <p className='font-bold'>
> {t('application:website')}:{' '}
{date.format(new Date(user.createdAt), 'DD/MM/YYYY')} <a
target='_blank'
rel='noreferrer'
href={user.website}
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-2px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
>
{user.website}
</a>
</p> </p>
</div> )}
<div className='my-2 text-left'> {user.status != null && (
{user.email != null && ( <p className='flex font-bold'>
<p className='font-bold'> {t('application:status')}:{' '}
Email:{' '} <span className='ml-2 font-normal tracking-wide'>
<a {user.status}
href={`mailto:${user.email}`} </span>
target='_blank' </p>
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-1px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white' )}
rel='noreferrer'
data-cy='user-email'
>
{user.email}
</a>
</p>
)}
{user.website != null && (
<p className='font-bold'>
{t('application:website')}:{' '}
<a
target='_blank'
rel='noreferrer'
href={user.website}
className='relative ml-2 font-normal tracking-wide no-underline opacity-80 transition-all after:absolute after:left-0 after:bottom-[-2px] after:h-[1px] after:w-0 after:bg-black after:transition-all hover:opacity-100 hover:after:w-full dark:after:bg-white'
>
{user.website}
</a>
</p>
)}
{user.status != null && (
<p className='flex font-bold'>
{t('application:status')}:{' '}
<span className='ml-2 font-normal tracking-wide'>
{user.status}
</span>
</p>
)}
</div>
</div> </div>
</div> </div>
</div> </div>
{user.biography != null && (
<div className='mt-7 text-center'>
<p>{user.biography}</p>
</div>
)}
</div> </div>
{user.biography != null && (
<div className='mt-7 text-center'>
<p>{user.biography}</p>
</div>
)}
</div> </div>
</div> </div>
</div>
<style jsx global>{`
#application-page-content {
overflow-x: hidden;
}
`}</style>
</>
) )
} }

View File

@ -1,54 +1,45 @@
import useTranslation from 'next-translate/useTranslation' import useTranslation from 'next-translate/useTranslation'
import Link from 'next/link' import Link from 'next/link'
export interface ErrorPageProps { import type { FooterProps } from './Footer'
import { Footer } from './Footer'
import { Header } from './Header'
export interface ErrorPageProps extends FooterProps {
statusCode: number statusCode: number
message: string message: string
} }
export const ErrorPage: React.FC<ErrorPageProps> = (props) => { export const ErrorPage: React.FC<ErrorPageProps> = (props) => {
const { message, statusCode } = props const { message, statusCode, version } = props
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<> <>
<h1 className='my-6 text-4xl font-semibold'> <div className='flex h-screen flex-col pt-0'>
{t('errors:error')}{' '} <Header />
<span <main className='flex min-w-full flex-1 flex-col items-center justify-center'>
className='text-green-800 dark:text-green-400' <h1 className='my-6 text-4xl font-semibold'>
data-cy='status-code' {t('errors:error')}{' '}
> <span
{statusCode} className='text-green-800 dark:text-green-400'
</span> data-cy='status-code'
</h1> >
<p className='text-center text-lg'> {statusCode}
{message}{' '} </span>
<Link </h1>
href='/' <p className='text-center text-lg'>
className='text-green-800 hover:underline dark:text-green-400' {message}{' '}
> <Link
{t('errors:return-to-home-page')} href='/'
</Link> className='text-green-800 hover:underline dark:text-green-400'
</p> >
{t('errors:return-to-home-page')}
<style jsx global> </Link>
{` </p>
main { </main>
display: flex; <Footer version={version} />
flex-direction: column; </div>
justify-content: center;
align-items: center;
min-width: 100vw;
flex: 1;
}
#__next {
display: flex;
flex-direction: column;
padding-top: 0;
height: 100vh;
}
`}
</style>
</> </>
) )
} }

View File

@ -0,0 +1,78 @@
import { useEffect, useState } from 'react'
import classNames from 'clsx'
import { useTheme } from 'next-themes'
export const SwitchTheme: React.FC = () => {
const [mounted, setMounted] = useState(false)
const { theme, setTheme } = useTheme()
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}
const handleClick = (): void => {
setTheme(theme === 'dark' ? 'light' : 'dark')
}
return (
<div
className='flex items-center'
data-cy='switch-theme-click'
onClick={handleClick}
>
<div className='relative inline-block cursor-pointer touch-pan-x select-none border-0 bg-transparent p-0'>
<div className='h-[24px] w-[50px] rounded-[30px] bg-[#4d4d4d] p-0 text-white transition-all duration-200 ease-in-out'>
<div
data-cy='switch-theme-dark'
className={classNames(
'absolute top-0 bottom-0 left-[8px] mt-auto mb-auto h-[10px] w-[14px] leading-[0] transition-opacity duration-[250ms] ease-in-out',
{
'opacity-100': theme === 'dark',
'opacity-0': theme === 'light'
}
)}
>
<span className='relative flex h-[10px] w-[10px] items-center justify-center'>
🌜
</span>
</div>
<div
data-cy='switch-theme-light'
className={classNames(
'absolute right-[10px] top-0 bottom-0 mt-auto mb-auto h-[10px] w-[10px] leading-[0]',
{
'opacity-100': theme === 'light',
'opacity-0': theme === 'dark'
}
)}
>
<span className='relative flex h-[10px] w-[10px] items-center justify-center'>
🌞
</span>
</div>
</div>
<div
className={classNames(
'absolute top-[1px] box-border h-[22px] w-[22px] rounded-[50%] bg-[#fafafa] text-white transition-all duration-[250ms] ease-in-out',
{
'left-[27px]': theme === 'dark',
'left-0': theme === 'light'
}
)}
style={{ border: '1px solid #4d4d4d' }}
/>
<input
data-cy='switch-theme-input'
type='checkbox'
aria-label='Dark mode toggle'
className='absolute m-[-1px] h-[1px] w-[1px] overflow-hidden border-0 p-0'
defaultChecked
/>
</div>
</div>
)
}

View File

@ -1,126 +0,0 @@
import { useEffect, useState } from 'react'
import { useTheme } from 'next-themes'
export const SwitchTheme: React.FC = () => {
const [mounted, setMounted] = useState(false)
const { theme, setTheme } = useTheme()
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}
const handleClick = (): void => {
setTheme(theme === 'dark' ? 'light' : 'dark')
}
return (
<>
<div
className='flex items-center'
data-cy='switch-theme-click'
onClick={handleClick}
>
<div className='toggle-theme-button relative inline-block cursor-pointer bg-transparent'>
<div className='toggle-track'>
<div
data-cy='switch-theme-dark'
className='toggle-track-check absolute'
>
<span className='toggle_Dark relative flex items-center justify-center'>
🌜
</span>
</div>
<div
data-cy='switch-theme-light'
className='toggle-track-x absolute'
>
<span className='toggle_Light relative flex items-center justify-center'>
🌞
</span>
</div>
</div>
<div className='toggle-thumb absolute' />
<input
data-cy='switch-theme-input'
type='checkbox'
aria-label='Dark mode toggle'
className='toggle-screenreader-only absolute overflow-hidden'
defaultChecked
/>
</div>
</div>
<style jsx>
{`
.toggle-theme-button {
touch-action: pan-x;
border: 0;
padding: 0;
user-select: none;
}
.toggle-track {
width: 50px;
height: 24px;
padding: 0;
border-radius: 30px;
background-color: #4d4d4d;
transition: all 0.2s ease;
color: #fff;
}
.toggle-track-check {
width: 14px;
height: 10px;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
line-height: 0;
left: 8px;
opacity: ${theme === 'dark' ? 1 : 0};
transition: opacity 0.25s ease;
}
.toggle-track-x {
width: 10px;
height: 10px;
top: 0;
bottom: 0;
margin-top: auto;
margin-bottom: auto;
line-height: 0;
right: 10px;
opacity: ${theme === 'dark' ? 0 : 1};
}
.toggle_Dark,
.toggle_Light {
height: 10px;
width: 10px;
}
.toggle-thumb {
left: ${theme === 'dark' ? '27px' : '0px'};
width: 22px;
height: 22px;
border: 1px solid #4d4d4d;
border-radius: 50%;
background-color: #fafafa;
box-sizing: border-box;
transition: all 0.25s ease;
top: 1px;
color: #fff;
}
.toggle-screenreader-only {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
padding: 0;
width: 1px;
}
`}
</style>
</>
)
}

View File

@ -1 +0,0 @@
export * from './SwitchTheme'

View File

@ -1,20 +0,0 @@
export const ScrollableBody: React.FC<React.PropsWithChildren<{}>> = (
props
) => {
const { children } = props
return (
<>
{children}
<style jsx global>{`
body {
scrollbar-width: thin;
scrollbar-color: var(--scroll-bar-color) var(--scroll-bar-bg-color);
z-index: 1000;
height: calc(100vh - 64px);
overflow-y: auto;
}
`}</style>
</>
)
}

View File

@ -35,60 +35,46 @@ export const Input: React.FC<InputProps> = (props) => {
} }
return ( return (
<> <div className='flex flex-col'>
<div className='flex flex-col'> <div className={classNames('mt-6 mb-2 flex justify-between', className)}>
<div <label className='pl-1' htmlFor={name}>
className={classNames('mt-6 mb-2 flex justify-between', className)} {label}
> </label>
<label className='pl-1' htmlFor={name}> {type === 'password' && showForgotPassword ? (
{label} <Link
</label> href='/authentication/forgot-password'
{type === 'password' && showForgotPassword ? ( className='text-center font-headline text-xs text-green-800 hover:underline dark:text-green-400 sm:text-sm'
<Link data-cy='forgot-password-link'
href='/authentication/forgot-password' >
className='text-center font-headline text-xs text-green-800 hover:underline dark:text-green-400 sm:text-sm' {t('authentication:forgot-password')}
data-cy='forgot-password-link' </Link>
> ) : null}
{t('authentication:forgot-password')}
</Link>
) : null}
</div>
<div className='relative mt-0'>
<input
data-cy={`input-${name ?? 'name'}`}
className='h-11 w-full rounded-lg border border-transparent bg-[#f1f1f1] px-3 font-paragraph leading-10 text-[#2a2a2a] caret-green-600 focus:border focus:shadow-green focus:outline-none'
{...rest}
id={name}
name={name}
type={inputType}
/>
{type === 'password' && (
<div
data-cy='password-eye'
onClick={handlePassword}
className='password-eye absolute cursor-pointer bg-[#f1f1f1] bg-cover'
/>
)}
<FormState
id={`error-${name ?? 'input'}`}
state={error == null ? 'idle' : 'error'}
message={error}
/>
</div>
</div> </div>
<div className='relative mt-0'>
<style jsx> <input
{` data-cy={`input-${name ?? 'name'}`}
.password-eye { className='h-11 w-full rounded-lg border border-transparent bg-[#f1f1f1] px-3 font-paragraph leading-10 text-[#2a2a2a] caret-green-600 focus:border focus:shadow-green focus:outline-none'
top: 12px; {...rest}
right: 16px; id={name}
z-index: 1; name={name}
width: 20px; type={inputType}
height: 20px; />
background-image: url('/images/svg/icons/input/${inputType}.svg'); {type === 'password' && (
} <div
`} data-cy='password-eye'
</style> onClick={handlePassword}
</> style={{
backgroundImage: `url('/images/svg/icons/input/${inputType}.svg')`
}}
className='absolute top-3 right-4 z-10 h-5 w-5 cursor-pointer bg-[#f1f1f1] bg-cover'
/>
)}
<FormState
id={`error-${name ?? 'input'}`}
state={error == null ? 'idle' : 'error'}
message={error}
/>
</div>
</div>
) )
} }

View File

@ -0,0 +1,39 @@
@keyframes progressSpinnerRotate {
100% {
transform: rotate(360deg);
}
}
@keyframes progressSpinnerDash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35px;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124px;
}
}
.progressSpinnerSvg {
animation: progressSpinnerRotate 2s linear infinite;
height: 100%;
transform-origin: center center;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.progressSpinnerCircle {
stroke-dasharray: 89, 200;
stroke-dashoffset: 0;
stroke: #27b05e;
animation: progressSpinnerDash 1.5s ease-in-out infinite;
stroke-linecap: round;
}

View File

@ -1,3 +1,5 @@
import styles from './Loader.module.css'
export interface LoaderProps { export interface LoaderProps {
width?: number width?: number
height?: number height?: number
@ -9,10 +11,14 @@ export const Loader: React.FC<LoaderProps> = (props) => {
return ( return (
<div className={props.className}> <div className={props.className}>
<div data-cy='progress-spinner' className='progress-spinner'> <div
<svg className='progress-spinner-svg' viewBox='25 25 50 50'> data-cy='progress-spinner'
className='relative my-0 mx-auto before:block before:pt-[100%] before:content-none'
style={{ width: `${width}px`, height: `${height}px` }}
>
<svg className={styles.progressSpinnerSvg} viewBox='25 25 50 50'>
<circle <circle
className='progress-spinner-circle' className={styles.progressSpinnerCircle}
cx='50' cx='50'
cy='50' cy='50'
r='20' r='20'
@ -22,60 +28,6 @@ export const Loader: React.FC<LoaderProps> = (props) => {
/> />
</svg> </svg>
</div> </div>
<style jsx>
{`
.progress-spinner {
position: relative;
margin: 0 auto;
width: ${width}px;
height: ${height}px;
}
.progress-spinner::before {
content: '';
display: block;
padding-top: 100%;
}
.progress-spinner-svg {
animation: progress-spinner-rotate 2s linear infinite;
height: 100%;
transform-origin: center center;
width: 100%;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
.progress-spinner-circle {
stroke-dasharray: 89, 200;
stroke-dashoffset: 0;
stroke: #27b05e;
animation: progress-spinner-dash 1.5s ease-in-out infinite;
stroke-linecap: round;
}
@keyframes progress-spinner-rotate {
100% {
transform: rotate(360deg);
}
}
@keyframes progress-spinner-dash {
0% {
stroke-dasharray: 1, 200;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -35px;
}
100% {
stroke-dasharray: 89, 200;
stroke-dashoffset: -124px;
}
}
`}
</style>
</div> </div>
) )
} }

View File

@ -0,0 +1,11 @@
.buttonGoogle {
color: #000;
border: 1px solid #000;
}
.buttonMedia {
color: #fff;
border: none;
}
.button:focus {
box-shadow: 0 0 0 2px #27b05e;
}

View File

@ -3,6 +3,7 @@ import Image from 'next/image'
import classNames from 'clsx' import classNames from 'clsx'
import type { ProviderOAuth } from '../../../models/OAuth' import type { ProviderOAuth } from '../../../models/OAuth'
import styles from './SocialMediaButton.module.css'
export type SocialMedia = ProviderOAuth export type SocialMedia = ProviderOAuth
@ -52,27 +53,21 @@ export const SocialMediaButton: React.FC<SocialMediaButtonProps> = (props) => {
}, [socialMedia]) }, [socialMedia])
return ( return (
<> <button
<button {...rest}
{...rest} style={{ background: socialMediaColor }}
className={classNames(className, 'button', givenClassName)} className={classNames(
> className,
<SocialMediaChildren socialMedia={socialMedia} /> styles.button,
</button> {
[styles.buttonGoogle]: socialMedia === 'Google',
<style jsx> [styles.buttonMedia]: socialMedia !== 'Google'
{` },
.button { givenClassName
background: ${socialMediaColor}; )}
color: ${socialMedia === 'Google' ? '#000' : '#fff'}; >
border: ${socialMedia === 'Google' ? '1px solid #000' : 'none'}; <SocialMediaChildren socialMedia={socialMedia} />
} </button>
.button:focus {
box-shadow: 0 0 0 2px #27b05e;
}
`}
</style>
</>
) )
} }
@ -88,23 +83,20 @@ export const SocialMediaLink: React.FC<SocialMediaLinkProps> = (props) => {
}, [socialMedia]) }, [socialMedia])
return ( return (
<> <a
<a {...rest} className={classNames(className, 'link', givenClassName)}> {...rest}
<SocialMediaChildren socialMedia={socialMedia} /> style={{ background: socialMediaColor }}
</a> className={classNames(
className,
<style jsx> styles.button,
{` {
.link { [styles.buttonGoogle]: socialMedia === 'Google',
background: ${socialMediaColor}; [styles.buttonMedia]: socialMedia !== 'Google'
color: ${socialMedia === 'Google' ? '#000' : '#fff'}; },
border: ${socialMedia === 'Google' ? '1px solid #000' : 'none'}; givenClassName
} )}
.link:focus { >
box-shadow: 0 0 0 2px #27b05e; <SocialMediaChildren socialMedia={socialMedia} />
} </a>
`}
</style>
</>
) )
} }

View File

@ -19,9 +19,7 @@ let server: Mockttp | null = null
export default defineConfig({ export default defineConfig({
fixturesFolder: false, fixturesFolder: false,
video: false, video: false,
downloadsFolder: undefined,
screenshotOnRunFailure: false, screenshotOnRunFailure: false,
e2e: { e2e: {
baseUrl: 'http://127.0.0.1:3000', baseUrl: 'http://127.0.0.1:3000',
supportFile: false, supportFile: false,
@ -62,7 +60,6 @@ export default defineConfig({
return config return config
} }
}, },
component: { component: {
devServer: { devServer: {
framework: 'next', framework: 'next',

View File

@ -3,9 +3,7 @@ import useTranslation from 'next-translate/useTranslation'
import { ErrorPage } from '../components/ErrorPage' import { ErrorPage } from '../components/ErrorPage'
import { Head } from '../components/Head' import { Head } from '../components/Head'
import { Header } from '../components/Header'
import type { FooterProps } from '../components/Footer' import type { FooterProps } from '../components/Footer'
import { Footer } from '../components/Footer'
const Error404: NextPage<FooterProps> = (props) => { const Error404: NextPage<FooterProps> = (props) => {
const { t } = useTranslation() const { t } = useTranslation()
@ -14,12 +12,11 @@ const Error404: NextPage<FooterProps> = (props) => {
return ( return (
<> <>
<Head title='Thream | 404' /> <Head title='Thream | 404' />
<ErrorPage
<Header /> statusCode={404}
<main className='flex flex-col md:mx-auto md:max-w-4xl lg:max-w-7xl'> message={t('errors:page-not-found')}
<ErrorPage statusCode={404} message={t('errors:page-not-found')} /> version={version}
</main> />
<Footer version={version} />
</> </>
) )
} }

View File

@ -5,7 +5,6 @@ import { ErrorPage } from '../components/ErrorPage'
import { Head } from '../components/Head' import { Head } from '../components/Head'
import { Header } from '../components/Header' import { Header } from '../components/Header'
import type { FooterProps } from '../components/Footer' import type { FooterProps } from '../components/Footer'
import { Footer } from '../components/Footer'
const Error500: NextPage<FooterProps> = (props) => { const Error500: NextPage<FooterProps> = (props) => {
const { t } = useTranslation() const { t } = useTranslation()
@ -16,10 +15,11 @@ const Error500: NextPage<FooterProps> = (props) => {
<Head title='Thream | 500' /> <Head title='Thream | 500' />
<Header /> <Header />
<main className='flex flex-col md:mx-auto md:max-w-4xl lg:max-w-7xl'> <ErrorPage
<ErrorPage statusCode={500} message={t('errors:server-error')} /> statusCode={500}
</main> message={t('errors:server-error')}
<Footer version={version} /> version={version}
/>
</> </>
) )
} }

View File

@ -15,7 +15,6 @@ import { Input } from '../../components/design/Input'
import { Button } from '../../components/design/Button' import { Button } from '../../components/design/Button'
import { FormState } from '../../components/design/FormState' import { FormState } from '../../components/design/FormState'
import { authenticationFromServerSide } from '../../tools/authentication' import { authenticationFromServerSide } from '../../tools/authentication'
import { ScrollableBody } from '../../components/ScrollableBody'
import { userSchema } from '../../models/User' import { userSchema } from '../../models/User'
import { api } from '../../tools/api' import { api } from '../../tools/api'
import { useFormTranslation } from '../../hooks/useFormTranslation' import { useFormTranslation } from '../../hooks/useFormTranslation'
@ -60,7 +59,7 @@ const ForgotPassword: NextPage<FooterProps> = (props) => {
} }
return ( return (
<ScrollableBody> <>
<Head title={`Thream | ${t('authentication:forgot-password')}`} /> <Head title={`Thream | ${t('authentication:forgot-password')}`} />
<Header /> <Header />
<Main> <Main>
@ -86,7 +85,7 @@ const ForgotPassword: NextPage<FooterProps> = (props) => {
/> />
</Main> </Main>
<Footer version={version} /> <Footer version={version} />
</ScrollableBody> </>
) )
} }

View File

@ -15,7 +15,6 @@ import { Input } from '../../components/design/Input'
import { Button } from '../../components/design/Button' import { Button } from '../../components/design/Button'
import { authenticationFromServerSide } from '../../tools/authentication' import { authenticationFromServerSide } from '../../tools/authentication'
import { AuthenticationForm } from '../../components/Authentication' import { AuthenticationForm } from '../../components/Authentication'
import { ScrollableBody } from '../../components/ScrollableBody'
import { api } from '../../tools/api' import { api } from '../../tools/api'
import { userSchema } from '../../models/User' import { userSchema } from '../../models/User'
import { useFormTranslation } from '../../hooks/useFormTranslation' import { useFormTranslation } from '../../hooks/useFormTranslation'
@ -55,7 +54,7 @@ const ResetPassword: NextPage<FooterProps> = (props) => {
} }
return ( return (
<ScrollableBody> <>
<Head title={`Thream | ${t('authentication:reset-password')}`} /> <Head title={`Thream | ${t('authentication:reset-password')}`} />
<Header /> <Header />
<Main> <Main>
@ -81,7 +80,7 @@ const ResetPassword: NextPage<FooterProps> = (props) => {
/> />
</Main> </Main>
<Footer version={version} /> <Footer version={version} />
</ScrollableBody> </>
) )
} }

View File

@ -7,19 +7,18 @@ import { Header } from '../../components/Header'
import type { FooterProps } from '../../components/Footer' import type { FooterProps } from '../../components/Footer'
import { Footer } from '../../components/Footer' import { Footer } from '../../components/Footer'
import { authenticationFromServerSide } from '../../tools/authentication' import { authenticationFromServerSide } from '../../tools/authentication'
import { ScrollableBody } from '../../components/ScrollableBody'
const Signin: NextPage<FooterProps> = (props) => { const Signin: NextPage<FooterProps> = (props) => {
const { version } = props const { version } = props
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<ScrollableBody> <>
<Head title={`Thream | ${t('authentication:signin')}`} /> <Head title={`Thream | ${t('authentication:signin')}`} />
<Header /> <Header />
<Authentication mode='signin' /> <Authentication mode='signin' />
<Footer version={version} /> <Footer version={version} />
</ScrollableBody> </>
) )
} }

View File

@ -7,19 +7,18 @@ import { Header } from '../../components/Header'
import type { FooterProps } from '../../components/Footer' import type { FooterProps } from '../../components/Footer'
import { Footer } from '../../components/Footer' import { Footer } from '../../components/Footer'
import { authenticationFromServerSide } from '../../tools/authentication' import { authenticationFromServerSide } from '../../tools/authentication'
import { ScrollableBody } from '../../components/ScrollableBody'
const Signup: NextPage<FooterProps> = (props) => { const Signup: NextPage<FooterProps> = (props) => {
const { version } = props const { version } = props
const { t } = useTranslation() const { t } = useTranslation()
return ( return (
<ScrollableBody> <>
<Head title={`Thream | ${t('authentication:signup')}`} /> <Head title={`Thream | ${t('authentication:signup')}`} />
<Header /> <Header />
<Authentication mode='signup' /> <Authentication mode='signup' />
<Footer version={version} /> <Footer version={version} />
</ScrollableBody> </>
) )
} }

View File

@ -11,14 +11,13 @@ import type { FooterProps } from '../components/Footer'
import { Footer } from '../components/Footer' import { Footer } from '../components/Footer'
import { SocialMediaLink } from '../components/design/SocialMediaButton' import { SocialMediaLink } from '../components/design/SocialMediaButton'
import { ButtonLink } from '../components/design/Button' import { ButtonLink } from '../components/design/Button'
import { ScrollableBody } from '../components/ScrollableBody'
const Home: NextPage<FooterProps> = (props) => { const Home: NextPage<FooterProps> = (props) => {
const { t } = useTranslation() const { t } = useTranslation()
const { version } = props const { version } = props
return ( return (
<ScrollableBody> <>
<Head /> <Head />
<Header /> <Header />
<Main> <Main>
@ -71,7 +70,7 @@ const Home: NextPage<FooterProps> = (props) => {
</div> </div>
</Main> </Main>
<Footer version={version} /> <Footer version={version} />
</ScrollableBody> </>
) )
} }

View File

@ -12,9 +12,18 @@
@apply flex h-screen flex-col; @apply flex h-screen flex-col;
} }
#application-page-content {
overflow-x: hidden;
}
body { body {
@apply bg-white font-headline text-black dark:bg-black dark:text-white; @apply bg-white font-headline text-black dark:bg-black dark:text-white;
overflow: hidden; overflow: hidden;
scrollbar-width: thin;
scrollbar-color: var(--scroll-bar-color) var(--scroll-bar-bg-color);
z-index: 1000;
height: calc(100vh - 64px);
overflow-y: auto;
} }
.h-full-without-header { .h-full-without-header {

View File

@ -1,4 +1,5 @@
module.exports = { /** @type {import('tailwindcss').Config} */
const tailwindConfig = {
content: [ content: [
'./pages/**/*.{js,ts,jsx,tsx}', './pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}' './components/**/*.{js,ts,jsx,tsx}'
@ -31,3 +32,5 @@ module.exports = {
}, },
plugins: [] plugins: []
} }
module.exports = tailwindConfig