このコミットが含まれているのは:
+18
-22
@@ -10,6 +10,10 @@
|
||||
{
|
||||
--background: 0 0% 100%;
|
||||
--foreground: 222.2 84% 4.9%;
|
||||
--card: 0 0% 100%;
|
||||
--card-foreground: 222.2 84% 4.9%;
|
||||
--popover: 0 0% 100%;
|
||||
--popover-foreground: 222.2 84% 4.9%;
|
||||
|
||||
--primary: 222.2 47.4% 11.2%;
|
||||
--primary-foreground: 210 40% 98%;
|
||||
@@ -29,6 +33,7 @@
|
||||
--border: 214.3 31.8% 91.4%;
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 222.2 84% 4.9%;
|
||||
--theme-link: 221.2 83.2% 53.3%;
|
||||
|
||||
--tag-colour-deerjikist: #9f1239;
|
||||
--tag-colour-deerjikist-hover: #b62a51;
|
||||
@@ -50,6 +55,10 @@
|
||||
{
|
||||
--background: 222.2 84% 4.9%;
|
||||
--foreground: 210 40% 98%;
|
||||
--card: 222.2 84% 4.9%;
|
||||
--card-foreground: 210 40% 98%;
|
||||
--popover: 222.2 84% 4.9%;
|
||||
--popover-foreground: 210 40% 98%;
|
||||
|
||||
--primary: 210 40% 98%;
|
||||
--primary-foreground: 222.2 47.4% 11.2%;
|
||||
@@ -73,16 +82,16 @@
|
||||
|
||||
body
|
||||
{
|
||||
@apply overflow-x-clip;
|
||||
@apply overflow-x-clip bg-background text-foreground;
|
||||
}
|
||||
|
||||
a
|
||||
{
|
||||
@apply text-blue-700 dark:text-blue-300;
|
||||
color: hsl(var(--theme-link));
|
||||
}
|
||||
a:hover
|
||||
{
|
||||
@apply text-blue-500 dark:text-blue-100;
|
||||
opacity: .85;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,8 +102,8 @@
|
||||
font-weight: 400;
|
||||
|
||||
color-scheme: light dark;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
background-color: #242424;
|
||||
color: hsl(var(--foreground));
|
||||
background-color: hsl(var(--background));
|
||||
|
||||
font-synthesis: none;
|
||||
text-rendering: optimizeLegibility;
|
||||
@@ -135,28 +144,15 @@ body
|
||||
{
|
||||
margin: 0;
|
||||
min-width: 320px;
|
||||
background: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
#root
|
||||
{
|
||||
min-height: 100dvh;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: light)
|
||||
{
|
||||
:root
|
||||
{
|
||||
color: #213547;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
a:hover
|
||||
{
|
||||
color: #747bff;
|
||||
}
|
||||
button
|
||||
{
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
background: hsl(var(--background));
|
||||
color: hsl(var(--foreground));
|
||||
}
|
||||
|
||||
@keyframes wiki-blink
|
||||
|
||||
+137
-16
@@ -14,12 +14,35 @@ export type BuiltinThemeId = 'light' | 'dark'
|
||||
export type ThemeId = BuiltinThemeId | `custom:${ string }`
|
||||
export type ActiveThemeId = ThemeId | 'system'
|
||||
export type ResolvedTheme = 'light' | 'dark'
|
||||
export type ThemeTokens = {
|
||||
background: string
|
||||
foreground: string
|
||||
card: string
|
||||
cardForeground: string
|
||||
popover: string
|
||||
popoverForeground: string
|
||||
primary: string
|
||||
primaryForeground: string
|
||||
secondary: string
|
||||
secondaryForeground: string
|
||||
muted: string
|
||||
mutedForeground: string
|
||||
accent: string
|
||||
accentForeground: string
|
||||
destructive: string
|
||||
destructiveForeground: string
|
||||
border: string
|
||||
input: string
|
||||
ring: string
|
||||
link: string
|
||||
tagColours: ThemeTagColours
|
||||
}
|
||||
export type ClientTheme = {
|
||||
id: ThemeId
|
||||
name: string
|
||||
builtin: boolean
|
||||
baseTheme: BuiltinThemeId
|
||||
tagColours: ThemeTagColours }
|
||||
tokens: ThemeTokens }
|
||||
export type CustomClientTheme =
|
||||
ClientTheme & { builtin: false }
|
||||
|
||||
@@ -119,20 +142,66 @@ export const DEFAULT_DARK_THEME_TAG_COLOURS: ThemeTagColours = {
|
||||
nico: '#e5e7eb',
|
||||
}
|
||||
export const DEFAULT_THEME_TAG_COLOURS = DEFAULT_LIGHT_THEME_TAG_COLOURS
|
||||
export const LIGHT_THEME_TOKENS: ThemeTokens = {
|
||||
background: '0 0% 100%',
|
||||
foreground: '222.2 84% 4.9%',
|
||||
card: '0 0% 100%',
|
||||
cardForeground: '222.2 84% 4.9%',
|
||||
popover: '0 0% 100%',
|
||||
popoverForeground: '222.2 84% 4.9%',
|
||||
primary: '222.2 47.4% 11.2%',
|
||||
primaryForeground: '210 40% 98%',
|
||||
secondary: '210 40% 96.1%',
|
||||
secondaryForeground: '222.2 47.4% 11.2%',
|
||||
muted: '210 40% 96.1%',
|
||||
mutedForeground: '215.4 16.3% 46.9%',
|
||||
accent: '210 40% 96.1%',
|
||||
accentForeground: '222.2 47.4% 11.2%',
|
||||
destructive: '0 72.2% 50.6%',
|
||||
destructiveForeground: '210 40% 98%',
|
||||
border: '214.3 31.8% 91.4%',
|
||||
input: '214.3 31.8% 91.4%',
|
||||
ring: '222.2 84% 4.9%',
|
||||
link: '221.2 83.2% 53.3%',
|
||||
tagColours: DEFAULT_LIGHT_THEME_TAG_COLOURS,
|
||||
}
|
||||
export const DARK_THEME_TOKENS: ThemeTokens = {
|
||||
background: '222.2 84% 4.9%',
|
||||
foreground: '210 40% 98%',
|
||||
card: '222.2 84% 4.9%',
|
||||
cardForeground: '210 40% 98%',
|
||||
popover: '222.2 84% 4.9%',
|
||||
popoverForeground: '210 40% 98%',
|
||||
primary: '210 40% 98%',
|
||||
primaryForeground: '222.2 47.4% 11.2%',
|
||||
secondary: '217.2 32.6% 17.5%',
|
||||
secondaryForeground: '210 40% 98%',
|
||||
muted: '217.2 32.6% 17.5%',
|
||||
mutedForeground: '215 20.2% 65.1%',
|
||||
accent: '217.2 32.6% 17.5%',
|
||||
accentForeground: '210 40% 98%',
|
||||
destructive: '0 62.8% 45%',
|
||||
destructiveForeground: '210 40% 98%',
|
||||
border: '217.2 32.6% 17.5%',
|
||||
input: '217.2 32.6% 17.5%',
|
||||
ring: '212.7 26.8% 83.9%',
|
||||
link: '213.1 93.9% 67.8%',
|
||||
tagColours: DEFAULT_DARK_THEME_TAG_COLOURS,
|
||||
}
|
||||
export const BUILTIN_THEMES: Record<BuiltinThemeId, ClientTheme> = {
|
||||
light: {
|
||||
id: 'light',
|
||||
name: 'ライト・モード',
|
||||
builtin: true,
|
||||
baseTheme: 'light',
|
||||
tagColours: DEFAULT_LIGHT_THEME_TAG_COLOURS,
|
||||
tokens: LIGHT_THEME_TOKENS,
|
||||
},
|
||||
dark: {
|
||||
id: 'dark',
|
||||
name: 'ダーク・モード',
|
||||
builtin: true,
|
||||
baseTheme: 'dark',
|
||||
tagColours: DEFAULT_DARK_THEME_TAG_COLOURS,
|
||||
tokens: DARK_THEME_TOKENS,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -369,10 +438,26 @@ const normaliseCustomTheme = (
|
||||
name,
|
||||
builtin: false,
|
||||
baseTheme,
|
||||
tagColours: normaliseThemeTagColours (
|
||||
theme.tagColours as Partial<ThemeTagColours> | undefined,
|
||||
defaultThemeTagColoursFor (baseTheme),
|
||||
),
|
||||
tokens: {
|
||||
...(
|
||||
baseTheme === 'dark'
|
||||
? DARK_THEME_TOKENS
|
||||
: LIGHT_THEME_TOKENS
|
||||
),
|
||||
...(theme.tokens && typeof theme.tokens === 'object'
|
||||
? theme.tokens as Partial<ThemeTokens>
|
||||
: { }),
|
||||
tagColours: normaliseThemeTagColours (
|
||||
(
|
||||
theme.tokens
|
||||
&& typeof theme.tokens === 'object'
|
||||
&& 'tagColours' in theme.tokens
|
||||
)
|
||||
? (theme.tokens as { tagColours?: Partial<ThemeTagColours> }).tagColours
|
||||
: theme.tagColours as Partial<ThemeTagColours> | undefined,
|
||||
defaultThemeTagColoursFor (baseTheme),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,10 +490,13 @@ export const getClientCustomThemes = (): Record<string, CustomClientTheme> => {
|
||||
name: themeCopyName (baseTheme),
|
||||
builtin: false,
|
||||
baseTheme,
|
||||
tagColours: normaliseThemeTagColours (
|
||||
legacyTagColours,
|
||||
defaultThemeTagColoursFor (baseTheme),
|
||||
),
|
||||
tokens: {
|
||||
...(baseTheme === 'dark' ? DARK_THEME_TOKENS : LIGHT_THEME_TOKENS),
|
||||
tagColours: normaliseThemeTagColours (
|
||||
legacyTagColours,
|
||||
defaultThemeTagColoursFor (baseTheme),
|
||||
),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -477,7 +565,7 @@ export const deriveUserThemeModeFromSelection = (
|
||||
|
||||
export const createCustomThemeFromBase = (
|
||||
baseTheme: BuiltinThemeId,
|
||||
tagColours?: ThemeTagColours,
|
||||
tokens?: ThemeTokens,
|
||||
): CustomClientTheme => {
|
||||
const id = `custom:${ crypto.randomUUID () }` as ThemeId
|
||||
return {
|
||||
@@ -485,7 +573,9 @@ export const createCustomThemeFromBase = (
|
||||
name: themeCopyName (baseTheme),
|
||||
builtin: false,
|
||||
baseTheme,
|
||||
tagColours: tagColours ?? { ...defaultThemeTagColoursFor (baseTheme) },
|
||||
tokens: tokens ?? {
|
||||
...(baseTheme === 'dark' ? DARK_THEME_TOKENS : LIGHT_THEME_TOKENS),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +585,7 @@ export const getClientThemeTagColours = (
|
||||
customThemes: Record<string, CustomClientTheme> = getClientCustomThemes (),
|
||||
): ThemeTagColours => {
|
||||
return {
|
||||
...getResolvedThemeFromSelection (activeThemeId, customThemes).tagColours,
|
||||
...getResolvedThemeFromSelection (activeThemeId, customThemes).tokens.tagColours,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +621,10 @@ export const setClientThemeTagColours = (
|
||||
...customThemes,
|
||||
[activeThemeId]: {
|
||||
...customThemes[activeThemeId],
|
||||
tagColours,
|
||||
tokens: {
|
||||
...customThemes[activeThemeId].tokens,
|
||||
tagColours,
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -561,13 +654,41 @@ export const applyThemeTagColours = (tagColours: ThemeTagColours): void => {
|
||||
}
|
||||
|
||||
|
||||
export const applyThemeTokens = (tokens: ThemeTokens): void => {
|
||||
const root = document.documentElement
|
||||
|
||||
root.style.setProperty ('--background', tokens.background)
|
||||
root.style.setProperty ('--foreground', tokens.foreground)
|
||||
root.style.setProperty ('--card', tokens.card)
|
||||
root.style.setProperty ('--card-foreground', tokens.cardForeground)
|
||||
root.style.setProperty ('--popover', tokens.popover)
|
||||
root.style.setProperty ('--popover-foreground', tokens.popoverForeground)
|
||||
root.style.setProperty ('--primary', tokens.primary)
|
||||
root.style.setProperty ('--primary-foreground', tokens.primaryForeground)
|
||||
root.style.setProperty ('--secondary', tokens.secondary)
|
||||
root.style.setProperty ('--secondary-foreground', tokens.secondaryForeground)
|
||||
root.style.setProperty ('--muted', tokens.muted)
|
||||
root.style.setProperty ('--muted-foreground', tokens.mutedForeground)
|
||||
root.style.setProperty ('--accent', tokens.accent)
|
||||
root.style.setProperty ('--accent-foreground', tokens.accentForeground)
|
||||
root.style.setProperty ('--destructive', tokens.destructive)
|
||||
root.style.setProperty ('--destructive-foreground', tokens.destructiveForeground)
|
||||
root.style.setProperty ('--border', tokens.border)
|
||||
root.style.setProperty ('--input', tokens.input)
|
||||
root.style.setProperty ('--ring', tokens.ring)
|
||||
root.style.setProperty ('--theme-link', tokens.link)
|
||||
|
||||
applyThemeTagColours (tokens.tagColours)
|
||||
}
|
||||
|
||||
|
||||
export const applyThemeSelection = (
|
||||
activeThemeId: ActiveThemeId,
|
||||
customThemes: Record<string, CustomClientTheme>,
|
||||
): void => {
|
||||
const theme = getResolvedThemeFromSelection (activeThemeId, customThemes)
|
||||
applyThemeMode (theme.baseTheme)
|
||||
applyThemeTagColours (theme.tagColours)
|
||||
applyThemeTokens (theme.tokens)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
||||
() => getResolvedThemeFromSelection (draftActiveThemeId, draftCustomThemes),
|
||||
[draftActiveThemeId, draftCustomThemes],
|
||||
)
|
||||
const draftTagColours = selectedTheme.tagColours
|
||||
const draftTagColours = selectedTheme.tokens.tagColours
|
||||
|
||||
const setActiveTab = (tab: SettingsTab) => {
|
||||
const params = new URLSearchParams (location.search)
|
||||
@@ -498,7 +498,10 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
||||
|
||||
const customTheme = createCustomThemeFromBase (
|
||||
selectedTheme.baseTheme,
|
||||
{ ...selectedTheme.tagColours },
|
||||
{
|
||||
...selectedTheme.tokens,
|
||||
tagColours: { ...selectedTheme.tokens.tagColours },
|
||||
},
|
||||
)
|
||||
const nextCustomThemes = {
|
||||
...draftCustomThemes,
|
||||
@@ -681,9 +684,12 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
||||
...editable.customThemes,
|
||||
[editable.activeThemeId]: {
|
||||
...editableTheme,
|
||||
tagColours: {
|
||||
...editableTheme.tagColours,
|
||||
[category]: colour,
|
||||
tokens: {
|
||||
...editableTheme.tokens,
|
||||
tagColours: {
|
||||
...editableTheme.tokens.tagColours,
|
||||
[category]: colour,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -699,8 +705,11 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
||||
...draftCustomThemes,
|
||||
[draftActiveThemeId]: {
|
||||
...draftCustomThemes[draftActiveThemeId],
|
||||
tagColours: {
|
||||
...defaultThemeTagColoursFor (selectedTheme.baseTheme),
|
||||
tokens: {
|
||||
...draftCustomThemes[draftActiveThemeId].tokens,
|
||||
tagColours: {
|
||||
...defaultThemeTagColoursFor (selectedTheme.baseTheme),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -716,10 +725,13 @@ const SettingPage: FC<Props> = ({ user, setUser }) => {
|
||||
...draftCustomThemes,
|
||||
[draftActiveThemeId]: {
|
||||
...draftCustomThemes[draftActiveThemeId],
|
||||
tagColours: {
|
||||
...draftCustomThemes[draftActiveThemeId].tagColours,
|
||||
[category]:
|
||||
defaultThemeTagColoursFor (selectedTheme.baseTheme)[category],
|
||||
tokens: {
|
||||
...draftCustomThemes[draftActiveThemeId].tokens,
|
||||
tagColours: {
|
||||
...draftCustomThemes[draftActiveThemeId].tokens.tagColours,
|
||||
[category]:
|
||||
defaultThemeTagColoursFor (selectedTheme.baseTheme)[category],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
新しい課題から参照
ユーザをブロックする