Skip to content

Commit

Permalink
Desktop: Accessibility: Allow increasing scrollbar and checkbox sizes
Browse files Browse the repository at this point in the history
  • Loading branch information
personalizedrefrigerator committed Jan 11, 2025
1 parent e9ee8c8 commit 91dc830
Show file tree
Hide file tree
Showing 16 changed files with 95 additions and 15 deletions.
2 changes: 1 addition & 1 deletion .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,7 @@ packages/app-desktop/gui/Sidebar/listItemComponents/TagItem.js
packages/app-desktop/gui/Sidebar/styles/index.js
packages/app-desktop/gui/Sidebar/types.js
packages/app-desktop/gui/StatusScreen/StatusScreen.js
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js
packages/app-desktop/gui/StyleSheets/AppStyles.js
packages/app-desktop/gui/SyncWizard/Dialog.js
packages/app-desktop/gui/TagItem.js
packages/app-desktop/gui/TagList.js
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ packages/app-desktop/gui/Sidebar/listItemComponents/TagItem.js
packages/app-desktop/gui/Sidebar/styles/index.js
packages/app-desktop/gui/Sidebar/types.js
packages/app-desktop/gui/StatusScreen/StatusScreen.js
packages/app-desktop/gui/StyleSheets/StyleSheetContainer.js
packages/app-desktop/gui/StyleSheets/AppStyles.js
packages/app-desktop/gui/SyncWizard/Dialog.js
packages/app-desktop/gui/TagItem.js
packages/app-desktop/gui/TagList.js
Expand Down
4 changes: 2 additions & 2 deletions packages/app-desktop/gui/NoteEditor/EditorWindow.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import { useCallback, useMemo, useRef, useState } from 'react';
import NoteEditor from './NoteEditor';
import StyleSheetContainer from '../StyleSheets/StyleSheetContainer';
import AppStyles from '../StyleSheets/AppStyles';
import { connect } from 'react-redux';
import { AppState } from '../../app.reducer';
import { Dispatch } from 'redux';
Expand Down Expand Up @@ -79,7 +79,7 @@ const SecondaryWindow: React.FC<Props> = props => {
<WindowCommandsAndDialogs windowId={props.windowId} />
{editor}
</LibraryStyleRoot>
<StyleSheetContainer />
<AppStyles />
</NewWindowOrIFrame>;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {

const allAssetsOptions: NoteStyleOptions = {
contentMaxWidthTarget: '.mce-content-body',
increaseControlsSize: props.increaseControlSize,
themeId: props.contentMarkupLanguage === MarkupLanguage.Html ? 1 : null,
whiteBackgroundNoteRendering: props.whiteBackgroundNoteRendering,
};
Expand All @@ -1051,7 +1052,7 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
cancelled = true;
};
// eslint-disable-next-line @seiyab/react-hooks/exhaustive-deps -- Old code before rule was applied
}, [editor, props.themeId, props.markupToHtml, props.allAssets, props.content, props.resourceInfos, props.contentKey, props.contentMarkupLanguage, props.whiteBackgroundNoteRendering]);
}, [editor, props.themeId, props.increaseControlSize, props.markupToHtml, props.allAssets, props.content, props.resourceInfos, props.contentKey, props.contentMarkupLanguage, props.whiteBackgroundNoteRendering]);

useEffect(() => {
if (!editor) return () => {};
Expand Down
6 changes: 5 additions & 1 deletion packages/app-desktop/gui/NoteEditor/NoteEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ function NoteEditorContent(props: NoteEditorProps) {
whiteBackgroundNoteRendering,
customCss: props.customCss,
plugins: props.plugins,
increaseControlsSize: props.increaseControlsSize,
settingValue: getPluginSettingValue,
});

Expand All @@ -200,9 +201,10 @@ function NoteEditorContent(props: NoteEditorProps) {
return markupToHtml.allAssets(markupLanguage, theme, {
contentMaxWidth: props.contentMaxWidth,
contentMaxWidthTarget: options.contentMaxWidthTarget,
increaseControlsSize: props.increaseControlsSize,
whiteBackgroundNoteRendering: options.whiteBackgroundNoteRendering,
});
}, [props.themeId, props.customCss, props.contentMaxWidth]);
}, [props.themeId, props.increaseControlsSize, props.customCss, props.contentMaxWidth]);

