revert: undo t0ng7u UI design-system refactor
Revert the following commits: -308e3e347feat(web): polish themed data views and add task log details -b2a890e75fix: Fontsource asset resolution across workspace layouts -9d1ca545erefactor(web): refine data-table cards and pricing page layout -0918bdb49refactor(web): consolidate design-system primitives and responsive data views -262ab9312style(web): unify design system across default frontend
This commit is contained in:
+77
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright (C) 2023-2026 QuantumNous
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
|
||||
import { fonts } from '@/config/fonts'
|
||||
import { getCookie, setCookie, removeCookie } from '@/lib/cookies'
|
||||
|
||||
type Font = (typeof fonts)[number]
|
||||
|
||||
const FONT_COOKIE_NAME = 'font'
|
||||
const FONT_COOKIE_MAX_AGE = 60 * 60 * 24 * 365 // 1 year
|
||||
|
||||
type FontContextType = {
|
||||
font: Font
|
||||
setFont: (font: Font) => void
|
||||
resetFont: () => void
|
||||
}
|
||||
|
||||
const FontContext = createContext<FontContextType | null>(null)
|
||||
|
||||
export function FontProvider({ children }: { children: React.ReactNode }) {
|
||||
const [font, _setFont] = useState<Font>(() => {
|
||||
const savedFont = getCookie(FONT_COOKIE_NAME)
|
||||
return fonts.includes(savedFont as Font) ? (savedFont as Font) : fonts[0]
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
const applyFont = (font: string) => {
|
||||
const root = document.documentElement
|
||||
root.classList.forEach((cls) => {
|
||||
if (cls.startsWith('font-')) root.classList.remove(cls)
|
||||
})
|
||||
root.classList.add(`font-${font}`)
|
||||
}
|
||||
|
||||
applyFont(font)
|
||||
}, [font])
|
||||
|
||||
const setFont = (font: Font) => {
|
||||
setCookie(FONT_COOKIE_NAME, font, FONT_COOKIE_MAX_AGE)
|
||||
_setFont(font)
|
||||
}
|
||||
|
||||
const resetFont = () => {
|
||||
removeCookie(FONT_COOKIE_NAME)
|
||||
_setFont(fonts[0])
|
||||
}
|
||||
|
||||
return (
|
||||
<FontContext value={{ font, setFont, resetFont }}>{children}</FontContext>
|
||||
)
|
||||
}
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export const useFont = () => {
|
||||
const context = useContext(FontContext)
|
||||
if (!context) {
|
||||
throw new Error('useFont must be used within a FontProvider')
|
||||
}
|
||||
return context
|
||||
}
|
||||
+8
-10
@@ -20,7 +20,7 @@ import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useLayoutEffect,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
@@ -133,11 +133,9 @@ export function ThemeCustomizationProvider(props: {
|
||||
)
|
||||
)
|
||||
|
||||
// Mirror state to <body> via data-* attributes before paint so theme-
|
||||
// presets.css can override CSS variables without a one-frame size/font flash.
|
||||
// useLayoutEffect (not useEffect) is required: useEffect runs after paint,
|
||||
// which is exactly when users see text jump from default → cookie scale/font.
|
||||
useLayoutEffect(() => {
|
||||
// Mirror state to the <body> via data-* attributes so theme-presets.css can
|
||||
// override CSS variables at the right cascade layer.
|
||||
useEffect(() => {
|
||||
applyAttribute(
|
||||
'data-theme-preset',
|
||||
preset === DEFAULT_THEME_CUSTOMIZATION.preset ? null : preset
|
||||
@@ -150,25 +148,25 @@ export function ThemeCustomizationProvider(props: {
|
||||
// Resolving here (instead of in CSS via `:not()` selectors) keeps the
|
||||
// stylesheet to one simple `[data-theme-font='serif']` selector and lets
|
||||
// future presets opt into typography via `PRESET_DEFAULT_FONT` alone.
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
applyAttribute('data-theme-font', resolveThemeFont(font, preset))
|
||||
}, [font, preset])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
applyAttribute(
|
||||
'data-theme-radius',
|
||||
radius === DEFAULT_THEME_CUSTOMIZATION.radius ? null : radius
|
||||
)
|
||||
}, [radius])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
applyAttribute(
|
||||
'data-theme-scale',
|
||||
scale === DEFAULT_THEME_CUSTOMIZATION.scale ? null : scale
|
||||
)
|
||||
}, [scale])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
applyAttribute('data-theme-content-layout', contentLayout)
|
||||
}, [contentLayout])
|
||||
|
||||
|
||||
+2
-3
@@ -20,7 +20,7 @@ import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useLayoutEffect,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react'
|
||||
@@ -88,8 +88,7 @@ export function ThemeProvider({
|
||||
resolveTheme(getStoredTheme(storageKey, defaultTheme))
|
||||
)
|
||||
|
||||
// Apply before paint to avoid a light→dark (or reverse) flash on load.
|
||||
useLayoutEffect(() => {
|
||||
useEffect(() => {
|
||||
const root = window.document.documentElement
|
||||
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user