|
|
|
import clsx from 'clsx'; |
|
import * as React from 'react'; |
|
import { |
|
HiArrowRight, |
|
HiOutlineCreditCard, |
|
HiOutlineDesktopComputer, |
|
HiOutlineDeviceMobile, |
|
HiOutlineShieldCheck, |
|
HiPlus, |
|
} from 'react-icons/hi'; |
|
|
|
import Button from '@/components/buttons/Button'; |
|
import IconButton from '@/components/buttons/IconButton'; |
|
import TextButton from '@/components/buttons/TextButton'; |
|
import Layout from '@/components/layout/Layout'; |
|
import ArrowLink from '@/components/links/ArrowLink'; |
|
import ButtonLink from '@/components/links/ButtonLink'; |
|
import PrimaryLink from '@/components/links/PrimaryLink'; |
|
import UnderlineLink from '@/components/links/UnderlineLink'; |
|
import UnstyledLink from '@/components/links/UnstyledLink'; |
|
import NextImage from '@/components/NextImage'; |
|
import Seo from '@/components/Seo'; |
|
import Skeleton from '@/components/Skeleton'; |
|
|
|
type Color = (typeof colorList)[number]; |
|
|
|
export default function ComponentsPage() { |
|
const [mode, setMode] = React.useState<'dark' | 'light'>('light'); |
|
const [color, setColor] = React.useState<Color>('sky'); |
|
function toggleMode() { |
|
return mode === 'dark' ? setMode('light') : setMode('dark'); |
|
} |
|
|
|
const textColor = mode === 'dark' ? 'text-gray-300' : 'text-gray-600'; |
|
|
|
return ( |
|
<Layout> |
|
<Seo |
|
templateTitle='Components' |
|
description='Pre-built components with awesome default' |
|
/> |
|
|
|
<main> |
|
<section |
|
className={clsx(mode === 'dark' ? 'bg-dark' : 'bg-white', color)} |
|
> |
|
<div |
|
className={clsx( |
|
'layout min-h-screen py-20', |
|
mode === 'dark' ? 'text-white' : 'text-black' |
|
)} |
|
> |
|
<h1>Built-in Components</h1> |
|
<ArrowLink direction='left' className='mt-2' href='/'> |
|
Back to Home |
|
</ArrowLink> |
|
|
|
<div className='mt-8 flex flex-wrap gap-2'> |
|
<Button |
|
onClick={toggleMode} |
|
variant={mode === 'dark' ? 'light' : 'dark'} |
|
> |
|
Set to {mode === 'dark' ? 'light' : 'dark'} |
|
</Button> |
|
{/* <Button onClick={randomize}>Randomize CSS Variable</Button> */} |
|
</div> |
|
|
|
<ol className='mt-8 space-y-6'> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>Customize Colors</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
You can change primary color to any Tailwind CSS colors. See |
|
globals.css to change your color. |
|
</p> |
|
<div className='flex flex-wrap gap-2'> |
|
<select |
|
name='color' |
|
id='color' |
|
value={color} |
|
className={clsx( |
|
'block max-w-xs rounded', |
|
mode === 'dark' |
|
? 'bg-dark border border-gray-600' |
|
: 'border-gray-300 bg-white', |
|
'focus:border-primary-400 focus:ring-primary-400 focus:outline-none focus:ring' |
|
)} |
|
onChange={(e) => setColor(e.target.value as Color)} |
|
> |
|
{colorList.map((c) => ( |
|
<option key={c} value={c}> |
|
{c} |
|
</option> |
|
))} |
|
</select> |
|
<ButtonLink href='https://github.com/theodorusclarence/ts-nextjs-tailwind-starter/blob/main/src/styles/colors.css'> |
|
Check list of colors |
|
</ButtonLink> |
|
</div> |
|
<div className='flex flex-wrap gap-2 text-xs font-medium'> |
|
<div className='bg-primary-50 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
50 |
|
</div> |
|
<div className='bg-primary-100 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
100 |
|
</div> |
|
<div className='bg-primary-200 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
200 |
|
</div> |
|
<div className='bg-primary-300 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
300 |
|
</div> |
|
<div className='bg-primary-400 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
400 |
|
</div> |
|
<div className='bg-primary-500 flex h-10 w-10 items-center justify-center rounded text-black'> |
|
500 |
|
</div> |
|
<div className='bg-primary-600 flex h-10 w-10 items-center justify-center rounded text-white'> |
|
600 |
|
</div> |
|
<div className='bg-primary-700 flex h-10 w-10 items-center justify-center rounded text-white'> |
|
700 |
|
</div> |
|
<div className='bg-primary-800 flex h-10 w-10 items-center justify-center rounded text-white'> |
|
800 |
|
</div> |
|
<div className='bg-primary-900 flex h-10 w-10 items-center justify-center rounded text-white'> |
|
900 |
|
</div> |
|
<div className='bg-primary-950 flex h-10 w-10 items-center justify-center rounded text-white'> |
|
950 |
|
</div> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>UnstyledLink</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
No style applied, differentiate internal and outside links, |
|
give custom cursor for outside links. |
|
</p> |
|
<div className='space-x-2'> |
|
<UnstyledLink href='/'>Internal Links</UnstyledLink> |
|
<UnstyledLink href='https://theodorusclarence.com'> |
|
Outside Links |
|
</UnstyledLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>PrimaryLink</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Add styling on top of UnstyledLink, giving a primary color to |
|
the link. |
|
</p> |
|
<div className='space-x-2'> |
|
<PrimaryLink href='/'>Internal Links</PrimaryLink> |
|
<PrimaryLink href='https://theodorusclarence.com'> |
|
Outside Links |
|
</PrimaryLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>UnderlineLink</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Add styling on top of UnstyledLink, giving a dotted and |
|
animated underline. |
|
</p> |
|
<div className='space-x-2'> |
|
<UnderlineLink href='/'>Internal Links</UnderlineLink> |
|
<UnderlineLink href='https://theodorusclarence.com'> |
|
Outside Links |
|
</UnderlineLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>ArrowLink</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Useful for indicating navigation, I use this quite a lot, so |
|
why not build a component with some whimsy touch? |
|
</p> |
|
<div className='flex flex-wrap items-center gap-4'> |
|
<ArrowLink href='/' direction='left'> |
|
Direction Left |
|
</ArrowLink> |
|
<ArrowLink href='/'>Direction Right</ArrowLink> |
|
<ArrowLink |
|
as={UnstyledLink} |
|
className='inline-flex items-center' |
|
href='/' |
|
> |
|
Polymorphic |
|
</ArrowLink> |
|
<ArrowLink |
|
as={ButtonLink} |
|
variant='light' |
|
className='inline-flex items-center' |
|
href='/' |
|
> |
|
Polymorphic |
|
</ArrowLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>ButtonLink</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Button styled link with 3 variants. |
|
</p> |
|
<div className='flex flex-wrap gap-2'> |
|
<ButtonLink |
|
variant='primary' |
|
href='https://theodorusclarence.com' |
|
> |
|
Primary Variant |
|
</ButtonLink> |
|
<ButtonLink |
|
variant='outline' |
|
isDarkBg={mode === 'dark'} |
|
href='https://theodorusclarence.com' |
|
> |
|
Outline Variant |
|
</ButtonLink> |
|
<ButtonLink |
|
variant='ghost' |
|
isDarkBg={mode === 'dark'} |
|
href='https://theodorusclarence.com' |
|
> |
|
Ghost Variant |
|
</ButtonLink> |
|
<ButtonLink |
|
variant='dark' |
|
href='https://theodorusclarence.com' |
|
> |
|
Dark Variant |
|
</ButtonLink> |
|
<ButtonLink |
|
variant='light' |
|
href='https://theodorusclarence.com' |
|
> |
|
Light Variant |
|
</ButtonLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>Button</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Ordinary button with style. |
|
</p> |
|
<div className='flex flex-wrap gap-2'> |
|
<Button variant='primary'>Primary Variant</Button> |
|
<Button variant='outline' isDarkBg={mode === 'dark'}> |
|
Outline Variant |
|
</Button> |
|
<Button variant='ghost' isDarkBg={mode === 'dark'}> |
|
Ghost Variant |
|
</Button> |
|
<Button variant='dark'>Dark Variant</Button> |
|
<Button variant='light'>Light Variant</Button> |
|
</div> |
|
<div className='flex flex-wrap gap-2'> |
|
<Button |
|
variant='primary' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
variant='outline' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
variant='ghost' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
variant='dark' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
variant='light' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
</div> |
|
<div className='!mt-4 flex flex-wrap gap-2'> |
|
<Button size='sm' variant='primary'> |
|
Small Size |
|
</Button> |
|
<Button |
|
size='sm' |
|
variant='outline' |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Small Size |
|
</Button> |
|
<Button size='sm' variant='ghost' isDarkBg={mode === 'dark'}> |
|
Small Size |
|
</Button> |
|
<Button size='sm' variant='dark'> |
|
Small Size |
|
</Button> |
|
<Button size='sm' variant='light'> |
|
Small Size |
|
</Button> |
|
</div> |
|
<div className='flex flex-wrap gap-2'> |
|
<Button |
|
size='sm' |
|
variant='primary' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
size='sm' |
|
variant='outline' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
size='sm' |
|
variant='ghost' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Icon |
|
</Button> |
|
|
|
<Button |
|
size='sm' |
|
variant='dark' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
<Button |
|
size='sm' |
|
variant='light' |
|
leftIcon={HiPlus} |
|
rightIcon={HiArrowRight} |
|
> |
|
Icon |
|
</Button> |
|
</div> |
|
|
|
<div className='!mt-4 flex flex-wrap gap-2'> |
|
<Button disabled variant='primary'> |
|
Disabled |
|
</Button> |
|
<Button disabled variant='outline' isDarkBg={mode === 'dark'}> |
|
Disabled |
|
</Button> |
|
<Button disabled variant='ghost' isDarkBg={mode === 'dark'}> |
|
Disabled |
|
</Button> |
|
<Button disabled variant='dark'> |
|
Disabled |
|
</Button> |
|
<Button disabled variant='light'> |
|
Disabled |
|
</Button> |
|
</div> |
|
<div className='flex flex-wrap gap-2'> |
|
<Button isLoading variant='primary'> |
|
Disabled |
|
</Button> |
|
<Button |
|
isLoading |
|
variant='outline' |
|
isDarkBg={mode === 'dark'} |
|
> |
|
Disabled |
|
</Button> |
|
<Button isLoading variant='ghost' isDarkBg={mode === 'dark'}> |
|
Disabled |
|
</Button> |
|
<Button isLoading variant='dark'> |
|
Disabled |
|
</Button> |
|
<Button isLoading variant='light'> |
|
Disabled |
|
</Button> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>TextButton</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Button with a text style |
|
</p> |
|
<div className='space-x-2'> |
|
<TextButton>Primary Variant</TextButton> |
|
<TextButton variant='basic'>Basic Variant</TextButton> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>IconButton</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Button with only icon inside |
|
</p> |
|
<div className='space-x-2'> |
|
<IconButton icon={HiPlus} /> |
|
<IconButton |
|
variant='outline' |
|
icon={HiOutlineDesktopComputer} |
|
/> |
|
<IconButton variant='ghost' icon={HiOutlineDeviceMobile} /> |
|
<IconButton variant='dark' icon={HiOutlineShieldCheck} /> |
|
<IconButton variant='light' icon={HiOutlineCreditCard} /> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>Custom 404 Page</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Styled 404 page with some animation. |
|
</p> |
|
<div className='flex flex-wrap gap-2'> |
|
<ButtonLink href='/404'>Visit the 404 page</ButtonLink> |
|
</div> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>Next Image</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Next Image with default props and skeleton animation |
|
</p> |
|
<NextImage |
|
useSkeleton |
|
className='w-32 md:w-40' |
|
src='/favicon/android-chrome-192x192.png' |
|
width='180' |
|
height='180' |
|
alt='Icon' |
|
/> |
|
</li> |
|
<li className='space-y-2'> |
|
<h2 className='text-lg md:text-xl'>Skeleton</h2> |
|
<p className={clsx('!mt-1 text-sm', textColor)}> |
|
Skeleton with shimmer effect |
|
</p> |
|
<Skeleton className='h-72 w-72' /> |
|
</li> |
|
</ol> |
|
</div> |
|
</section> |
|
</main> |
|
</Layout> |
|
); |
|
} |
|
|
|
const colorList = [ |
|
'slate', |
|
'gray', |
|
'zinc', |
|
'neutral', |
|
'stone', |
|
'red', |
|
'orange', |
|
'amber', |
|
'yellow', |
|
'lime', |
|
'green', |
|
'emerald', |
|
'teal', |
|
'cyan', |
|
'sky', |
|
'blue', |
|
'indigo', |
|
'violet', |
|
'purple', |
|
'fuchsia', |
|
'pink', |
|
'rose', |
|
] as const; |
|
|