const handleProvisionalFlag = useCallback(() => {
if (props.isProvisional) {
Expand Down Expand Up @@ -494,6 +496,7 @@ function NoteEditorContent(props: NoteEditorProps) {
plugins: props.plugins,
fontSize: Setting.value('style.editor.fontSize'),
contentMaxWidth: props.contentMaxWidth,
increaseControlSize: props.increaseControlsSize,
isSafeMode: props.isSafeMode,
useCustomPdfViewer: props.useCustomPdfViewer,
// We need it to identify the context for which media is rendered.
Expand Down Expand Up @@ -747,6 +750,7 @@ const mapStateToProps = (state: AppState, ownProps: ConnectProps) => {
'setTags',
], whenClauseContext)[0] as ToolbarButtonInfo,
contentMaxWidth: state.settings['style.editor.contentMaxWidth'],
increaseControlsSize: state.settings['style.increaseControlSize'],
isSafeMode: state.settings.isSafeMode,
useCustomPdfViewer: false,
syncUserId: state.settings['sync.userId'],
Expand Down
4 changes: 4 additions & 0 deletions packages/app-desktop/gui/NoteEditor/utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export interface NoteEditorProps {
toolbarButtonInfos: ToolbarItem[];
setTagsToolbarButtonInfo: ToolbarButtonInfo;
contentMaxWidth: number;
increaseControlsSize: boolean;
isSafeMode: boolean;
useCustomPdfViewer: boolean;
shareCacheSetting: string;
Expand All @@ -76,6 +77,7 @@ export interface MarkupToHtmlOptions {
replaceResourceInternalToExternalLinks?: boolean;
resourceInfos?: ResourceInfos;
contentMaxWidth?: number;
increaseControlsSize?: boolean;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
plugins?: Record<string, any>;
bodyOnly?: boolean;
Expand Down Expand Up @@ -105,6 +107,8 @@ export interface NoteBodyEditorProps {
// avoid cases where black text is rendered over a dark background.
whiteBackgroundNoteRendering: boolean;

increaseControlSize: boolean;

content: string;
contentKey: string;
contentMarkupLanguage: number;
Expand Down
6 changes: 4 additions & 2 deletions packages/app-desktop/gui/NoteEditor/utils/useMarkupToHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ interface HookDependencies {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
settingValue: (pluginId: string, key: string)=> any;
whiteBackgroundNoteRendering: boolean;
increaseControlsSize: boolean;
}

export default function useMarkupToHtml(deps: HookDependencies) {
const { themeId, customCss, plugins, whiteBackgroundNoteRendering } = deps;
const { themeId, customCss, plugins, whiteBackgroundNoteRendering, increaseControlsSize } = deps;

const resourceBaseUrl = useMemo(() => {
return `joplin-content://note-viewer/${Setting.value('resourceDir')}/`;
Expand Down Expand Up @@ -63,6 +64,7 @@ export default function useMarkupToHtml(deps: HookDependencies) {
codeHighlightCacheKey: 'useMarkupToHtml',
settingValue: deps.settingValue,
whiteBackgroundNoteRendering,
increaseControlsSize,
itemIdToUrl: (id: string, urlParameters = '') => {
if (!(id in resources) || !resources[id]) {
return null;
Expand All @@ -74,5 +76,5 @@ export default function useMarkupToHtml(deps: HookDependencies) {
});

return result;
}, [themeId, markupToHtml, whiteBackgroundNoteRendering, resourceBaseUrl, deps.settingValue]);
}, [themeId, markupToHtml, whiteBackgroundNoteRendering, increaseControlsSize, resourceBaseUrl, deps.settingValue]);
}
4 changes: 2 additions & 2 deletions packages/app-desktop/gui/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import ClipperServer from '@joplin/lib/ClipperServer';
import DialogTitle from './DialogTitle';
import DialogButtonRow, { ButtonSpec, ClickEvent, ClickEventHandler } from './DialogButtonRow';
import Dialog from './Dialog';
import StyleSheetContainer from './StyleSheets/StyleSheetContainer';
import AppStyles from './StyleSheets/AppStyles';
import ImportScreen from './ImportScreen';
const { ResourceScreen } = require('./ResourceScreen.js');
import Navigator from './Navigator';
Expand Down Expand Up @@ -197,7 +197,7 @@ class RootComponent extends React.Component<Props, any> {
return (
<StyleSheetManager disableVendorPrefixes>
<ThemeProvider theme={theme}>
<StyleSheetContainer/>
<AppStyles/>
<MenuBar/>
<GlobalStyle/>
<WindowCommandsAndDialogs windowId={defaultWindowId} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { AppState } from '../../app.reducer';

interface Props {
themeId: number;
largeControls: boolean;
editorFontSetting: string;
customChromeCssPaths: string[];
}
Expand Down Expand Up @@ -95,7 +96,21 @@ const useAppliedCss = (doc: Document|null, css: string) => {
}, [css, doc]);
};

const StyleSheetContainer: React.FC<Props> = props => {

const useThemeFlag = (doc: Document|null, flag: string, enabled: boolean) => {
useEffect(() => {
if (enabled && doc?.documentElement) {
doc.documentElement.classList.add(flag);
return () => {
doc.documentElement.classList.remove(flag);
};
}

return () => {};
}, [doc, flag, enabled]);
};

const AppStyles: React.FC<Props> = props => {
const [elementRef, setElementRef] = useState<HTMLElement|null>(null);
const doc = useDocument(elementRef);

Expand All @@ -111,13 +126,16 @@ const StyleSheetContainer: React.FC<Props> = props => {
`);
useLinkedCss(doc, props.customChromeCssPaths);

useThemeFlag(doc, '-large-controls', props.largeControls);

return <div ref={setElementRef} style={{ display: 'none' }}></div>;
};

export default connect((state: AppState) => {
return {
themeId: state.settings.theme,
editorFontSetting: state.settings['style.editor.fontFamily'] as string,
largeControls: state.settings['style.increaseControlSize'],
customChromeCssPaths: state.customChromeCssPaths,
};
})(StyleSheetContainer);
})(AppStyles);
6 changes: 6 additions & 0 deletions packages/app-desktop/gui/note-viewer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,12 @@

addPluginAssets(event.options.pluginAssets);

if (event.options.increaseControlSize) {
document.documentElement.classList.add('-larger-controls');
} else {
document.documentElement.classList.remove('-larger-controls');
}

if (event.options.downloadResources === 'manual') {
webviewLib.setupResourceManualDownload();
}
Expand Down
13 changes: 13 additions & 0 deletions packages/app-desktop/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ a {
height: 7px;
}

:root.-large-controls {
// WCAG 2.2's SC 2.5.8: The target size for pointer events must be at least 24px x 24px
// (Though there are exceptions).
::-webkit-scrollbar, input[type=checkbox] {
width: 24px;
height: 24px;
}

::-webkit-scrollbar-thumb {
border-radius: 12px;
}
}

::-webkit-scrollbar-corner {
background: none;
}
Expand Down
12 changes: 12 additions & 0 deletions packages/lib/models/settings/builtInMetadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1120,6 +1120,18 @@ const builtInMetadata = (Setting: typeof SettingType) => {

'style.editor.contentMaxWidth': { value: 0, type: SettingItemType.Int, public: true, storage: SettingStorage.File, isGlobal: true, appTypes: [AppType.Desktop], section: 'appearance', label: () => _('Editor maximum width'), description: () => _('Set it to 0 to make it take the complete available space. Recommended width is 600.') },

'style.increaseControlSize': {
value: false,
type: SettingItemType.Bool,
public: true,
section: 'appearance',

label: () => _('Prefer large controls'),
description: () => _('Increases the size of checkboxes, scrollbars, and other otherwise-small controls.'),
storage: SettingStorage.File,
isGlobal: true,
},

'ui.layout': { value: {}, type: SettingItemType.Object, storage: SettingStorage.File, isGlobal: true, public: false, appTypes: [AppType.Desktop] },

'ui.lastSelectedPluginPanel': {
Expand Down
4 changes: 2 additions & 2 deletions packages/renderer/MarkupToHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import HtmlToHtml from './HtmlToHtml';
import htmlUtils from './htmlUtils';
import { Options as NoteStyleOptions } from './noteStyle';
import { AllHtmlEntities } from 'html-entities';
import { FsDriver, MarkupRenderer, MarkupToHtmlConverter, OptionsResourceModel, RenderResult } from './types';
import { FsDriver, MarkupRenderer, MarkupToHtmlConverter, OptionsResourceModel, RenderOptions, RenderResult } from './types';
import defaultResourceModel from './defaultResourceModel';
const MarkdownIt = require('markdown-it');

Expand Down Expand Up @@ -95,7 +95,7 @@ export default class MarkupToHtml implements MarkupToHtmlConverter {
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
public async render(markupLanguage: MarkupLanguage, markup: string, theme: any, options: any): Promise<RenderResult> {
public async render(markupLanguage: MarkupLanguage, markup: string, theme: any, options: RenderOptions): Promise<RenderResult> {
if (this.options_.isSafeMode) {
const htmlentities = new AllHtmlEntities();
return {
Expand Down
1 change: 1 addition & 0 deletions packages/renderer/MdToHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ export default class MdToHtml implements MarkupRenderer {
const renderedBody = markdownIt.render(body, context);

let cssStrings = noteStyle(options.theme, {
increaseControlsSize: options.increaseControlsSize,
contentMaxWidth: options.contentMaxWidth,
});

Expand Down
13 changes: 13 additions & 0 deletions packages/renderer/noteStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function formatCssSize(v: any): string {
export interface Options {
contentMaxWidth?: number;
contentMaxWidthTarget?: string;
increaseControlsSize?: boolean;
themeId?: number;
whiteBackgroundNoteRendering?: boolean;
}
Expand Down Expand Up @@ -117,6 +118,7 @@ export default function(theme: any, options: Options = null) {
border-radius: 3px;
background-color: ${theme.codeBackgroundColor};
}
::-webkit-scrollbar {
width: 7px;
height: 7px;
Expand All @@ -138,6 +140,17 @@ export default function(theme: any, options: Options = null) {
background: rgba(100, 100, 100, 0.7);
}
${options.increaseControlsSize ? `
::-webkit-scrollbar {
width: 24px;
height: 24px;
}
::-webkit-scrollbar-thumb {
border-radius: 12px;
}
` : ''}
${maxWidthCss}
/* Remove top padding and margin from first child so that top of rendered text is aligned to top of text editor text */
Expand Down
8 changes: 7 additions & 1 deletion packages/renderer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ interface ResourceEntity {
file_extension?: string;
}

interface ResourceInfo {
localState: unknown;
item: ResourceEntity;
}

export interface FsDriver {
writeFile: (path: string, content: string, encoding: string)=> Promise<void>;
exists: (path: string)=> Promise<boolean>;
Expand All @@ -19,6 +24,7 @@ export interface FsDriver {

export interface RenderOptions {
contentMaxWidth?: number;
increaseControlsSize?: boolean;
bodyOnly?: boolean;
splitted?: boolean;
enableLongPress?: boolean;
Expand Down Expand Up @@ -48,7 +54,7 @@ export interface RenderOptions {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
settingValue?: (pluginId: string, key: string)=> any;

resources?: Record<string, ResourceEntity>;
resources?: Record<string, ResourceInfo>;

onResourceLoaded?: ()=> void;
editPopupFiletypes?: string[];
Expand Down

0 comments on commit 91dc830

Please sign in to comment.