remove next-themes, convert header to custom button
This commit is contained in:
parent
bff7c90e5f
commit
dfe0d39fa0
21 changed files with 281 additions and 160 deletions
|
@ -36,6 +36,11 @@
|
|||
color: var(--fg);
|
||||
}
|
||||
|
||||
/* when data-theme on html is light, change font color */
|
||||
[data-theme="light"] .warning {
|
||||
color: var(--bg);
|
||||
}
|
||||
|
||||
.error {
|
||||
background-color: red;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ const ButtonDropdown: React.FC<
|
|||
|
||||
return (
|
||||
<div
|
||||
className={`${styles.main} ${className}`}
|
||||
className={`${styles.main} ${className || ""}`}
|
||||
onMouseDown={onMouseDown}
|
||||
onMouseUp={onMouseUp}
|
||||
onMouseLeave={onMouseLeave}
|
||||
|
|
|
@ -46,8 +46,13 @@
|
|||
margin-left: var(--gap-half);
|
||||
}
|
||||
|
||||
.iconLeft {
|
||||
margin-right: var(--gap-half);
|
||||
}
|
||||
|
||||
.icon svg {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: scale(1.2) translateY(-0.05em);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ type Props = React.HTMLProps<HTMLButtonElement> & {
|
|||
className?: string
|
||||
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void
|
||||
iconRight?: React.ReactNode
|
||||
iconLeft?: React.ReactNode
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react/display-name
|
||||
|
@ -20,6 +21,7 @@ const Button = forwardRef<HTMLButtonElement, Props>(
|
|||
type = "button",
|
||||
disabled = false,
|
||||
iconRight,
|
||||
iconLeft,
|
||||
...props
|
||||
},
|
||||
ref
|
||||
|
@ -27,11 +29,16 @@ const Button = forwardRef<HTMLButtonElement, Props>(
|
|||
return (
|
||||
<button
|
||||
ref={ref}
|
||||
className={`${styles.button} ${styles[type]} ${className}`}
|
||||
className={`${styles.button} ${styles[type]} ${className || ""}`}
|
||||
disabled={disabled}
|
||||
onClick={onClick}
|
||||
{...props}
|
||||
>
|
||||
{iconLeft && (
|
||||
<span className={`${styles.icon} ${styles.iconLeft}`}>
|
||||
{iconLeft}
|
||||
</span>
|
||||
)}
|
||||
{children}
|
||||
{iconRight && (
|
||||
<span className={`${styles.icon} ${styles.iconRight}`}>
|
||||
|
|
|
@ -9,7 +9,7 @@ export default function Card({
|
|||
className?: string
|
||||
} & React.ComponentProps<"div">) {
|
||||
return (
|
||||
<div className={`${styles.card} ${className}`} {...props}>
|
||||
<div className={`${styles.card} ${className || ""}`} {...props}>
|
||||
<div className={styles.content}>{children}</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
@ -1,18 +1,14 @@
|
|||
import React, { useEffect, useState } from "react"
|
||||
import MoonIcon from "@geist-ui/icons/moon"
|
||||
import SunIcon from "@geist-ui/icons/sun"
|
||||
// import { useAllThemes, useTheme } from '@geist-ui/core'
|
||||
import styles from "./header.module.css"
|
||||
import { Select } from "@geist-ui/core/dist"
|
||||
import { useTheme } from "next-themes"
|
||||
import { useTheme } from "@components/theme/ThemeClientContextProvider"
|
||||
|
||||
const Controls = () => {
|
||||
const [mounted, setMounted] = useState(false)
|
||||
const { resolvedTheme, setTheme } = useTheme()
|
||||
useEffect(() => setMounted(true), [])
|
||||
if (!mounted) return null
|
||||
const { theme, setTheme } = useTheme()
|
||||
const switchThemes = () => {
|
||||
if (resolvedTheme === "dark") {
|
||||
if (theme === "dark") {
|
||||
setTheme("light")
|
||||
} else {
|
||||
setTheme("dark")
|
||||
|
@ -26,7 +22,7 @@ const Controls = () => {
|
|||
h="28px"
|
||||
pure
|
||||
onChange={switchThemes}
|
||||
value={resolvedTheme}
|
||||
value={theme}
|
||||
>
|
||||
<Select.Option value="light">
|
||||
<span className={styles.selectContent}>
|
||||
|
|
|
@ -11,20 +11,37 @@
|
|||
align-items: center;
|
||||
}
|
||||
|
||||
.tabs .buttons > button,
|
||||
.tabs .buttons > a > button {
|
||||
.tabs .buttons button {
|
||||
border: none;
|
||||
border-radius: 0;
|
||||
cursor: pointer;
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.tabs .active {
|
||||
border-bottom: 1px solid var(--darker-gray) !important;
|
||||
.tabs .buttons > a:hover,
|
||||
.tabs .buttons > button:hover {
|
||||
color: var(--fg);
|
||||
box-shadow: inset 0 -1px 0 var(--fg);
|
||||
transition: box-shadow 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.tabs a:active,
|
||||
.tabs a:focus,
|
||||
.tabs button:active,
|
||||
.tabs button:focus {
|
||||
color: var(--darker-gray);
|
||||
}
|
||||
|
||||
.mobile {
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.mobile button {
|
||||
z-index: 1000;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.controls {
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
"use client"
|
||||
|
||||
import {
|
||||
ButtonGroup,
|
||||
Button,
|
||||
Page,
|
||||
Spacer,
|
||||
useBodyScroll,
|
||||
useMediaQuery
|
||||
} from "@geist-ui/core/dist"
|
||||
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { useEffect, useState } from "react"
|
||||
import styles from "./header.module.css"
|
||||
|
||||
import HomeIcon from "@geist-ui/icons/home"
|
||||
|
@ -23,11 +20,12 @@ import YourIcon from "@geist-ui/icons/list"
|
|||
import MoonIcon from "@geist-ui/icons/moon"
|
||||
import SettingsIcon from "@geist-ui/icons/settings"
|
||||
import SunIcon from "@geist-ui/icons/sun"
|
||||
import { useTheme } from "next-themes"
|
||||
// import useUserData from "@lib/hooks/use-user-data"
|
||||
import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { signOut } from "next-auth/react"
|
||||
import { useTheme } from "@components/theme/ThemeClientContextProvider"
|
||||
import Button from "@components/button"
|
||||
|
||||
type Tab = {
|
||||
name: string
|
||||
|
@ -44,8 +42,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
const isMobile = useMediaQuery("xs", { match: "down" })
|
||||
// const { status } = useSession()
|
||||
// const signedIn = status === "authenticated"
|
||||
const { setTheme, resolvedTheme } = useTheme()
|
||||
|
||||
const { setTheme, theme } = useTheme()
|
||||
useEffect(() => {
|
||||
setBodyHidden(expanded)
|
||||
}, [expanded, setBodyHidden])
|
||||
|
@ -68,16 +65,16 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
name: isMobile ? "Change theme" : "",
|
||||
onClick: function () {
|
||||
if (typeof window !== "undefined")
|
||||
setTheme(resolvedTheme === "light" ? "dark" : "light")
|
||||
setTheme(theme === "light" ? "dark" : "light")
|
||||
},
|
||||
icon: resolvedTheme === "light" ? <MoonIcon /> : <SunIcon />,
|
||||
icon: theme === "light" ? <MoonIcon /> : <SunIcon />,
|
||||
value: "theme"
|
||||
}
|
||||
]
|
||||
|
||||
if (isAdmin) {
|
||||
defaultPages.push({
|
||||
name: "admin",
|
||||
name: "Admin",
|
||||
icon: <SettingsIcon />,
|
||||
value: "admin",
|
||||
href: "/admin"
|
||||
|
@ -87,25 +84,25 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
if (signedIn)
|
||||
return [
|
||||
{
|
||||
name: "new",
|
||||
name: "New",
|
||||
icon: <NewIcon />,
|
||||
value: "new",
|
||||
href: "/new"
|
||||
},
|
||||
{
|
||||
name: "yours",
|
||||
name: "Yours",
|
||||
icon: <YourIcon />,
|
||||
value: "yours",
|
||||
href: "/mine"
|
||||
},
|
||||
{
|
||||
name: "settings",
|
||||
name: "Settings",
|
||||
icon: <SettingsIcon />,
|
||||
value: "settings",
|
||||
href: "/settings"
|
||||
},
|
||||
{
|
||||
name: "sign out",
|
||||
name: "Sign Out",
|
||||
icon: <SignOutIcon />,
|
||||
value: "signout",
|
||||
onClick: () => signOut()
|
||||
|
@ -115,7 +112,7 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
else
|
||||
return [
|
||||
{
|
||||
name: "home",
|
||||
name: "Home",
|
||||
icon: <HomeIcon />,
|
||||
value: "home",
|
||||
href: "/"
|
||||
|
@ -147,26 +144,29 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
}
|
||||
|
||||
const getButton = (tab: Tab) => {
|
||||
const activeStyle = pathname === tab.href ? styles.active : ""
|
||||
const isActive = pathname === tab.href
|
||||
const activeStyle = isActive ? styles.active : ""
|
||||
if (tab.onClick) {
|
||||
return (
|
||||
<Button
|
||||
auto={isMobile ? false : true}
|
||||
key={tab.value}
|
||||
icon={tab.icon}
|
||||
iconLeft={tab.icon}
|
||||
onClick={() => onTabChange(tab.value)}
|
||||
className={`${styles.tab} ${activeStyle}`}
|
||||
shadow={false}
|
||||
aria-label={tab.name}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
>
|
||||
{tab.name ? tab.name : undefined}
|
||||
</Button>
|
||||
)
|
||||
} else if (tab.href) {
|
||||
return (
|
||||
<Link key={tab.value} href={tab.href} className={styles.tab}>
|
||||
<Button auto={isMobile ? false : true} icon={tab.icon} shadow={false}>
|
||||
{tab.name ? tab.name : undefined}
|
||||
</Button>
|
||||
<Link
|
||||
key={tab.value}
|
||||
href={tab.href}
|
||||
className={`${styles.tab} ${activeStyle}`}
|
||||
>
|
||||
<Button iconLeft={tab.icon}>{tab.name ? tab.name : undefined}</Button>
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
@ -180,28 +180,14 @@ const Header = ({ signedIn = false, isAdmin = false }) => {
|
|||
<div className={styles.buttons}>{buttons}</div>
|
||||
</div>
|
||||
<div className={styles.controls}>
|
||||
<Button
|
||||
effect={false}
|
||||
auto
|
||||
type="abort"
|
||||
onClick={() => setExpanded(!expanded)}
|
||||
aria-label="Menu"
|
||||
>
|
||||
<Spacer height={5 / 6} width={0} />
|
||||
<Button onClick={() => setExpanded(!expanded)} aria-label="Menu">
|
||||
<MenuIcon />
|
||||
</Button>
|
||||
</div>
|
||||
{/* setExpanded should occur elsewhere; we don't want to close if they change themes */}
|
||||
{isMobile && expanded && (
|
||||
<div className={styles.mobile} onClick={() => setExpanded(!expanded)}>
|
||||
<ButtonGroup
|
||||
vertical
|
||||
style={{
|
||||
background: "var(--bg)"
|
||||
}}
|
||||
>
|
||||
{buttons}
|
||||
</ButtonGroup>
|
||||
{buttons}
|
||||
</div>
|
||||
)}
|
||||
</Page.Header>
|
||||
|
|
5
client/app/components/page/index.tsx
Normal file
5
client/app/components/page/index.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
import styles from "./page.module.css"
|
||||
|
||||
export default function Page({ children }: { children: React.ReactNode }) {
|
||||
return <div className={styles.page}>{children}</div>
|
||||
}
|
10
client/app/components/page/page.module.css
Normal file
10
client/app/components/page/page.module.css
Normal file
|
@ -0,0 +1,10 @@
|
|||
.page {
|
||||
max-width: 100vw;
|
||||
min-height: 100vh;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
padding: 0 calc(1.34 * 16px) 0 calc(1.34 * 16px);
|
||||
margin: 0 auto 0 auto;
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
'use client';
|
||||
import { Fieldset, Text, Divider } from "@geist-ui/core/dist"
|
||||
"use client"
|
||||
import Card from "@components/card"
|
||||
import styles from "./settings-group.module.css"
|
||||
|
||||
type Props = {
|
||||
|
@ -9,13 +9,11 @@ type Props = {
|
|||
|
||||
const SettingsGroup = ({ title, children }: Props) => {
|
||||
return (
|
||||
<Fieldset width={'100%'}>
|
||||
<Fieldset.Content>
|
||||
<Text h4>{title}</Text>
|
||||
</Fieldset.Content>
|
||||
<Divider />
|
||||
<Fieldset.Content className={styles.content}>{children}</Fieldset.Content>
|
||||
</Fieldset>
|
||||
<Card>
|
||||
<h4>{title}</h4>
|
||||
<hr />
|
||||
<div className={styles.content}>{children}</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
62
client/app/components/theme/ThemeClientContextProvider.tsx
Normal file
62
client/app/components/theme/ThemeClientContextProvider.tsx
Normal file
|
@ -0,0 +1,62 @@
|
|||
"use client"
|
||||
|
||||
import {
|
||||
FunctionComponent,
|
||||
PropsWithChildren,
|
||||
useCallback,
|
||||
useMemo
|
||||
} from "react"
|
||||
import React, { useContext, useState, createContext } from "react"
|
||||
import { DEFAULT_THEME, Theme, THEME_COOKIE_NAME } from "./theme"
|
||||
import { setCookie } from "cookies-next"
|
||||
|
||||
interface UseThemeProps {
|
||||
theme: Theme
|
||||
setTheme: (theme: Theme) => void
|
||||
}
|
||||
|
||||
const ThemeContext = createContext<UseThemeProps | null>(null)
|
||||
|
||||
export function useTheme(): {
|
||||
theme: Theme
|
||||
setTheme: (theme: Theme) => void
|
||||
} {
|
||||
return (
|
||||
useContext(ThemeContext) || {
|
||||
theme: DEFAULT_THEME,
|
||||
setTheme: () => {}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
interface Props extends PropsWithChildren<{}> {
|
||||
defaultTheme: Theme
|
||||
}
|
||||
|
||||
const ThemeClientContextProvider: FunctionComponent<Props> = ({
|
||||
defaultTheme,
|
||||
children
|
||||
}) => {
|
||||
const [theme, setThemeState] = useState<Theme>(defaultTheme)
|
||||
const setCookieAndDocument = useCallback(
|
||||
(theme: Theme) => {
|
||||
setThemeState(theme)
|
||||
setCookie(THEME_COOKIE_NAME, theme)
|
||||
document.documentElement.setAttribute("data-theme", theme)
|
||||
},
|
||||
[setThemeState]
|
||||
)
|
||||
|
||||
const setTheme = useCallback(
|
||||
(theme: Theme) => {
|
||||
setCookieAndDocument(theme)
|
||||
},
|
||||
[setCookieAndDocument]
|
||||
)
|
||||
|
||||
const value = useMemo(() => ({ theme, setTheme }), [theme, setTheme])
|
||||
|
||||
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
||||
}
|
||||
|
||||
export default ThemeClientContextProvider
|
26
client/app/components/theme/ThemeProvider.tsx
Normal file
26
client/app/components/theme/ThemeProvider.tsx
Normal file
|
@ -0,0 +1,26 @@
|
|||
import type { FunctionComponent, PropsWithChildren } from "react";
|
||||
import ThemeClientContextProvider from "./ThemeClientContextProvider";
|
||||
import ThemeServerContextProvider, {
|
||||
useServerTheme,
|
||||
} from "./ThemeServerContextProvider";
|
||||
|
||||
const ThemeProviderWrapper: FunctionComponent<PropsWithChildren<{}>> = ({
|
||||
children,
|
||||
}) => {
|
||||
const theme = useServerTheme();
|
||||
return (
|
||||
<ThemeClientContextProvider defaultTheme={theme}>
|
||||
{children}
|
||||
</ThemeClientContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const ThemeProvider: FunctionComponent<PropsWithChildren<{}>> = ({ children }) => {
|
||||
return (
|
||||
<ThemeServerContextProvider>
|
||||
<ThemeProviderWrapper>{children}</ThemeProviderWrapper>
|
||||
</ThemeServerContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeProvider;
|
24
client/app/components/theme/ThemeServerContextProvider.tsx
Normal file
24
client/app/components/theme/ThemeServerContextProvider.tsx
Normal file
|
@ -0,0 +1,24 @@
|
|||
import type { FunctionComponent, PropsWithChildren } from "react";
|
||||
// @ts-ignore -- createServerContext is not in @types/react atm
|
||||
import { useContext, createServerContext } from "react";
|
||||
import { cookies } from "next/headers";
|
||||
import { Theme, THEME_COOKIE_NAME } from "./theme";
|
||||
import { DEFAULT_THEME } from "./theme";
|
||||
|
||||
const ThemeContext = createServerContext<Theme | null>(null);
|
||||
|
||||
export function useServerTheme(): Theme {
|
||||
return useContext(ThemeContext);
|
||||
}
|
||||
|
||||
const ThemeServerContextProvider: FunctionComponent<PropsWithChildren<{}>> = ({
|
||||
children,
|
||||
}) => {
|
||||
const cookiesList = cookies();
|
||||
const theme = cookiesList.get(THEME_COOKIE_NAME)?.value ?? DEFAULT_THEME;
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>{children}</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThemeServerContextProvider;
|
5
client/app/components/theme/theme.tsx
Normal file
5
client/app/components/theme/theme.tsx
Normal file
|
@ -0,0 +1,5 @@
|
|||
export type Theme = "light" | "dark";
|
||||
|
||||
export const DEFAULT_THEME: Theme = "light";
|
||||
|
||||
export const THEME_COOKIE_NAME = "drift-theme";
|
|
@ -1,6 +1,4 @@
|
|||
"use client"
|
||||
|
||||
import { Card } from "@geist-ui/core/dist"
|
||||
import Card from "@components/card"
|
||||
import * as RadixTooltip from "@radix-ui/react-tooltip"
|
||||
import "./tooltip.css"
|
||||
|
||||
|
@ -16,14 +14,12 @@ const Tooltip = ({
|
|||
} & RadixTooltip.TooltipProps) => {
|
||||
return (
|
||||
<RadixTooltip.Root {...props}>
|
||||
<RadixTooltip.Trigger asChild className={className}>{children}</RadixTooltip.Trigger>
|
||||
<RadixTooltip.Trigger asChild className={className}>
|
||||
{children}
|
||||
</RadixTooltip.Trigger>
|
||||
|
||||
<RadixTooltip.Content>
|
||||
<Card className="tooltip">
|
||||
<Card.Body margin={0} padding={1 / 2}>
|
||||
{content}
|
||||
</Card.Body>
|
||||
</Card>
|
||||
<Card className="tooltip">{content}</Card>
|
||||
</RadixTooltip.Content>
|
||||
</RadixTooltip.Root>
|
||||
)
|
||||
|
|
|
@ -1,31 +1,46 @@
|
|||
import "@styles/globals.css"
|
||||
import { ServerThemeProvider } from "next-themes"
|
||||
import { LayoutWrapper } from "./root-layout-wrapper"
|
||||
import styles from '@styles/Home.module.css';
|
||||
import { cookies } from "next/headers";
|
||||
import { getSession } from "@lib/server/session";
|
||||
import styles from "@styles/Home.module.css"
|
||||
import { getSession } from "@lib/server/session"
|
||||
import ThemeProvider from "@components/theme/ThemeProvider"
|
||||
import { THEME_COOKIE_NAME } from "@components/theme/theme"
|
||||
import { useServerTheme } from "@components/theme/ThemeServerContextProvider"
|
||||
|
||||
interface RootLayoutProps {
|
||||
children: React.ReactNode
|
||||
}
|
||||
|
||||
export default async function RootLayout({ children }: RootLayoutProps) {
|
||||
export default async function RootLayout({ children }: RootLayoutProps) {
|
||||
// TODO: this opts out of SSG
|
||||
const session = await getSession()
|
||||
return (
|
||||
<ServerThemeProvider
|
||||
disableTransitionOnChange
|
||||
attribute="data-theme"
|
||||
enableColorScheme
|
||||
>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
</head>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function() {
|
||||
var theme = document.cookie
|
||||
.split('; ')
|
||||
.find(row => row.startsWith('${THEME_COOKIE_NAME}='))
|
||||
.split('=')[1];
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
console.log("theme on load", theme)
|
||||
})();
|
||||
`,
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
<ThemeProvider>
|
||||
<body className={styles.main}>
|
||||
<LayoutWrapper signedIn={Boolean(session?.user)} isAdmin={session?.user.role === "admin"}>{children}</LayoutWrapper>
|
||||
<LayoutWrapper
|
||||
signedIn={Boolean(session?.user)}
|
||||
isAdmin={session?.user.role === "admin"}
|
||||
>
|
||||
{children}
|
||||
</LayoutWrapper>
|
||||
</body>
|
||||
</html>
|
||||
</ServerThemeProvider>
|
||||
</ThemeProvider>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,73 +1,24 @@
|
|||
"use client"
|
||||
|
||||
import Header from "@components/header"
|
||||
import { CssBaseline, GeistProvider, Page, Themes } from "@geist-ui/core/dist"
|
||||
import { ThemeProvider } from "next-themes"
|
||||
import Page from "@components/page"
|
||||
import * as RadixTooltip from "@radix-ui/react-tooltip"
|
||||
|
||||
export function LayoutWrapper({
|
||||
children,
|
||||
signedIn,
|
||||
isAdmin,
|
||||
isAdmin
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
signedIn?: boolean
|
||||
isAdmin?: boolean
|
||||
}) {
|
||||
const customTheme = Themes.createFromLight({
|
||||
type: "custom",
|
||||
palette: {
|
||||
background: "var(--bg)",
|
||||
foreground: "var(--fg)",
|
||||
accents_1: "var(--lightest-gray)",
|
||||
accents_2: "var(--lighter-gray)",
|
||||
accents_3: "var(--light-gray)",
|
||||
accents_4: "var(--gray)",
|
||||
accents_5: "var(--darker-gray)",
|
||||
accents_6: "var(--darker-gray)",
|
||||
accents_7: "var(--darkest-gray)",
|
||||
accents_8: "var(--darkest-gray)",
|
||||
border: "var(--light-gray)",
|
||||
warning: "var(--warning)"
|
||||
},
|
||||
expressiveness: {
|
||||
dropdownBoxShadow: "0 0 0 1px var(--lighter-gray)",
|
||||
shadowSmall: "0 0 0 1px var(--lighter-gray)",
|
||||
shadowLarge: "0 0 0 1px var(--lighter-gray)",
|
||||
shadowMedium: "0 0 0 1px var(--lighter-gray)"
|
||||
},
|
||||
layout: {
|
||||
gap: "var(--gap)",
|
||||
gapHalf: "var(--gap-half)",
|
||||
gapQuarter: "var(--gap-quarter)",
|
||||
gapNegative: "var(--gap-negative)",
|
||||
gapHalfNegative: "var(--gap-half-negative)",
|
||||
gapQuarterNegative: "var(--gap-quarter-negative)",
|
||||
radius: "var(--radius)"
|
||||
},
|
||||
font: {
|
||||
mono: "var(--font-mono)",
|
||||
sans: "var(--font-sans)"
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<RadixTooltip.Provider delayDuration={200}>
|
||||
<GeistProvider themes={[customTheme]} themeType={"custom"}>
|
||||
<ThemeProvider
|
||||
disableTransitionOnChange
|
||||
cookieName="drift-theme"
|
||||
attribute="data-theme"
|
||||
>
|
||||
<CssBaseline />
|
||||
<Page width={"100%"}>
|
||||
<Page.Header>
|
||||
<Header isAdmin={isAdmin} signedIn={signedIn} />
|
||||
</Page.Header>
|
||||
{children}
|
||||
</Page>
|
||||
</ThemeProvider>
|
||||
</GeistProvider>
|
||||
<Page>
|
||||
<Header isAdmin={isAdmin} signedIn={signedIn} />
|
||||
{children}
|
||||
</Page>
|
||||
</RadixTooltip.Provider>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
--border: var(--lighter-gray);
|
||||
--warning: rgb(27, 134, 23);
|
||||
--link: #3291ff;
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
|
@ -69,8 +70,10 @@
|
|||
--header-bg: rgba(255, 255, 255, 0.8);
|
||||
--gray-alpha: rgba(19, 20, 21, 0.5);
|
||||
--selection: var(0, 0, 0, .6);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
@ -96,7 +99,6 @@ body {
|
|||
font-family: var(--font-sans);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
/* TODO: this should be unnecessary. Overides the browser background for color-scheme while geist-ui catches up */
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
|
@ -131,6 +133,12 @@ code {
|
|||
font-family: var(--font-mono) !important;
|
||||
}
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-bottom: 1px solid var(--light-gray);
|
||||
margin: var(--gap) 0;
|
||||
}
|
||||
|
||||
@media print {
|
||||
:root {
|
||||
--bg: #fff;
|
||||
|
@ -166,3 +174,4 @@ main {
|
|||
margin-top: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
"jest": "^29.3.1",
|
||||
"next": "13.0.3",
|
||||
"next-auth": "^4.16.4",
|
||||
"next-themes": "npm:@wits/next-themes@0.2.7",
|
||||
"next-themes": "^0.2.1",
|
||||
"rc-table": "7.24.1",
|
||||
"react": "18.2.0",
|
||||
"react-datepicker": "4.8.0",
|
||||
|
@ -69,5 +69,9 @@
|
|||
"components",
|
||||
"lib"
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ specifiers:
|
|||
katex: ^0.16.3
|
||||
next: 13.0.3
|
||||
next-auth: ^4.16.4
|
||||
next-themes: npm:@wits/next-themes@0.2.7
|
||||
next-themes: ^0.2.1
|
||||
next-unused: 0.0.6
|
||||
prettier: 2.6.2
|
||||
prisma: ^4.6.1
|
||||
|
@ -58,7 +58,7 @@ dependencies:
|
|||
jest: 29.3.1_@types+node@17.0.23
|
||||
next: 13.0.3_biqbaboplfbrettd7655fr4n2y
|
||||
next-auth: 4.16.4_ogpkrxaz2lg6nectum6dl66tn4
|
||||
next-themes: /@wits/next-themes/0.2.7_ogpkrxaz2lg6nectum6dl66tn4
|
||||
next-themes: 0.2.1_ogpkrxaz2lg6nectum6dl66tn4
|
||||
rc-table: 7.24.1_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-datepicker: 4.8.0_biqbaboplfbrettd7655fr4n2y
|
||||
|
@ -1594,18 +1594,6 @@ packages:
|
|||
- supports-color
|
||||
dev: false
|
||||
|
||||
/@wits/next-themes/0.2.7_ogpkrxaz2lg6nectum6dl66tn4:
|
||||
resolution: {integrity: sha512-CpmNH3RRqf2w0i1Xbrz5GKNE/d5gMq1oBlGpofY9LWcjH225nUgrxP15wKRITRAbn68ERDbsBGEBiaRECTmQag==}
|
||||
peerDependencies:
|
||||
next: '*'
|
||||
react: '*'
|
||||
react-dom: '*'
|
||||
dependencies:
|
||||
next: 13.0.3_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/abbrev/1.1.1:
|
||||
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
|
||||
dev: false
|
||||
|
@ -5129,6 +5117,18 @@ packages:
|
|||
uuid: 8.3.2
|
||||
dev: false
|
||||
|
||||
/next-themes/0.2.1_ogpkrxaz2lg6nectum6dl66tn4:
|
||||
resolution: {integrity: sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==}
|
||||
peerDependencies:
|
||||
next: '*'
|
||||
react: '*'
|
||||
react-dom: '*'
|
||||
dependencies:
|
||||
next: 13.0.3_biqbaboplfbrettd7655fr4n2y
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0_react@18.2.0
|
||||
dev: false
|
||||
|
||||
/next-unused/0.0.6:
|
||||
resolution: {integrity: sha512-dHFNNBanFq4wvYrULtsjfWyZ6BzOnr5VYI9EYMGAZYF2vkAhFpj2JOuT5Wu2o3LbFSG92PmAZnSUF/LstF82pA==}
|
||||
hasBin: true
|
||||
|
|
Loading…
Reference in a new issue