diff --git a/frontend/public/translations/en.json b/frontend/public/translations/en.json index 74392e410..990c15f45 100644 --- a/frontend/public/translations/en.json +++ b/frontend/public/translations/en.json @@ -238,7 +238,9 @@ "stopImpersonating": "Stop Impersonating", "openInVirtualWindow": "Open in Virtual Window", "openInPopup": "Open in Popup", - "openInNewTab": "Open in New Tab" + "openInNewTab": "Open in New Tab", + "switchToDark": "Switch to Dark Mode", + "switchToLight": "Switch to Light Mode" } }, "permissionSelector": { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 4de042aa6..aa2c1ea6e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,4 +1,4 @@ -import { MantineProvider, type MantineThemeOverride, v8CssVariablesResolver } from '@mantine/core'; +import { MantineProvider, type MantineThemeOverride } from '@mantine/core'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { ReactQueryDevtools } from '@tanstack/react-query-devtools'; import { createBrowserHistory } from 'history'; @@ -96,12 +96,7 @@ export default function App({ theme }: { theme: MantineThemeOverride }) { return Object.keys(settings).length > 0 ? ( - + diff --git a/frontend/src/app.css b/frontend/src/app.css index f747a1c87..f14daf883 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,4 +1,8 @@ @import "tailwindcss"; +@import "highlight.js/styles/a11y-light.min.css"; + +@custom-variant dark (&:where([data-mantine-color-scheme="dark"], [data-mantine-color-scheme="dark"] *)); +@custom-variant light (&:where([data-mantine-color-scheme="light"], [data-mantine-color-scheme="light"] *)); @font-face { font-family: "Helvetica"; @@ -40,8 +44,14 @@ } } +:root[data-mantine-color-scheme="light"] { + --mantine-color-body: #f0eff0; +} + body { - @apply font-sans bg-neutral-850 text-neutral-200; + @apply font-sans; + background-color: var(--mantine-color-body); + color: var(--mantine-color-text); } h1, @@ -54,7 +64,8 @@ h6 { } p { - @apply text-neutral-200 leading-snug font-sans; + @apply leading-snug font-sans; + color: var(--mantine-color-text); } form { @@ -73,3 +84,50 @@ button:focus-visible { strong { @apply font-semibold; } + +[data-mantine-color-scheme="dark"] { + .hljs { + background: #2b2b2b; + color: #f8f8f2; + } + .hljs-comment, + .hljs-quote { + color: #d4d0ab; + } + .hljs-deletion, + .hljs-name, + .hljs-regexp, + .hljs-selector-class, + .hljs-selector-id, + .hljs-tag, + .hljs-template-variable, + .hljs-variable { + color: #ffa07a; + } + .hljs-built_in, + .hljs-link, + .hljs-literal, + .hljs-meta, + .hljs-number, + .hljs-params, + .hljs-type { + color: #f5ab35; + } + .hljs-attribute { + color: gold; + } + .hljs-addition, + .hljs-bullet, + .hljs-string, + .hljs-symbol { + color: #abe338; + } + .hljs-section, + .hljs-title { + color: #00e0e0; + } + .hljs-keyword, + .hljs-selector-tag { + color: #dcc6e0; + } +} diff --git a/frontend/src/elements/Button.tsx b/frontend/src/elements/Button.tsx index 842b17408..fdae4e38a 100644 --- a/frontend/src/elements/Button.tsx +++ b/frontend/src/elements/Button.tsx @@ -22,7 +22,7 @@ const Button = forwardRef( style={{ cursor: loading ? 'wait' : undefined, fontWeight: 'normal', - border: disabled ? '1px solid var(--mantine-color-dark-4)' : undefined, + border: disabled ? '1px solid var(--mantine-color-default-border)' : undefined, color: disabled ? 'var(--mantine-color-dimmed)' : undefined, ...rest.style, }} diff --git a/frontend/src/elements/Card.tsx b/frontend/src/elements/Card.tsx index b8af51848..08104ef4c 100644 --- a/frontend/src/elements/Card.tsx +++ b/frontend/src/elements/Card.tsx @@ -16,7 +16,7 @@ const Card = forwardRef>( className={classNames( 'relative', className, - hoverable && 'transition-all! duration-190 hover:border-white/25! cursor-pointer', + hoverable && 'transition-all! duration-190 hover:border-(--mantine-color-default-border)/20! cursor-pointer', )} pl={typeof pl === 'number' && leftStripeClassName ? pl + 4 : leftStripeClassName ? 20 : pl} radius='md' diff --git a/frontend/src/elements/CollapsibleSection.tsx b/frontend/src/elements/CollapsibleSection.tsx index dbf056875..d45e4efd2 100644 --- a/frontend/src/elements/CollapsibleSection.tsx +++ b/frontend/src/elements/CollapsibleSection.tsx @@ -17,8 +17,8 @@ function CollapsibleSection({ icon, title, className, enabled, onToggle, childre {icon} - + {title} {
{error && appDebug && ( -
+
@@ -98,7 +98,7 @@ class ErrorBoundary extends Component {

{this.context?.t('elements.errorBoundary.stackTrace', {}) || 'Stack Trace:'}

-
+                        
                           {error.stack}
                         
@@ -109,7 +109,7 @@ class ErrorBoundary extends Component {

{this.context?.t('elements.errorBoundary.componentStack', {}) || 'Component Stack:'}

-
+                        
                           {errorInfo.componentStack}
                         
diff --git a/frontend/src/elements/HljsCode.tsx b/frontend/src/elements/HljsCode.tsx index dfcf7cc14..3b186e5d3 100644 --- a/frontend/src/elements/HljsCode.tsx +++ b/frontend/src/elements/HljsCode.tsx @@ -1,7 +1,6 @@ +import { LanguageFn } from 'highlight.js'; import hljs from 'highlight.js/lib/core'; import { forwardRef, useCallback, useEffect, useState } from 'react'; -import 'highlight.js/styles/a11y-dark.min.css'; -import { LanguageFn } from 'highlight.js'; import Spinner from '@/elements/Spinner.tsx'; import Code from './Code.tsx'; diff --git a/frontend/src/elements/KbdKey.tsx b/frontend/src/elements/KbdKey.tsx index 81ee68647..934132642 100644 --- a/frontend/src/elements/KbdKey.tsx +++ b/frontend/src/elements/KbdKey.tsx @@ -13,7 +13,7 @@ function KbdKey({ children, className, icon }: KbdKeyProps) { return (
diff --git a/frontend/src/elements/MonacoEditor.tsx b/frontend/src/elements/MonacoEditor.tsx index 602003a79..05339d829 100644 --- a/frontend/src/elements/MonacoEditor.tsx +++ b/frontend/src/elements/MonacoEditor.tsx @@ -1,3 +1,4 @@ +import { useComputedColorScheme } from '@mantine/core'; import { Editor, loader } from '@monaco-editor/react'; import { ComponentProps } from 'react'; @@ -8,9 +9,12 @@ loader.config({ }); export default function MonacoEditor(props: ComponentProps) { + const computedColorScheme = useComputedColorScheme('dark'); + return ( { for (const handler of window.extensionContext.extensionRegistry.elements.monacoEditor.onMountHandlers) { handler(e, m); diff --git a/frontend/src/elements/PermissionSelector.tsx b/frontend/src/elements/PermissionSelector.tsx index 6342dd8cf..443b2114f 100644 --- a/frontend/src/elements/PermissionSelector.tsx +++ b/frontend/src/elements/PermissionSelector.tsx @@ -111,18 +111,18 @@ export default function PermissionSelector({ const selectedPanel = ( - + <Title order={3}> {t('elements.permissionSelector.selectedPermissions', { count: selectedPermissions.length })}
{selectedPermissions.length === 0 ? ( -

{t('elements.permissionSelector.noPermissions', {})}

+

{t('elements.permissionSelector.noPermissions', {})}

) : (
{sortedSelectedPermissions.map((permission) => ( - + - {permission} + {permission} togglePermission(permission)}> @@ -170,7 +170,7 @@ export default function PermissionSelector({ /> )}
- + <Title order={5} className='uppercase'> {category.replaceAll('-', ' ')}

{description}

@@ -184,9 +184,9 @@ export default function PermissionSelector({ /> toggleCategory(category)}> {isExpanded ? ( - + ) : ( - + )}
diff --git a/frontend/src/elements/ScreenBlock.tsx b/frontend/src/elements/ScreenBlock.tsx index 7297f9725..123371d7b 100644 --- a/frontend/src/elements/ScreenBlock.tsx +++ b/frontend/src/elements/ScreenBlock.tsx @@ -8,7 +8,7 @@ function ScreenBlock({ title, content }: { title: string; content: string }) {
{title} -

{content}

+

{content}

diff --git a/frontend/src/elements/ServerStatusIndicator.tsx b/frontend/src/elements/ServerStatusIndicator.tsx index 6b6a92947..110202744 100644 --- a/frontend/src/elements/ServerStatusIndicator.tsx +++ b/frontend/src/elements/ServerStatusIndicator.tsx @@ -94,15 +94,15 @@ export default function ServerStatusIndicator() { {socketConnected ? ( <> - {t(`common.enum.serverState.${state}`, {})} + {t(`common.enum.serverState.${state}`, {})} ) : ( <> - + {socketConnected ? t('common.enum.connectionStatus.connected', {}) : t('common.enum.connectionStatus.offline', {})} diff --git a/frontend/src/elements/Sidebar.tsx b/frontend/src/elements/Sidebar.tsx index 34000c4ca..2bae715e1 100644 --- a/frontend/src/elements/Sidebar.tsx +++ b/frontend/src/elements/Sidebar.tsx @@ -3,12 +3,14 @@ import { faBars, faEllipsisVertical, faGraduationCap, + faMoon, + faSun, faUserCog, faWindowRestore, IconDefinition, } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { Menu } from '@mantine/core'; +import { Menu, useComputedColorScheme, useMantineColorScheme } from '@mantine/core'; import classNames from 'classnames'; import { ReactNode, useEffect, useState } from 'react'; import { MemoryRouter, matchPath, NavLink, useLocation, useNavigate } from 'react-router'; @@ -150,7 +152,7 @@ function Link({ to, end, icon, name, title = name, className, activeMatches }: L