mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-03-14 04:00:42 -04:00
feat(a11y): add arrow buttons to monaco scrollbar (#52425)
This commit is contained in:
@@ -192,3 +192,53 @@ textarea.inputarea {
|
||||
.hint-status {
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
/* overwriting default arrow styles for accessibility */
|
||||
:root {
|
||||
--monaco-scrollbar-arrow-box-size: 0;
|
||||
--monaco-scrollbar-arrow-icon-top-bottom: 0;
|
||||
--monaco-scrollbar-arrow-icon-left: 0;
|
||||
--monaco-scrollbar-arrow-icon-size: 11px;
|
||||
--monaco-scrollbar-arrow-icon-font-size: 11px;
|
||||
}
|
||||
|
||||
/* z-index is needed for arrox box and icons because the scrollbar may
|
||||
overlap the arrow buttons when zoomed in */
|
||||
|
||||
/* arrow box - by default the width is the same as the scrollbar,
|
||||
so we only need to ajdust the height */
|
||||
.vs .monaco-scrollable-element .scrollbar .arrow-background {
|
||||
height: var(--monaco-scrollbar-arrow-box-size) !important;
|
||||
background-color: #666;
|
||||
z-index: 998;
|
||||
}
|
||||
|
||||
/* arrow icons - includes both up and down */
|
||||
.vs .monaco-scrollable-element .scrollbar .scra {
|
||||
top: var(--monaco-scrollbar-arrow-icon-top-bottom) !important;
|
||||
left: var(--monaco-scrollbar-arrow-icon-left) !important;
|
||||
width: var(--monaco-scrollbar-arrow-icon-size) !important;
|
||||
height: var(--monaco-scrollbar-arrow-icon-size) !important;
|
||||
font-size: var(--monaco-scrollbar-arrow-icon-font-size) !important;
|
||||
color: white;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
/* down arrow icon only */
|
||||
.vs .monaco-scrollable-element .scrollbar .codicon-scrollbar-button-down {
|
||||
top: unset !important;
|
||||
bottom: var(--monaco-scrollbar-arrow-icon-top-bottom) !important;
|
||||
}
|
||||
|
||||
/* we can live with with no color change for hover state if browser doesn't
|
||||
support :has (the mouse cursor will still change to pointer) */
|
||||
@supports (selector(html:has(body))) {
|
||||
.vs .monaco-scrollable-element .scrollbar .arrow-background:hover,
|
||||
.vs
|
||||
.monaco-scrollable-element
|
||||
.scrollbar
|
||||
.arrow-background:has(+ .codicon:hover) {
|
||||
cursor: pointer;
|
||||
background-color: #222 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,10 @@ import {
|
||||
isChallengeCompletedSelector
|
||||
} from '../redux/selectors';
|
||||
import GreenPass from '../../../assets/icons/green-pass';
|
||||
import { enhancePrismAccessibility } from '../utils/index';
|
||||
import {
|
||||
enhancePrismAccessibility,
|
||||
setScrollbarArrowStyles
|
||||
} from '../utils/index';
|
||||
import { getScrollbarWidth } from '../../../utils/scrollbar-width';
|
||||
import LowerJaw from './lower-jaw';
|
||||
|
||||
@@ -291,9 +294,12 @@ const Editor = (props: EditorProps): JSX.Element => {
|
||||
scrollbar: {
|
||||
horizontal: 'hidden',
|
||||
vertical: 'visible',
|
||||
verticalHasArrows: false,
|
||||
verticalHasArrows: true,
|
||||
useShadows: false,
|
||||
verticalScrollbarSize: getScrollbarWidth()
|
||||
verticalScrollbarSize: getScrollbarWidth(),
|
||||
// this helps the scroll bar fit properly between the arrows,
|
||||
// but doesn't do anything for the arrows themselves
|
||||
arrowSize: getScrollbarWidth()
|
||||
},
|
||||
parameterHints: {
|
||||
enabled: false
|
||||
@@ -602,6 +608,9 @@ const Editor = (props: EditorProps): JSX.Element => {
|
||||
scrollGutterNode
|
||||
);
|
||||
editor.addContentWidget(scrollGutterWidget);
|
||||
|
||||
// update scrollbar arrows
|
||||
setScrollbarArrowStyles(getScrollbarWidth());
|
||||
};
|
||||
|
||||
const toggleAriaRoledescription = () => {
|
||||
|
||||
@@ -74,3 +74,38 @@ export function enhancePrismAccessibility(
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
// Adjusts scrollbar arrows based on scrollbar width
|
||||
export function setScrollbarArrowStyles(scrollbarWidth: number): void {
|
||||
const root = document.documentElement;
|
||||
|
||||
// make the arrow box a square
|
||||
root.style.setProperty(
|
||||
'--monaco-scrollbar-arrow-box-size',
|
||||
`${scrollbarWidth}px`
|
||||
);
|
||||
|
||||
// adjust arrow icon size to fit arrow box
|
||||
const iconSize = scrollbarWidth < 11 ? scrollbarWidth : scrollbarWidth - 5;
|
||||
const iconFontSize =
|
||||
scrollbarWidth < 11 ? scrollbarWidth : scrollbarWidth - 5;
|
||||
root.style.setProperty('--monaco-scrollbar-arrow-icon-size', `${iconSize}px`);
|
||||
root.style.setProperty(
|
||||
'--monaco-scrollbar-arrow-icon-font-size',
|
||||
`${iconFontSize}px`
|
||||
);
|
||||
|
||||
// position arrow icon in arrow box
|
||||
const iconTopBottom =
|
||||
scrollbarWidth < 11 ? 0 : scrollbarWidth / 2 - iconFontSize / 2 - 1;
|
||||
const iconLeftPosition =
|
||||
scrollbarWidth < 11 ? 0 : (scrollbarWidth - iconFontSize) / 2;
|
||||
root.style.setProperty(
|
||||
'--monaco-scrollbar-arrow-icon-top-bottom',
|
||||
`${iconTopBottom}px`
|
||||
);
|
||||
root.style.setProperty(
|
||||
'--monaco-scrollbar-arrow-icon-left',
|
||||
`${iconLeftPosition}px`
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user