feat(site): add dark mode

This commit is contained in:
Rickard Natt och Dag 2021-05-11 14:03:26 +02:00
parent 85bc6d4210
commit 1bc545fcc0
No known key found for this signature in database
GPG Key ID: 97AA4A72D75845D5
18 changed files with 101 additions and 52 deletions

View File

@ -11,9 +11,9 @@ import shape6 from '../assets/img/banner/shape6.png'
import shape7 from '../assets/img/banner/shape7.png' import shape7 from '../assets/img/banner/shape7.png'
import playstore from '../assets/img/playstore.png' import playstore from '../assets/img/playstore.png'
import Link from './Link' import Link from './Link'
import { H1 } from './Typography' import { H1, H2 } from './Typography'
import { useIntl } from 'react-intl' import { useIntl } from 'react-intl'
import { ButtonLinkPatreon } from './ButtonLink' import { ButtonLinkPatreon, ButtonLinkInternal } from './ButtonLink'
const Banner = (): JSX.Element => { const Banner = (): JSX.Element => {
const intl = useIntl() const intl = useIntl()
@ -66,9 +66,7 @@ const Banner = (): JSX.Element => {
<p>{intl.formatMessage({ id: 'general.description' })}</p> <p>{intl.formatMessage({ id: 'general.description' })}</p>
{!!intl.formatMessage({ id: 'general.flashtitle' }) && ( {!!intl.formatMessage({ id: 'general.flashtitle' }) && (
<div className="mt-5"> <div className="mt-5">
<h2 className="mb-4 text-2xl font-bold leading-tight text-gray-800 md:text-4xl"> <H2>{intl.formatMessage({ id: 'general.flashtitle' })}</H2>
{intl.formatMessage({ id: 'general.flashtitle' })}
</h2>
<p>{intl.formatMessage({ id: 'general.flashtext' })}</p> <p>{intl.formatMessage({ id: 'general.flashtext' })}</p>
</div> </div>
)} )}
@ -102,17 +100,13 @@ const Banner = (): JSX.Element => {
</ButtonLinkPatreon> </ButtonLinkPatreon>
</p> </p>
<p className="flex flex-col mt-5 sm:items-center sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2"> <p className="flex flex-col mt-5 sm:items-center sm:flex-row space-y-2 sm:space-y-0 sm:space-x-2">
<NextLink href="/integritet"> <ButtonLinkInternal href="/integritet">
<a className="inline-block px-4 py-2 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full lg:px-8 lg:py-4 hover:bg-indigo-800 hover:text-white"> <a>{intl.formatMessage({ id: 'navigation.integrity' })}</a>
{intl.formatMessage({ id: 'navigation.integrity' })} </ButtonLinkInternal>
</a>
</NextLink>
<NextLink href="/qa"> <ButtonLinkInternal href="/qa">
<a className="inline-block px-4 py-2 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full lg:px-8 lg:py-4 hover:bg-indigo-800 hover:text-white"> <a>{intl.formatMessage({ id: 'navigation.qna' })}</a>
{intl.formatMessage({ id: 'navigation.qna' })} </ButtonLinkInternal>
</a>
</NextLink>
</p> </p>
</div> </div>
<div className="flex items-start justify-center pr-0 motion-safe:animate-bounce-slow md:pr-4 xl:pr-0"> <div className="flex items-start justify-center pr-0 motion-safe:animate-bounce-slow md:pr-4 xl:pr-0">

View File

@ -2,11 +2,15 @@ import Link from 'next/link'
type ButtonLinkProps = Pick<HTMLAnchorElement, 'href' | 'target'> type ButtonLinkProps = Pick<HTMLAnchorElement, 'href' | 'target'>
const ButtonLink: React.FC<ButtonLinkProps> = ({ children, href, target }) => { export const ButtonLink: React.FC<ButtonLinkProps> = ({
children,
href,
target,
}) => {
return ( return (
<a <a
href={href} href={href}
className="inline-block py-2 px-4 md:px-8 md:py-4 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full hover:bg-indigo-800 hover:text-white" className="inline-block py-2 px-4 md:px-8 md:py-4 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full hover:bg-indigo-800 hover:text-white dark:border-indigo-300 dark:text-indigo-300 dark:hover:bg-indigo-300"
target={target} target={target}
rel={target === '_blank' ? 'noopener noreferrer' : ''} rel={target === '_blank' ? 'noopener noreferrer' : ''}
> >
@ -23,7 +27,7 @@ export const ButtonLinkInternal: React.FC<ButtonLinkInternalProps> = ({
}) => { }) => {
return ( return (
<Link href={href}> <Link href={href}>
<a className="inline-block px-4 py-2 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full cursor-pointer md:px-8 md:py-4 hover:bg-indigo-800 hover:text-white"> <a className="inline-block px-4 py-2 font-bold text-indigo-800 border-2 border-indigo-800 rounded-full cursor-pointer md:px-8 md:py-4 hover:bg-indigo-800 hover:text-white dark:border-indigo-300 dark:text-indigo-300 dark:hover:bg-indigo-300">
{children} {children}
</a> </a>
</Link> </Link>
@ -34,7 +38,7 @@ export const ButtonLinkPatreon: React.FC = ({ children }) => {
return ( return (
<a <a
href="https://www.patreon.com/oppnaskolplattformen" href="https://www.patreon.com/oppnaskolplattformen"
className="inline-block px-4 py-2 font-bold text-white bg-red-500 border-2 rounded-full md:px-8 md:py-4 hover:bg-white hover:border-red-500 hover:text-red-500" className="inline-block px-4 py-2 font-bold text-white bg-orange-500 border-2 rounded-full md:px-8 md:py-4 hover:bg-white hover:border-orange-500 hover:text-orange-500 dark:hover:text-orange-300 dark:hover:bg-gray-800 dark:border-orange-300 dark:bg-orange-300 dark:text-orange-600"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
> >
@ -42,5 +46,3 @@ export const ButtonLinkPatreon: React.FC = ({ children }) => {
</a> </a>
) )
} }
export default ButtonLink

View File

@ -6,7 +6,7 @@ import { H2 } from './Typography'
const CtaThree = (): JSX.Element => { const CtaThree = (): JSX.Element => {
return ( return (
<Section bg="bg-white"> <Section bg="bg-white dark:bg-gray-700">
<div> <div>
<H2>Se summering för alla dina barn ett ställe</H2> <H2>Se summering för alla dina barn ett ställe</H2>
<p> <p>

View File

@ -1,4 +1,4 @@
import ButtonLink, { ButtonLinkPatreon } from './ButtonLink' import { ButtonLink, ButtonLinkPatreon } from './ButtonLink'
const DownloadButtons = (): JSX.Element => { const DownloadButtons = (): JSX.Element => {
return ( return (

View File

@ -60,8 +60,8 @@ const Footer = (): JSX.Element => {
</ul> </ul>
</div> </div>
<div className="p-5 bg-white shadow-md rounded-md"> <div className="p-5 bg-white shadow-md rounded-md dark:bg-gray-800">
<div className="mb-3 text-gray-800"> <div className="mb-3 text-gray-800 dark:text-gray-400">
@iteam1337 Digitalisering riktigt. @iteam1337 Digitalisering riktigt.
</div> </div>
<div> <div>

View File

@ -11,7 +11,7 @@ const Internal: React.FC<LinkInternalProps> = ({
}): JSX.Element => { }): JSX.Element => {
return ( return (
<Link href={href}> <Link href={href}>
<a className="text-indigo-800">{children}</a> <a className="text-indigo-800 dark:text-indigo-300">{children}</a>
</Link> </Link>
) )
} }
@ -30,7 +30,7 @@ const External: React.FC<LinkExternalProps> = ({
}): JSX.Element => { }): JSX.Element => {
return ( return (
<a <a
className={classnames('text-indigo-800', className)} className={classnames('text-indigo-800 dark:text-indigo-300', className)}
href={href} href={href}
target={target} target={target}
rel={target === '_blank' ? 'noopener noreferrer' : ''} rel={target === '_blank' ? 'noopener noreferrer' : ''}

View File

@ -16,6 +16,7 @@ interface LinkProps {
const NavLinks = ({ onClick }: NavLinksProps): JSX.Element => { const NavLinks = ({ onClick }: NavLinksProps): JSX.Element => {
const { pathname } = useRouter() const { pathname } = useRouter()
const intl = useIntl() const intl = useIntl()
const className = 'dark:text-gray-300'
const path = (href: string) => { const path = (href: string) => {
const hashIndex = href.indexOf('#') const hashIndex = href.indexOf('#')
@ -23,10 +24,11 @@ const NavLinks = ({ onClick }: NavLinksProps): JSX.Element => {
return href.substring(0, hashIndex) return href.substring(0, hashIndex)
} }
const Link: React.FC<LinkProps> = ({ href, to, children }) => const Link: React.FC<LinkProps> = ({ href, to, children }) => {
path(href) === pathname ? ( return path(href) === pathname ? (
<ScrollLink <ScrollLink
activeClass="current" activeClass="current"
className={className}
to={to} to={to}
href={`#${to}`} href={`#${to}`}
spy={true} spy={true}
@ -42,9 +44,12 @@ const NavLinks = ({ onClick }: NavLinksProps): JSX.Element => {
</ScrollLink> </ScrollLink>
) : ( ) : (
<NavLink href={href}> <NavLink href={href}>
<a onClick={() => onClick?.()}>{children}</a> <a className={className} onClick={() => onClick?.()}>
{children}
</a>
</NavLink> </NavLink>
) )
}
return ( return (
<ul className="flex flex-col text-xl text-gray-800 md:flex-row md:items-center space-y-4 md:space-y-0 md:space-x-8 md:text-base"> <ul className="flex flex-col text-xl text-gray-800 md:flex-row md:items-center space-y-4 md:space-y-0 md:space-x-8 md:text-base">
@ -54,7 +59,9 @@ const NavLinks = ({ onClick }: NavLinksProps): JSX.Element => {
</Link> </Link>
</li> </li>
<li> <li>
<NavLink href="/aktuellt">Aktuellt</NavLink> <NavLink href="/aktuellt">
<a className={className}>Aktuellt</a>
</NavLink>
</li> </li>
<li> <li>
<Link to="funktioner" href="/#funktioner"> <Link to="funktioner" href="/#funktioner">

View File

@ -44,7 +44,7 @@ const Pricing = (): JSX.Element => {
/> />
</div> </div>
<div className="flex"> <div className="flex">
<div className="flex flex-col items-center inline-block px-5 py-8 mx-auto text-center shadow-lg rounded-md"> <div className="flex flex-col items-center inline-block px-5 py-8 mx-auto text-center shadow-lg rounded-md dark:bg-gray-700">
<h3 className="text-3xl text-gray-800">Engångskostnad</h3> <h3 className="text-3xl text-gray-800">Engångskostnad</h3>
<div className="mt-5 text-6xl text-pink-500"> <div className="mt-5 text-6xl text-pink-500">
{formatPrice(price)} {formatPrice(price)}

View File

@ -42,8 +42,10 @@ const Pricing = (): JSX.Element => {
/> />
</div> </div>
<div className="flex"> <div className="flex">
<div className="flex flex-col items-center inline-block px-5 py-8 mx-auto text-center shadow-lg rounded-md"> <div className="flex flex-col items-center inline-block px-5 py-8 mx-auto text-center shadow-lg rounded-md dark:bg-gray-800">
<h3 className="text-3xl text-gray-800">Tillfälligt</h3> <h3 className="text-3xl text-gray-800 dark:text-gray-300">
Tillfälligt
</h3>
<div className="mt-5 text-6xl text-pink-500"> <div className="mt-5 text-6xl text-pink-500">
{formatPrice(price)} {formatPrice(price)}
</div> </div>

View File

@ -1,7 +1,7 @@
const Privacy = (): JSX.Element => { const Privacy = (): JSX.Element => {
return ( return (
<div className="header"> <div className="header">
<div className="max-w-6xl mx-auto px-5 md:px-0 my-5 md:my-24 prose"> <div className="max-w-4xl mx-auto px-5 md:px-0 my-5 md:my-24 prose dark:prose-dark">
<h1>Öppna Skolplattformen</h1> <h1>Öppna Skolplattformen</h1>
<h2>Integritetspolicy</h2> <h2>Integritetspolicy</h2>
<p> <p>

View File

@ -1,7 +1,7 @@
const QA = (): JSX.Element => { const QA = (): JSX.Element => {
return ( return (
<div className="header"> <div className="header">
<div className="max-w-6xl px-5 mx-auto my-5 md:my-24 md:px-0 prose"> <div className="max-w-4xl px-5 mx-auto my-5 md:my-24 md:px-0 prose dark:prose-dark">
<h1>Frågor och svar om Öppna skolplattformen</h1> <h1>Frågor och svar om Öppna skolplattformen</h1>
<h2> <h2>

View File

@ -7,7 +7,7 @@ interface SectionProps {
} }
const Section: React.FC<SectionProps> = ({ const Section: React.FC<SectionProps> = ({
bg = 'bg-gray-100', bg = 'bg-gray-100 dark:bg-gray-800',
padding = 'py-8 md:py-20', padding = 'py-8 md:py-20',
children, children,
id, id,

View File

@ -1,3 +1,5 @@
import { H2 } from '../components/Typography'
interface SectionTitleProps { interface SectionTitleProps {
text?: string text?: string
title: string title: string
@ -6,9 +8,7 @@ interface SectionTitleProps {
const SectionTitle = ({ text, title }: SectionTitleProps): JSX.Element => { const SectionTitle = ({ text, title }: SectionTitleProps): JSX.Element => {
return ( return (
<div className="mb-16 text-center space-y-5"> <div className="mb-16 text-center space-y-5">
<h2 className="text-4xl md:text-5xl font-bold leading-tight text-gray-800"> <H2>{title}</H2>
{title}
</h2>
{text && <p className="text-gray-600">{text}</p>} {text && <p className="text-gray-600">{text}</p>}
</div> </div>
) )

View File

@ -21,7 +21,7 @@ const Timeline = ({ events }: TimelineProps): JSX.Element => {
<ul className="max-w-2xl border-gray-200 md:mx-auto md:border-l-2 space-y-4 md:space-y-12"> <ul className="max-w-2xl border-gray-200 md:mx-auto md:border-l-2 space-y-4 md:space-y-12">
{events.map(({ date, media, importantDates, overview }) => ( {events.map(({ date, media, importantDates, overview }) => (
<li className="relative" key={date}> <li className="relative" key={date}>
<div className="absolute top-0 items-center justify-center hidden w-10 h-10 text-white bg-indigo-400 border-4 border-white rounded-full md:flex -left-5 -top-2"> <div className="absolute top-0 items-center justify-center hidden w-10 h-10 text-white bg-indigo-400 border-4 border-white rounded-full md:flex -left-5 -top-2 dark:border-gray-600">
<svg <svg
className="w-5 h-5" className="w-5 h-5"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -35,10 +35,10 @@ const Timeline = ({ events }: TimelineProps): JSX.Element => {
/> />
</svg> </svg>
</div> </div>
<div className="hidden mb-4 ml-8 text-sm font-bold text-gray-700 capitalize md:block"> <div className="hidden mb-4 ml-8 text-sm font-bold text-gray-700 dark:text-gray-500 capitalize md:block">
{dateFormat(date)} {dateFormat(date)}
</div> </div>
<div className="p-4 text-sm leading-relaxed bg-white border-t-4 border-indigo-300 rounded-b shadow-md md:p-5 md:ml-8"> <div className="p-4 text-sm leading-relaxed bg-white border-t-4 border-indigo-300 rounded-b shadow-md md:p-5 md:ml-8 dark:bg-gray-800">
<div className="block mb-4 text-lg font-bold text-gray-700 capitalize md:hidden"> <div className="block mb-4 text-lg font-bold text-gray-700 capitalize md:hidden">
{dateFormat(date)} {dateFormat(date)}
</div> </div>
@ -56,7 +56,7 @@ const Timeline = ({ events }: TimelineProps): JSX.Element => {
) : ( ) : (
important.description important.description
)} )}
<div className="text-xs text-gray-500"> <div className="text-xs text-gray-500 dark:text-gray-400">
{important.date} {important.date}
</div> </div>
</li> </li>
@ -77,7 +77,9 @@ const Timeline = ({ events }: TimelineProps): JSX.Element => {
) : ( ) : (
m.description m.description
)} )}
<div className="text-xs text-gray-500">{m.date}</div> <div className="text-xs text-gray-500 dark:text-gray-400">
{m.date}
</div>
</li> </li>
))} ))}
</ul> </ul>

View File

@ -1,6 +1,7 @@
import { events } from '../data/timelineEvents' import { events } from '../data/timelineEvents'
import { ButtonLinkInternal } from './ButtonLink' import { ButtonLinkInternal } from './ButtonLink'
import Timeline from './Timeline' import Timeline from './Timeline'
import { H2 } from '../components/Typography'
const TimelineLatest = (): JSX.Element => { const TimelineLatest = (): JSX.Element => {
const latestMonthsEvents = events.slice(0, 1) const latestMonthsEvents = events.slice(0, 1)
@ -8,9 +9,7 @@ const TimelineLatest = (): JSX.Element => {
return ( return (
<section className="max-w-6xl px-5 py-8 mx-auto lg:px-0 lg:py-32 grid grid-cols-1 lg:grid-cols-2 gap-8"> <section className="max-w-6xl px-5 py-8 mx-auto lg:px-0 lg:py-32 grid grid-cols-1 lg:grid-cols-2 gap-8">
<div className="space-y-8"> <div className="space-y-8">
<h2 className="text-2xl md:text-4xl font-bold leading-tight text-gray-800"> <H2>Om Öppna Skolplattformen</H2>
Om Öppna Skolplattformen
</h2>
<p> <p>
Det talas mycket om värdet av digitalisering, innovation och Det talas mycket om värdet av digitalisering, innovation och
medskapande, om nytta för skattepengarna och medborgarinflytande. medskapande, om nytta för skattepengarna och medborgarinflytande.

View File

@ -1,6 +1,6 @@
export const H1: React.FC = ({ children }) => { export const H1: React.FC = ({ children }) => {
return ( return (
<h1 className="mb-5 text-4xl md:text-5xl font-semibold text-gray-800"> <h1 className="mb-5 text-4xl md:text-5xl font-semibold text-gray-800 dark:text-gray-300">
{children} {children}
</h1> </h1>
) )
@ -8,6 +8,8 @@ export const H1: React.FC = ({ children }) => {
export const H2: React.FC = ({ children }) => { export const H2: React.FC = ({ children }) => {
return ( return (
<h2 className="mb-5 text-5xl font-semibold text-gray-800">{children}</h2> <h2 className="mb-5 text-3xl font-semibold text-gray-800 dark:text-gray-300">
{children}
</h2>
) )
} }

View File

@ -10,7 +10,7 @@
html, html,
body { body {
@apply font-sans text-gray-700; @apply font-sans text-gray-700 dark:text-gray-400 dark:bg-gray-900;
} }
p { p {

View File

@ -1,6 +1,9 @@
const colors = require('tailwindcss/colors')
module.exports = { module.exports = {
mode: 'jit',
purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'], purge: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
darkMode: false, // or 'media' or 'class' darkMode: 'media',
theme: { theme: {
fontFamily: { fontFamily: {
sans: ['Poppins', 'sans-serif'], sans: ['Poppins', 'sans-serif'],
@ -9,6 +12,9 @@ module.exports = {
animation: { animation: {
'bounce-slow': 'slow-bounce 2s ease-in-out infinite', 'bounce-slow': 'slow-bounce 2s ease-in-out infinite',
}, },
colors: {
orange: colors.orange,
},
keyframes: { keyframes: {
'slow-bounce': { 'slow-bounce': {
'0%, 100%': { '0%, 100%': {
@ -24,12 +30,47 @@ module.exports = {
zIndex: { zIndex: {
'-1': '-1', '-1': '-1',
}, },
typography: (theme) => ({
dark: {
css: {
color: theme('colors.gray.400'),
a: {
color: theme('colors.indigo.300'),
'&:hover': {
color: theme('colors.indigo.300'),
},
},
strong: {
color: theme('colors.gray.400'),
},
h1: {
color: theme('colors.gray.300'),
},
h2: {
color: theme('colors.gray.300'),
},
h3: {
color: theme('colors.gray.300'),
},
h4: {
color: theme('colors.gray.300'),
},
h5: {
color: theme('colors.gray.300'),
},
h6: {
color: theme('colors.gray.300'),
},
},
},
}),
}, },
}, },
variants: { variants: {
extend: { extend: {
animation: ['motion-safe'], animation: ['motion-safe'],
}, },
typography: ['dark'],
}, },
plugins: [require('@tailwindcss/typography')], plugins: [require('@tailwindcss/typography')],
} }