Skip to content

Commit

Permalink
Desktop: Accessibility: Improve scrollbar contrast (#11708)
Browse files Browse the repository at this point in the history
  • Loading branch information
personalizedrefrigerator authored Jan 27, 2025
1 parent 762daa5 commit 9854049
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 44 deletions.
2 changes: 1 addition & 1 deletion packages/app-desktop/gui/ConfigScreen/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export default function Sidebar(props: Props) {
}

return (
<StyledRoot role='tablist'>
<StyledRoot className='settings-sidebar _scrollbar2' role='tablist'>
{buttons}
</StyledRoot>
);
Expand Down
1 change: 0 additions & 1 deletion packages/app-desktop/gui/ConfigScreen/styles/index.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

@use "./setting-description.scss";
@use "./setting-label.scss";
@use "./setting-header.scss";
Expand Down
4 changes: 2 additions & 2 deletions packages/app-desktop/gui/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as React from 'react';
import { StyledRoot, StyledSyncReportText, StyledSyncReport, StyledSynchronizeButton } from './styles';
import { StyledSyncReportText, StyledSyncReport, StyledSynchronizeButton, StyledRoot } from './styles';
import { ButtonLevel } from '../Button/Button';
import CommandService from '@joplin/lib/services/CommandService';
import Synchronizer from '@joplin/lib/Synchronizer';
Expand Down Expand Up @@ -74,7 +74,7 @@ const SidebarComponent = (props: Props) => {
);

return (
<StyledRoot className="sidebar" role='navigation' aria-label={_('Sidebar')}>
<StyledRoot className='sidebar _scrollbar2' role='navigation' aria-label={_('Sidebar')}>
<div style={{ flex: 1 }}><FolderAndTagList/></div>
<div style={{ flex: 0, padding: theme.mainPadding }}>
{syncReportComp}
Expand Down
16 changes: 14 additions & 2 deletions packages/app-desktop/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ a {
}

::-webkit-scrollbar-thumb {
background: rgba(100, 100, 100, 0.3);
background: var(--scrollbar-thumb-color);
border-radius: calc(var(--scrollbar-size, 7px) * 0.7);
}

Expand All @@ -53,7 +53,19 @@ a {
}

::-webkit-scrollbar-thumb:hover {
background: rgba(100, 100, 100, 0.7);
background: var(--scrollbar-thumb-color-hover);
}

:root {
--scrollbar-thumb-color: var(--joplin-scrollbar-thumb-color);
--scrollbar-thumb-color-hover: var(--joplin-scrollbar-thumb-color-hover);
}

// Uses a scrollbar with secondary colors. Should be used for content with
// background matching joplin-background-color2.
._scrollbar2 {
--scrollbar-thumb-color: var(--joplin-scrollbar-thumb-color2);
--scrollbar-thumb-color-hover: var(--joplin-scrollbar-thumb-color-hover2);
}

.fade_out {
Expand Down
3 changes: 2 additions & 1 deletion packages/app-mobile/components/global-style.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Setting from '@joplin/lib/models/Setting';
import { Platform, TextStyle, ViewStyle } from 'react-native';
import { themeById } from '@joplin/lib/theme';
import { withDerivedColors, themeById } from '@joplin/lib/theme';
import { Theme as BaseTheme } from '@joplin/lib/themes/type';

const Color = require('color');
Expand Down Expand Up @@ -154,6 +154,7 @@ function themeStyle(theme: number) {
const output: ThemeStyle = {
...baseStyle,
...baseTheme,
...withDerivedColors(baseTheme),
...extraStyles(baseTheme),
};
themeCache_[cacheKey] = output;
Expand Down
83 changes: 49 additions & 34 deletions packages/lib/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,49 @@ const globalStyle = (() => {
};
})();

export function extraStyles(theme: Theme) {
export const withDerivedColors = (theme: Theme) => {
const backgroundColor5 = theme.backgroundColor5 ?? theme.color4;
const backgroundColor4 = theme.backgroundColor4;

// Colors need to be converted to string to work in some cases (in particular
// on mobile)
const rgbString = (color: typeof Color): string => color.rgb().string();
const hexString = (color: typeof Color): string => color.hex();

return {
...theme,
borderColor4: rgbString(Color(theme.color).alpha(0.3)),
iconColor: rgbString(Color(theme.color).alpha(0.8)),
focusOutlineColor: theme.colorWarn,

backgroundColor5,
backgroundColorHover5: hexString(Color(backgroundColor5).darken(0.2)),
backgroundColorActive5: hexString(Color(backgroundColor5).darken(0.4)),

colorFaded2: rgbString(Color(theme.color2).alpha(0.52)),
colorHover2: rgbString(Color(theme.color2).alpha(0.7)),
colorActive2: rgbString(Color(theme.color2).alpha(0.9)),

backgroundColorHoverDim3: rgbString(Color(theme.backgroundColorHover3).alpha(0.3)),
backgroundColorActive3: rgbString(Color(theme.backgroundColorHover3).alpha(0.5)),
backgroundColorHover2: rgbString(Color(theme.selectedColor2).alpha(0.4)),
backgroundColorHover4: rgbString(Color(theme.backgroundColorHover3).alpha(0.3)),
backgroundColorActive4: rgbString(Color(theme.backgroundColorHover3).alpha(0.8)),

scrollbarThumbColor: rgbString(Color(theme.color).alpha(0.54)),
scrollbarThumbColorHover: rgbString(Color(theme.color).alpha(0.63)),
scrollbarThumbColor2: rgbString(Color(theme.color2).alpha(0.46)),
scrollbarThumbColorHover2: rgbString(Color(theme.color2).alpha(0.63)),

selectedDividerColor: hexString(Color(theme.dividerColor).darken(0.2)),
color5: theme.color5 ?? backgroundColor4,
colorHover3: theme.color3,
};
};

type ThemeAndDerivedColors = ReturnType<typeof withDerivedColors>;

export function extraStyles(theme: ThemeAndDerivedColors) {
const zoomRatio = 1;

const baseFontSize = Math.round(12 * zoomRatio);
Expand All @@ -107,15 +149,6 @@ export function extraStyles(theme: Theme) {
noteViewerFontSize: Math.round(baseFontSize * 1.25),
};

const bgColor4 = theme.backgroundColor4;
const borderColor4: string = Color(theme.color).alpha(0.3);
const iconColor = Color(theme.color).alpha(0.8);
const focusOutlineColor = theme.colorWarn;

const backgroundColor5 = theme.backgroundColor5 ?? theme.color4;
const backgroundColorHover5 = Color(backgroundColor5).darken(0.2).hex();
const backgroundColorActive5 = Color(backgroundColor5).darken(0.4).hex();

const inputStyle = {
...globalStyle.inputStyle,
color: theme.color,
Expand All @@ -133,7 +166,7 @@ export function extraStyles(theme: Theme) {
...globalStyle.buttonStyle,
color: theme.color4,
backgroundColor: theme.backgroundColor4,
borderColor: borderColor4,
borderColor: theme.borderColor4,
userSelect: literal('none'),
// cursor: 'pointer',

Expand Down Expand Up @@ -213,25 +246,6 @@ export function extraStyles(theme: Theme) {
return {
zoomRatio,
...fontSizes,
selectedDividerColor: Color(theme.dividerColor).darken(0.2).hex(),
iconColor,
colorFaded2: Color(theme.color2).alpha(0.52).rgb(),
colorHover2: Color(theme.color2).alpha(0.7).rgb(),
colorActive2: Color(theme.color2).alpha(0.9).rgb(),

backgroundColorHoverDim3: Color(theme.backgroundColorHover3).alpha(0.3).rgb(),
backgroundColorActive3: Color(theme.backgroundColorHover3).alpha(0.5).rgb(),
backgroundColorHover2: Color(theme.selectedColor2).alpha(0.4).rgb(),
backgroundColorHover4: Color(theme.backgroundColorHover3).alpha(0.3).rgb(),
backgroundColorActive4: Color(theme.backgroundColorHover3).alpha(0.8).rgb(),
colorHover3: theme.color3,
borderColor4,
backgroundColor4: bgColor4,
color5: theme.color5 ?? bgColor4,
backgroundColor5,
backgroundColorHover5,
backgroundColorActive5,
focusOutlineColor,

icon: {
...globalStyle.icon,
Expand Down Expand Up @@ -306,7 +320,7 @@ export function extraStyles(theme: Theme) {
flexDirection: literal('column'),
},
buttonIconStyle: {
color: iconColor,
color: theme.iconColor,
marginRight: 6,
},
notificationBox: {
Expand All @@ -329,7 +343,7 @@ export function extraStyles(theme: Theme) {

type ExtraStyles = ReturnType<typeof extraStyles>;
type GlobalStyle = typeof globalStyle;
export type ThemeStyle = Theme & ExtraStyles & GlobalStyle & { cacheKey: number };
export type ThemeStyle = ThemeAndDerivedColors & ExtraStyles & GlobalStyle & { cacheKey: number };

const themeCache_: Record<string, ThemeStyle> = {};

Expand All @@ -339,14 +353,15 @@ export function themeStyle(themeId: number): ThemeStyle {
const cacheKey = themeId;
if (themeCache_[cacheKey]) return themeCache_[cacheKey];

const theme = withDerivedColors(themes[themeId]);
const output: ThemeStyle = {
cacheKey,
...globalStyle,
...themes[themeId],
...theme,

// All theme are based on the light style, and just override the
// relevant properties
...extraStyles(themes[themeId]),
...extraStyles(theme),
};

themeCache_[cacheKey] = output;
Expand Down
5 changes: 2 additions & 3 deletions packages/renderer/noteStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,14 +137,13 @@ export default function(theme: any, options: Options = null) {
border: none;
}
::-webkit-scrollbar-thumb {
background: rgba(100, 100, 100, 0.3);
border-radius: 5px;
background: ${theme.scrollbarThumbColor};
}
::-webkit-scrollbar-track:hover {
background: rgba(0, 0, 0, 0.1);
}
::-webkit-scrollbar-thumb:hover {
background: rgba(100, 100, 100, 0.7);
background: ${theme.scrollbarThumbColorHover};
}
${maxWidthCss}
Expand Down

0 comments on commit 9854049

Please sign in to comment.