From 820741c80b3e233ee59f62b0e779af7b2983e762 Mon Sep 17 00:00:00 2001 From: Lorchie Date: Mon, 1 Jun 2026 20:46:59 +0200 Subject: [PATCH 1/2] feat(settings): accessibility section --- src/App.tsx | 16 ++- src/areas/settings/SettingsPage.tsx | 38 +++++--- .../components/AccessibilitySection.tsx | 40 ++++++++ .../AtkinsonHyperlegible-Bold.woff2 | Bin 0 -> 23776 bytes .../AtkinsonHyperlegible-Regular.woff2 | Bin 0 -> 23196 bytes .../fonts/atkinson-hyperlegible/OFL.txt | 92 ++++++++++++++++++ src/shared/stores/appStore.ts | 13 +++ src/shared/ui/index.tsx | 27 +++++ src/styles/globals.css | 27 ++++- 9 files changed, 239 insertions(+), 14 deletions(-) create mode 100644 src/areas/settings/components/AccessibilitySection.tsx create mode 100644 src/assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Bold.woff2 create mode 100644 src/assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Regular.woff2 create mode 100644 src/assets/fonts/atkinson-hyperlegible/OFL.txt diff --git a/src/App.tsx b/src/App.tsx index 9ef3edc..0555a68 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -6,8 +6,11 @@ import { UpdateModal } from '@shared/components/ui/UpdateModal' import { ErrorModal } from '@shared/components/ui/ErrorModal' import { Toast } from '@shared/components/ui/Toast' +type TextSize = 'small' | 'medium' | 'large' +const TEXT_SIZE_SCALE: Record = { small: 0.875, medium: 1, large: 1.25 } + export default function App(): JSX.Element { - const { checkSetup, setupStatus, initApp, backendStatus, showError } = useAppStore() + const { checkSetup, setupStatus, initApp, backendStatus, showError, useAtkinsonFont, textSize } = useAppStore() const [updateVersion, setUpdateVersion] = useState(null) const [currentVersion, setCurrentVersion] = useState('') @@ -23,6 +26,17 @@ export default function App(): JSX.Element { } }, []) + useEffect(() => { + const root = document.documentElement + root.style.setProperty( + '--app-font', + useAtkinsonFont + ? "'Atkinson Hyperlegible', system-ui, sans-serif" + : "'Inter', system-ui, sans-serif" + ) + root.style.setProperty('--app-font-scale', String(TEXT_SIZE_SCALE[textSize as TextSize])) + }, [useAtkinsonFont, textSize]) + useEffect(() => { if (setupStatus === 'done') initApp() }, [setupStatus]) diff --git a/src/areas/settings/SettingsPage.tsx b/src/areas/settings/SettingsPage.tsx index dbd9f23..d76f462 100644 --- a/src/areas/settings/SettingsPage.tsx +++ b/src/areas/settings/SettingsPage.tsx @@ -1,12 +1,13 @@ import { useState } from 'react' -import { StorageSection } from './components/StorageSection' -import { AboutSection } from './components/AboutSection' -import { LogsSection } from './components/LogsSection' -import { IntegrationsSection } from './components/IntegrationsSection' -import { AgentSection } from './components/AgentSection' -import { ApplicationSection } from './components/ApplicationSection' +import { StorageSection } from './components/StorageSection' +import { AboutSection } from './components/AboutSection' +import { LogsSection } from './components/LogsSection' +import { IntegrationsSection } from './components/IntegrationsSection' +import { AgentSection } from './components/AgentSection' +import { ApplicationSection } from './components/ApplicationSection' +import { AccessibilitySection } from './components/AccessibilitySection' -type Section = 'application' | 'storage' | 'integrations' | 'agent' | 'logs' | 'about' +type Section = 'application' | 'storage' | 'integrations' | 'accessibility' | 'agent' | 'logs' | 'about' const SECTIONS: { id: Section; label: string; icon: JSX.Element }[] = [ { @@ -41,6 +42,18 @@ const SECTIONS: { id: Section; label: string; icon: JSX.Element }[] = [ ) }, + { + id: 'accessibility', + label: 'Accessibility', + icon: ( + + + + + + + ) + }, { id: 'agent', label: 'Agent', @@ -109,11 +122,12 @@ export default function SettingsPage(): JSX.Element {
{section === 'application' && } - {section === 'storage' && } - {section === 'integrations' && } - {section === 'agent' && } - {section === 'logs' && } - {section === 'about' && } + {section === 'storage' && } + {section === 'integrations' && } + {section === 'accessibility' && } + {section === 'agent' && } + {section === 'logs' && } + {section === 'about' && }
diff --git a/src/areas/settings/components/AccessibilitySection.tsx b/src/areas/settings/components/AccessibilitySection.tsx new file mode 100644 index 0000000..ea17a86 --- /dev/null +++ b/src/areas/settings/components/AccessibilitySection.tsx @@ -0,0 +1,40 @@ +import { useAppStore } from '@shared/stores/appStore' +import { Section, Card, Row, Toggle, SegmentedControl } from '@shared/ui' + +export function AccessibilitySection(): JSX.Element { + const { useAtkinsonFont, setUseAtkinsonFont, textSize, setTextSize } = useAppStore() + + return ( +
+
+ + + + + + + + + + + + + +
+
+ ) +} diff --git a/src/assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Bold.woff2 b/src/assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Bold.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..3edf0a1744657b6d78ac106e21b63044ac9f1bac GIT binary patch literal 23776 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

h=>&yTEk~BKt|;&-`G2uV)S3*&wW? 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 T(?3GrZQ9%{x8g6Hnu6q8V94nX literal 0 HcmV?d00001 diff --git a/src/assets/fonts/atkinson-hyperlegible/OFL.txt b/src/assets/fonts/atkinson-hyperlegible/OFL.txt new file mode 100644 index 0000000..2befc89 --- /dev/null +++ b/src/assets/fonts/atkinson-hyperlegible/OFL.txt @@ -0,0 +1,92 @@ +Copyright 2020 Braille Institute of America, Inc. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/shared/stores/appStore.ts b/src/shared/stores/appStore.ts index 84759a0..d6f4ca8 100644 --- a/src/shared/stores/appStore.ts +++ b/src/shared/stores/appStore.ts @@ -111,6 +111,12 @@ interface AppState { showRamIndicator: boolean setShowRamIndicator: (v: boolean) => void + // Accessibility + useAtkinsonFont: boolean + setUseAtkinsonFont: (v: boolean) => void + textSize: 'small' | 'medium' | 'large' + setTextSize: (v: 'small' | 'medium' | 'large') => void + // Actions initApp: () => Promise setCurrentJob: (job: GenerationJob | null) => void @@ -205,6 +211,11 @@ export const useAppStore = create()( showRamIndicator: true, setShowRamIndicator: (v) => set({ showRamIndicator: v }), + useAtkinsonFont: false, + setUseAtkinsonFont: (v) => set({ useAtkinsonFont: v }), + textSize: 'medium', + setTextSize: (v) => set({ textSize: v }), + currentJob: null, selectedImagePath: null, setSelectedImagePath: (path) => set({ selectedImagePath: path }), @@ -254,6 +265,8 @@ export const useAppStore = create()( partialize: (state) => ({ generationOptions: state.generationOptions, showRamIndicator: state.showRamIndicator, + useAtkinsonFont: state.useAtkinsonFont, + textSize: state.textSize, }), } ) diff --git a/src/shared/ui/index.tsx b/src/shared/ui/index.tsx index 9fba52d..80e8d00 100644 --- a/src/shared/ui/index.tsx +++ b/src/shared/ui/index.tsx @@ -110,6 +110,33 @@ export function Select({ value, onChange, options }: { ) } +export function SegmentedControl({ value, onChange, options }: { + value: T + onChange: (v: T) => void + options: { value: T; label: string }[] +}): JSX.Element { + return ( +

+ ) +} + export function LinkButton({ label, href }: { label: string; href?: string }): JSX.Element { const handleClick = (): void => { if (href) window.open(href, '_blank') diff --git a/src/styles/globals.css b/src/styles/globals.css index 70ff358..fe9143a 100644 --- a/src/styles/globals.css +++ b/src/styles/globals.css @@ -1,16 +1,41 @@ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); +@font-face { + font-family: 'Atkinson Hyperlegible'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url('../assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Regular.woff2') format('woff2'); +} + +@font-face { + font-family: 'Atkinson Hyperlegible'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url('../assets/fonts/atkinson-hyperlegible/AtkinsonHyperlegible-Bold.woff2') format('woff2'); +} + @tailwind base; @tailwind components; @tailwind utilities; @layer base { + :root { + --app-font: 'Inter', system-ui, sans-serif; + --app-font-scale: 1; + } + * { box-sizing: border-box; margin: 0; padding: 0; } + html { + font-size: calc(16px * var(--app-font-scale)); + } + html, body, #root { @@ -19,7 +44,7 @@ overflow: hidden; background-color: #111113; color: #f4f4f5; - font-family: 'Inter', system-ui, sans-serif; + font-family: var(--app-font); -webkit-font-smoothing: antialiased; user-select: none; } From b9cb1df3c57ca6b0a80ed23e7e96345250a9afa9 Mon Sep 17 00:00:00 2001 From: Lorchie Date: Tue, 2 Jun 2026 18:39:03 +0200 Subject: [PATCH 2/2] feat(accessibility): interface scale via webFrame zoom + a11y on SegmentedControl --- electron/preload/index.ts | 7 ++++++- src/App.tsx | 19 +++++++++---------- src/areas/settings/SettingsPage.tsx | 12 ++++++------ .../components/AccessibilitySection.tsx | 11 ++++++----- src/shared/stores/appStore.ts | 11 ++++++----- src/shared/types/electron.d.ts | 3 +++ src/shared/ui/index.tsx | 7 +++++-- src/styles/globals.css | 5 ----- 8 files changed, 41 insertions(+), 34 deletions(-) diff --git a/electron/preload/index.ts b/electron/preload/index.ts index 9c41673..0962a36 100644 --- a/electron/preload/index.ts +++ b/electron/preload/index.ts @@ -1,4 +1,4 @@ -import { contextBridge, ipcRenderer } from 'electron' +import { contextBridge, ipcRenderer, webFrame } from 'electron' // Expose a typed API to the renderer process via window.electron contextBridge.exposeInMainWorld('electron', { @@ -9,6 +9,11 @@ contextBridge.exposeInMainWorld('electron', { close: () => ipcRenderer.send('window:close') }, + // Renderer UI (zoom whole page — scales every px/rem consistently) + ui: { + setZoomFactor: (factor: number) => webFrame.setZoomFactor(factor), + }, + // Shell utilities shell: { openExternal: (url: string) => ipcRenderer.invoke('shell:openExternal', url), diff --git a/src/App.tsx b/src/App.tsx index 0555a68..6409b76 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,16 +1,15 @@ -import { useEffect, useState } from 'react' -import { useAppStore } from '@shared/stores/appStore' +import { useEffect, useLayoutEffect, useState } from 'react' +import { useAppStore, type UiScale } from '@shared/stores/appStore' import FirstRunSetup from '@areas/setup/FirstRunSetup' import MainLayout from '@shared/components/layout/MainLayout' import { UpdateModal } from '@shared/components/ui/UpdateModal' import { ErrorModal } from '@shared/components/ui/ErrorModal' import { Toast } from '@shared/components/ui/Toast' -type TextSize = 'small' | 'medium' | 'large' -const TEXT_SIZE_SCALE: Record = { small: 0.875, medium: 1, large: 1.25 } +const UI_SCALE_FACTORS: Record = { small: 0.875, medium: 1, large: 1.25 } export default function App(): JSX.Element { - const { checkSetup, setupStatus, initApp, backendStatus, showError, useAtkinsonFont, textSize } = useAppStore() + const { checkSetup, setupStatus, initApp, backendStatus, showError, useAtkinsonFont, uiScale } = useAppStore() const [updateVersion, setUpdateVersion] = useState(null) const [currentVersion, setCurrentVersion] = useState('') @@ -26,16 +25,16 @@ export default function App(): JSX.Element { } }, []) - useEffect(() => { - const root = document.documentElement - root.style.setProperty( + // Apply before paint to avoid a flash of default font/size on launch. + useLayoutEffect(() => { + document.documentElement.style.setProperty( '--app-font', useAtkinsonFont ? "'Atkinson Hyperlegible', system-ui, sans-serif" : "'Inter', system-ui, sans-serif" ) - root.style.setProperty('--app-font-scale', String(TEXT_SIZE_SCALE[textSize as TextSize])) - }, [useAtkinsonFont, textSize]) + window.electron.ui.setZoomFactor(UI_SCALE_FACTORS[uiScale]) + }, [useAtkinsonFont, uiScale]) useEffect(() => { if (setupStatus === 'done') initApp() diff --git a/src/areas/settings/SettingsPage.tsx b/src/areas/settings/SettingsPage.tsx index d76f462..d819994 100644 --- a/src/areas/settings/SettingsPage.tsx +++ b/src/areas/settings/SettingsPage.tsx @@ -1,10 +1,10 @@ import { useState } from 'react' -import { StorageSection } from './components/StorageSection' -import { AboutSection } from './components/AboutSection' -import { LogsSection } from './components/LogsSection' -import { IntegrationsSection } from './components/IntegrationsSection' -import { AgentSection } from './components/AgentSection' -import { ApplicationSection } from './components/ApplicationSection' +import { StorageSection } from './components/StorageSection' +import { AboutSection } from './components/AboutSection' +import { LogsSection } from './components/LogsSection' +import { IntegrationsSection } from './components/IntegrationsSection' +import { AgentSection } from './components/AgentSection' +import { ApplicationSection } from './components/ApplicationSection' import { AccessibilitySection } from './components/AccessibilitySection' type Section = 'application' | 'storage' | 'integrations' | 'accessibility' | 'agent' | 'logs' | 'about' diff --git a/src/areas/settings/components/AccessibilitySection.tsx b/src/areas/settings/components/AccessibilitySection.tsx index ea17a86..0d9c363 100644 --- a/src/areas/settings/components/AccessibilitySection.tsx +++ b/src/areas/settings/components/AccessibilitySection.tsx @@ -2,7 +2,7 @@ import { useAppStore } from '@shared/stores/appStore' import { Section, Card, Row, Toggle, SegmentedControl } from '@shared/ui' export function AccessibilitySection(): JSX.Element { - const { useAtkinsonFont, setUseAtkinsonFont, textSize, setTextSize } = useAppStore() + const { useAtkinsonFont, setUseAtkinsonFont, uiScale, setUiScale } = useAppStore() return (
@@ -17,14 +17,15 @@ export function AccessibilitySection(): JSX.Element { - + void - textSize: 'small' | 'medium' | 'large' - setTextSize: (v: 'small' | 'medium' | 'large') => void + uiScale: UiScale + setUiScale: (v: UiScale) => void // Actions initApp: () => Promise @@ -213,8 +214,8 @@ export const useAppStore = create()( useAtkinsonFont: false, setUseAtkinsonFont: (v) => set({ useAtkinsonFont: v }), - textSize: 'medium', - setTextSize: (v) => set({ textSize: v }), + uiScale: 'medium', + setUiScale: (v) => set({ uiScale: v }), currentJob: null, selectedImagePath: null, @@ -266,7 +267,7 @@ export const useAppStore = create()( generationOptions: state.generationOptions, showRamIndicator: state.showRamIndicator, useAtkinsonFont: state.useAtkinsonFont, - textSize: state.textSize, + uiScale: state.uiScale, }), } ) diff --git a/src/shared/types/electron.d.ts b/src/shared/types/electron.d.ts index ac21327..1ed1ee2 100644 --- a/src/shared/types/electron.d.ts +++ b/src/shared/types/electron.d.ts @@ -119,6 +119,9 @@ declare global { maximize: () => void close: () => void } + ui: { + setZoomFactor: (factor: number) => void + } python: { start: () => Promise<{ success: boolean; port?: number; error?: string }> status: () => Promise<{ ready: boolean; apiUrl: string }> diff --git a/src/shared/ui/index.tsx b/src/shared/ui/index.tsx index 80e8d00..a960999 100644 --- a/src/shared/ui/index.tsx +++ b/src/shared/ui/index.tsx @@ -110,18 +110,21 @@ export function Select({ value, onChange, options }: { ) } -export function SegmentedControl({ value, onChange, options }: { +export function SegmentedControl({ value, onChange, options, ariaLabel }: { value: T onChange: (v: T) => void options: { value: T; label: string }[] + ariaLabel?: string }): JSX.Element { return ( -
+
{options.map((o) => { const active = o.value === value return (