chore: remove usage of styled-jsx
This commit is contained in:
@ -16,96 +16,88 @@ export const UserProfile: React.FC<UserProfileProps> = (props) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='relative flex h-full flex-col items-center justify-center'>
|
||||
<div className='transition'>
|
||||
<div className='max-w-[1000px] px-12'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<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'>
|
||||
<Image
|
||||
quality={100}
|
||||
className='rounded-full'
|
||||
src={
|
||||
user.logo != null
|
||||
? user.logo
|
||||
: '/images/data/user-default.png'
|
||||
}
|
||||
alt='Profil Picture'
|
||||
draggable='false'
|
||||
height={125}
|
||||
width={125}
|
||||
/>
|
||||
<div className='relative flex h-full flex-col items-center justify-center'>
|
||||
<div className='transition'>
|
||||
<div className='max-w-[1000px] px-12'>
|
||||
<div className='flex items-center justify-between'>
|
||||
<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'>
|
||||
<Image
|
||||
quality={100}
|
||||
className='rounded-full'
|
||||
src={
|
||||
user.logo != null
|
||||
? user.logo
|
||||
: '/images/data/user-default.png'
|
||||
}
|
||||
alt='Profil Picture'
|
||||
draggable='false'
|
||||
height={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 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}
|
||||
<div className='my-2 text-left'>
|
||||
{user.email != null && (
|
||||
<p className='font-bold'>
|
||||
Email:{' '}
|
||||
<a
|
||||
href={`mailto:${user.email}`}
|
||||
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
|
||||
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')}
|
||||
)}
|
||||
{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>
|
||||
</div>
|
||||
<div className='my-2 text-left'>
|
||||
{user.email != null && (
|
||||
<p className='font-bold'>
|
||||
Email:{' '}
|
||||
<a
|
||||
href={`mailto:${user.email}`}
|
||||
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>
|
||||
)}
|
||||
{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>
|
||||
)}
|
||||
{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>
|
||||
{user.biography != null && (
|
||||
<div className='mt-7 text-center'>
|
||||
<p>{user.biography}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{user.biography != null && (
|
||||
<div className='mt-7 text-center'>
|
||||
<p>{user.biography}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx global>{`
|
||||
#application-page-content {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -1,54 +1,45 @@
|
||||
import useTranslation from 'next-translate/useTranslation'
|
||||
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
|
||||
message: string
|
||||
}
|
||||
|
||||
export const ErrorPage: React.FC<ErrorPageProps> = (props) => {
|
||||
const { message, statusCode } = props
|
||||
const { message, statusCode, version } = props
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className='my-6 text-4xl font-semibold'>
|
||||
{t('errors:error')}{' '}
|
||||
<span
|
||||
className='text-green-800 dark:text-green-400'
|
||||
data-cy='status-code'
|
||||
>
|
||||
{statusCode}
|
||||
</span>
|
||||
</h1>
|
||||
<p className='text-center text-lg'>
|
||||
{message}{' '}
|
||||
<Link
|
||||
href='/'
|
||||
className='text-green-800 hover:underline dark:text-green-400'
|
||||
>
|
||||
{t('errors:return-to-home-page')}
|
||||
</Link>
|
||||
</p>
|
||||
|
||||
<style jsx global>
|
||||
{`
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-width: 100vw;
|
||||
flex: 1;
|
||||
}
|
||||
#__next {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-top: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div className='flex h-screen flex-col pt-0'>
|
||||
<Header />
|
||||
<main className='flex min-w-full flex-1 flex-col items-center justify-center'>
|
||||
<h1 className='my-6 text-4xl font-semibold'>
|
||||
{t('errors:error')}{' '}
|
||||
<span
|
||||
className='text-green-800 dark:text-green-400'
|
||||
data-cy='status-code'
|
||||
>
|
||||
{statusCode}
|
||||
</span>
|
||||
</h1>
|
||||
<p className='text-center text-lg'>
|
||||
{message}{' '}
|
||||
<Link
|
||||
href='/'
|
||||
className='text-green-800 hover:underline dark:text-green-400'
|
||||
>
|
||||
{t('errors:return-to-home-page')}
|
||||
</Link>
|
||||
</p>
|
||||
</main>
|
||||
<Footer version={version} />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
78
components/Header/SwitchTheme.tsx
Normal file
78
components/Header/SwitchTheme.tsx
Normal 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>
|
||||
)
|
||||
}
|
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
@ -1 +0,0 @@
|
||||
export * from './SwitchTheme'
|
@ -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>
|
||||
</>
|
||||
)
|
||||
}
|
@ -35,60 +35,46 @@ export const Input: React.FC<InputProps> = (props) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-col'>
|
||||
<div
|
||||
className={classNames('mt-6 mb-2 flex justify-between', className)}
|
||||
>
|
||||
<label className='pl-1' htmlFor={name}>
|
||||
{label}
|
||||
</label>
|
||||
{type === 'password' && showForgotPassword ? (
|
||||
<Link
|
||||
href='/authentication/forgot-password'
|
||||
className='text-center font-headline text-xs text-green-800 hover:underline dark:text-green-400 sm:text-sm'
|
||||
data-cy='forgot-password-link'
|
||||
>
|
||||
{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 className='flex flex-col'>
|
||||
<div className={classNames('mt-6 mb-2 flex justify-between', className)}>
|
||||
<label className='pl-1' htmlFor={name}>
|
||||
{label}
|
||||
</label>
|
||||
{type === 'password' && showForgotPassword ? (
|
||||
<Link
|
||||
href='/authentication/forgot-password'
|
||||
className='text-center font-headline text-xs text-green-800 hover:underline dark:text-green-400 sm:text-sm'
|
||||
data-cy='forgot-password-link'
|
||||
>
|
||||
{t('authentication:forgot-password')}
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.password-eye {
|
||||
top: 12px;
|
||||
right: 16px;
|
||||
z-index: 1;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-image: url('/images/svg/icons/input/${inputType}.svg');
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</>
|
||||
<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}
|
||||
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>
|
||||
)
|
||||
}
|
||||
|
39
components/design/Loader/Loader.module.css
Normal file
39
components/design/Loader/Loader.module.css
Normal 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;
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import styles from './Loader.module.css'
|
||||
|
||||
export interface LoaderProps {
|
||||
width?: number
|
||||
height?: number
|
||||
@ -9,10 +11,14 @@ export const Loader: React.FC<LoaderProps> = (props) => {
|
||||
|
||||
return (
|
||||
<div className={props.className}>
|
||||
<div data-cy='progress-spinner' className='progress-spinner'>
|
||||
<svg className='progress-spinner-svg' viewBox='25 25 50 50'>
|
||||
<div
|
||||
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
|
||||
className='progress-spinner-circle'
|
||||
className={styles.progressSpinnerCircle}
|
||||
cx='50'
|
||||
cy='50'
|
||||
r='20'
|
||||
@ -22,60 +28,6 @@ export const Loader: React.FC<LoaderProps> = (props) => {
|
||||
/>
|
||||
</svg>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -3,6 +3,7 @@ import Image from 'next/image'
|
||||
import classNames from 'clsx'
|
||||
|
||||
import type { ProviderOAuth } from '../../../models/OAuth'
|
||||
import styles from './SocialMediaButton.module.css'
|
||||
|
||||
export type SocialMedia = ProviderOAuth
|
||||
|
||||
@ -52,27 +53,21 @@ export const SocialMediaButton: React.FC<SocialMediaButtonProps> = (props) => {
|
||||
}, [socialMedia])
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
{...rest}
|
||||
className={classNames(className, 'button', givenClassName)}
|
||||
>
|
||||
<SocialMediaChildren socialMedia={socialMedia} />
|
||||
</button>
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.button {
|
||||
background: ${socialMediaColor};
|
||||
color: ${socialMedia === 'Google' ? '#000' : '#fff'};
|
||||
border: ${socialMedia === 'Google' ? '1px solid #000' : 'none'};
|
||||
}
|
||||
.button:focus {
|
||||
box-shadow: 0 0 0 2px #27b05e;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</>
|
||||
<button
|
||||
{...rest}
|
||||
style={{ background: socialMediaColor }}
|
||||
className={classNames(
|
||||
className,
|
||||
styles.button,
|
||||
{
|
||||
[styles.buttonGoogle]: socialMedia === 'Google',
|
||||
[styles.buttonMedia]: socialMedia !== 'Google'
|
||||
},
|
||||
givenClassName
|
||||
)}
|
||||
>
|
||||
<SocialMediaChildren socialMedia={socialMedia} />
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
@ -88,23 +83,20 @@ export const SocialMediaLink: React.FC<SocialMediaLinkProps> = (props) => {
|
||||
}, [socialMedia])
|
||||
|
||||
return (
|
||||
<>
|
||||
<a {...rest} className={classNames(className, 'link', givenClassName)}>
|
||||
<SocialMediaChildren socialMedia={socialMedia} />
|
||||
</a>
|
||||
|
||||
<style jsx>
|
||||
{`
|
||||
.link {
|
||||
background: ${socialMediaColor};
|
||||
color: ${socialMedia === 'Google' ? '#000' : '#fff'};
|
||||
border: ${socialMedia === 'Google' ? '1px solid #000' : 'none'};
|
||||
}
|
||||
.link:focus {
|
||||
box-shadow: 0 0 0 2px #27b05e;
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
</>
|
||||
<a
|
||||
{...rest}
|
||||
style={{ background: socialMediaColor }}
|
||||
className={classNames(
|
||||
className,
|
||||
styles.button,
|
||||
{
|
||||
[styles.buttonGoogle]: socialMedia === 'Google',
|
||||
[styles.buttonMedia]: socialMedia !== 'Google'
|
||||
},
|
||||
givenClassName
|
||||
)}
|
||||
>
|
||||
<SocialMediaChildren socialMedia={socialMedia} />
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
Reference in New Issue
Block a user