Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Desktop: Accessibility: Improve scrollbar contrast #11708

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 {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_scrollbar2 follows the naming pattern for RSCSS helper classes. RSCSS also suggests including all helpers in a single file called helpers. For now, _scrollbar2 is included in main.scss (near the other scrollbar logic). If desired, I can move it to a new helpers.scss file.

--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;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Setting border-radius here is unnecessary (it's already set a few lines above).

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
Loading