diff --git a/README.md b/README.md index b0d8ce4..ddd5141 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ I created this plugin because I hate ugly and space consuming scrollbars. Simila ## Goals & Features - Simple, powerful and well documented API - - High browser compatibility - Firefox, Chrome, Opera, Edge, Safari 10+ and IE 11 + - High browser compatibility - Firefox 59+, Chrome 55+, Opera 42+, Edge 12+, Safari 10+ and IE 11 - Can be run on the server - SSR, SSG and ISR support - Tested on various devices - Mobile, Desktop and Tablet - Tested with various (and mixed) inputs - Mouse, touch and pen @@ -33,11 +33,12 @@ I created this plugin because I hate ugly and space consuming scrollbars. Simila - Automatic update detection - no polling - Usage of latest browser features - best performance in new browsers - Bidirectional - LTR or RTL direction support + - Supports usage on the `body` element - Simple and effective scrollbar styling - Highly customizable - TypeScript support - fully written in TypeScript - Dependency free - 100% self written to ensure small size and best functionality - - High quality and fully typed Framework versions for [`react`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-react), [`vue`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-vue), [`angular`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-ngx), [`svelte`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-svelte) and [`solid`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-solid). + - High quality and fully typed framework versions for [`react`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-react), [`vue`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-vue), [`angular`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-ngx), [`svelte`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-svelte) and [`solid`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-solid). ## Choose your framework @@ -340,6 +341,8 @@ Indicates whether you can drag the scrollbar handles for scrolling. | :--- | :--- | | `boolean` | `false` | +> __Note__: This options requires the **ClickScrollPlugin** to work. + Indicates whether you can click on the scrollbar track for scrolling. ### `scrollbars.pointers` diff --git a/packages/overlayscrollbars/CHANGELOG.md b/packages/overlayscrollbars/CHANGELOG.md index 3c95a86..017e264 100644 --- a/packages/overlayscrollbars/CHANGELOG.md +++ b/packages/overlayscrollbars/CHANGELOG.md @@ -1,20 +1,33 @@ # Changelog +## W.I.P + +### Bug Fixes + +- Fix a bug where initial `RTL` direction wasn't detected properly. + +### Improvements + +- Introduce `CSS Custom Properties` to improve theming and styling of scrollbars. +- Improve the README documentation with a styling section. + ## 2.0.3 -Revert the `viewport` and `padding` style `position: relative` change introduced in `v2.0.2` due to breaking behavior. [#489](https://github.com/KingSora/OverlayScrollbars/issues/489) is considered a design limitation. +### Bug Fixes + +- Revert the `viewport` and `padding` style `position: relative` change introduced in `v2.0.2` due to breaking behavior. [#489](https://github.com/KingSora/OverlayScrollbars/issues/489) is considered a design limitation. ## 2.0.2 ### Bug Fixes -The `viewport` and `padding` elements won't have the style `position: relative` anymore if its not needed. The style is only needed for older browsers. ([#489](https://github.com/KingSora/OverlayScrollbars/issues/489)) +- The `viewport` and `padding` elements won't have the style `position: relative` anymore if its not needed. The style is only needed for older browsers. ([#489](https://github.com/KingSora/OverlayScrollbars/issues/489)) ## 2.0.1 ### Bug Fixes -The custom scrollbars are now always hidden if the `showNativeOverlaidScrollbars` option is `true`. +- The custom scrollbars are now always hidden if the `showNativeOverlaidScrollbars` option is `true`. ### Improvements diff --git a/packages/overlayscrollbars/README.md b/packages/overlayscrollbars/README.md index b0d8ce4..ddd5141 100644 --- a/packages/overlayscrollbars/README.md +++ b/packages/overlayscrollbars/README.md @@ -25,7 +25,7 @@ I created this plugin because I hate ugly and space consuming scrollbars. Simila ## Goals & Features - Simple, powerful and well documented API - - High browser compatibility - Firefox, Chrome, Opera, Edge, Safari 10+ and IE 11 + - High browser compatibility - Firefox 59+, Chrome 55+, Opera 42+, Edge 12+, Safari 10+ and IE 11 - Can be run on the server - SSR, SSG and ISR support - Tested on various devices - Mobile, Desktop and Tablet - Tested with various (and mixed) inputs - Mouse, touch and pen @@ -33,11 +33,12 @@ I created this plugin because I hate ugly and space consuming scrollbars. Simila - Automatic update detection - no polling - Usage of latest browser features - best performance in new browsers - Bidirectional - LTR or RTL direction support + - Supports usage on the `body` element - Simple and effective scrollbar styling - Highly customizable - TypeScript support - fully written in TypeScript - Dependency free - 100% self written to ensure small size and best functionality - - High quality and fully typed Framework versions for [`react`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-react), [`vue`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-vue), [`angular`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-ngx), [`svelte`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-svelte) and [`solid`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-solid). + - High quality and fully typed framework versions for [`react`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-react), [`vue`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-vue), [`angular`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-ngx), [`svelte`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-svelte) and [`solid`](https://github.com/KingSora/OverlayScrollbars/tree/master/packages/overlayscrollbars-solid). ## Choose your framework @@ -340,6 +341,8 @@ Indicates whether you can drag the scrollbar handles for scrolling. | :--- | :--- | | `boolean` | `false` | +> __Note__: This options requires the **ClickScrollPlugin** to work. + Indicates whether you can click on the scrollbar track for scrolling. ### `scrollbars.pointers` diff --git a/packages/overlayscrollbars/src/classnames.ts b/packages/overlayscrollbars/src/classnames.ts index 49bdb27..58b4521 100644 --- a/packages/overlayscrollbars/src/classnames.ts +++ b/packages/overlayscrollbars/src/classnames.ts @@ -25,6 +25,7 @@ export const classNameSizeObserverListenerItemFinal = `${classNameSizeObserverLi export const classNameTrinsicObserver = 'os-trinsic-observer'; +export const classNameScrollbarNoCssCustomProps = 'os-no-css-vars'; export const classNameScrollbarThemeNone = 'os-theme-none'; export const classNameScrollbar = 'os-scrollbar'; export const classNameScrollbarRtl = `${classNameScrollbar}-rtl`; diff --git a/packages/overlayscrollbars/src/index.scss b/packages/overlayscrollbars/src/index.scss index b6f5f9e..ab76417 100644 --- a/packages/overlayscrollbars/src/index.scss +++ b/packages/overlayscrollbars/src/index.scss @@ -2,3 +2,4 @@ @import './styles/trinsicobserver.scss'; @import './styles/structure.scss'; @import './styles/scrollbars.scss'; +@import './styles/themes.scss'; diff --git a/packages/overlayscrollbars/src/observers/sizeObserver.ts b/packages/overlayscrollbars/src/observers/sizeObserver.ts index ddb4608..3b58e50 100644 --- a/packages/overlayscrollbars/src/observers/sizeObserver.ts +++ b/packages/overlayscrollbars/src/observers/sizeObserver.ts @@ -170,7 +170,7 @@ export const createSizeObserver = ( if (observeDirectionChange) { const [updateDirectionIsRTLCache] = createCache( { - _initialValue: !getIsDirectionRTL(), // invert current value to trigger initial change + _initialValue: undefined, }, getIsDirectionRTL ); @@ -179,8 +179,8 @@ export const createSizeObserver = ( offListeners, on(sizeObserver, 'scroll', (event: Event) => { const directionIsRTLCacheValues = updateDirectionIsRTLCache(); - const [directionIsRTLCache, directionIsRTLCacheChanged] = directionIsRTLCacheValues; - + const [directionIsRTLCache, directionIsRTLCacheChanged, directionIsRTLCachePrevious] = + directionIsRTLCacheValues; if (directionIsRTLCacheChanged) { removeClass(listenerElement, 'ltr rtl'); if (directionIsRTLCache) { @@ -188,7 +188,12 @@ export const createSizeObserver = ( } else { addClass(listenerElement, 'ltr'); } - onSizeChangedCallbackProxy(directionIsRTLCacheValues); + + onSizeChangedCallbackProxy([ + !!directionIsRTLCache, + directionIsRTLCacheChanged, + directionIsRTLCachePrevious, + ]); } stopPropagation(event); diff --git a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.elements.ts b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.elements.ts index ffc04da..942d941 100644 --- a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.elements.ts +++ b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.elements.ts @@ -20,6 +20,7 @@ import { classNameScrollbarTrack, classNameScrollbarHandle, classNameScrollbarTransitionless, + classNameScrollbarNoCssCustomProps, } from '~/classnames'; import { getEnvironment } from '~/environment'; import { dynamicInitializationElement as generalDynamicInitializationElement } from '~/initialization'; @@ -76,7 +77,7 @@ export const createScrollbarsSetupElements = ( structureSetupElements: StructureSetupElementsObj, scrollbarsSetupEvents: ScrollbarsSetupEvents ): ScrollbarsSetupElements => { - const { _getDefaultInitialization } = getEnvironment(); + const { _getDefaultInitialization, _cssCustomProperties } = getEnvironment(); const { scrollbars: defaultInitScrollbars } = _getDefaultInitialization(); const { slot: defaultInitScrollbarsSlot } = defaultInitScrollbars; const { @@ -206,6 +207,10 @@ export const createScrollbarsSetupElements = ( _handle: handle, }; + if (!_cssCustomProperties) { + addClass(scrollbar, classNameScrollbarNoCssCustomProps); + } + appendChildren(scrollbar, track); appendChildren(track, handle); diff --git a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.events.ts b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.events.ts index 6b282f0..01357d2 100644 --- a/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.events.ts +++ b/packages/overlayscrollbars/src/setups/scrollbarsSetup/scrollbarsSetup.events.ts @@ -135,14 +135,14 @@ const createInteractiveScrollEvents = ( if (instantClickScroll) { moveHandleRelative(startOffset); } else if (!isDragScroll) { - const sizeObserverPlugin = getPlugins()[clickScrollPluginName] as + const clickScrollPlugin = getPlugins()[clickScrollPluginName] as | ClickScrollPluginInstance | undefined; - if (sizeObserverPlugin) { + if (clickScrollPlugin) { push( offFns, - sizeObserverPlugin._( + clickScrollPlugin._( moveHandleRelative, getHandleOffset, startOffset, diff --git a/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.ts b/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.ts index fb56640..3e7b761 100644 --- a/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.ts +++ b/packages/overlayscrollbars/src/setups/structureSetup/structureSetup.ts @@ -1,4 +1,11 @@ -import { createEventListenerHub, isEmptyObject, keys, scrollLeft, scrollTop } from '~/support'; +import { + createEventListenerHub, + directionIsRTL, + isEmptyObject, + keys, + scrollLeft, + scrollTop, +} from '~/support'; import { createState, createOptionCheck } from '~/setups/setups'; import { createStructureSetupElements } from '~/setups/structureSetup/structureSetup.elements'; import { createStructureSetupUpdate } from '~/setups/structureSetup/structureSetup.update'; @@ -34,7 +41,9 @@ type StructureSetupEventMap = { }; const initialXYNumber = { x: 0, y: 0 }; -const initialStructureSetupUpdateState: StructureSetupState = { +const createInitialStructureSetupUpdateState = ( + elements: StructureSetupElementsObj +): StructureSetupState => ({ _padding: { t: 0, r: 0, @@ -62,18 +71,18 @@ const initialStructureSetupUpdateState: StructureSetupState = { y: false, }, _heightIntrinsic: false, - _directionIsRTL: false, -}; + _directionIsRTL: directionIsRTL(elements._host), +}); export const createStructureSetup = ( target: InitializationTarget, options: ReadonlyOptions ): Setup => { const checkOptionsFallback = createOptionCheck(options, {}); - const state = createState(initialStructureSetupUpdateState); const [addEvent, removeEvent, triggerEvent] = createEventListenerHub(); - const [getState, setState] = state; const [elements, appendStructureElements, destroyElements] = createStructureSetupElements(target); + const state = createState(createInitialStructureSetupUpdateState(elements)); + const [getState, setState] = state; const updateStructure = createStructureSetupUpdate(elements, state); const triggerUpdateEvent: (...args: StructureSetupEventMap['u']) => boolean = ( updateHints, diff --git a/packages/overlayscrollbars/src/styles/scrollbars.scss b/packages/overlayscrollbars/src/styles/scrollbars.scss index d78f3bc..a45e59d 100644 --- a/packages/overlayscrollbars/src/styles/scrollbars.scss +++ b/packages/overlayscrollbars/src/styles/scrollbars.scss @@ -1,6 +1,7 @@ .os-scrollbar { - contain: strict; - transition: opacity 0.3s, visibility 0.3s, top 0.3s, right 0.3s, bottom 0.3s, left 0.3s; + contain: size layout; + contain: size layout style; + transition: opacity 0.15s, visibility 0.15s, top 0.15s, right 0.15s, bottom 0.15s, left 0.15s; pointer-events: none; position: absolute; opacity: 0; @@ -66,6 +67,16 @@ body > .os-scrollbar { .os-scrollbar-unusable .os-scrollbar-handle { opacity: 0 !important; } +.os-scrollbar-horizontal .os-scrollbar-handle { + bottom: 0; +} +.os-scrollbar-vertical .os-scrollbar-handle { + right: 0; +} +.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle { + right: auto; + left: 0; +} .os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless, .os-scrollbar.os-scrollbar-horizontal.os-scrollbar-cornerless.os-scrollbar-rtl { left: 0; @@ -76,105 +87,3 @@ body > .os-scrollbar { top: 0; bottom: 0; } - -/* NONE THEME: */ -[data-overlayscrollbars~='updating'] > .os-scrollbar, -.os-theme-none.os-scrollbar { - display: none !important; -} -/* DARK & LIGHT THEME: */ -.os-theme-dark.os-scrollbar-horizontal, -.os-theme-light.os-scrollbar-horizontal { - right: 10px; - height: 10px; -} -.os-theme-dark.os-scrollbar-vertical, -.os-theme-light.os-scrollbar-vertical { - bottom: 10px; - width: 10px; -} -.os-theme-dark.os-scrollbar-rtl.os-scrollbar-horizontal, -.os-theme-light.os-scrollbar-rtl.os-scrollbar-horizontal { - left: 10px; - right: 0; -} -.os-theme-dark.os-scrollbar, -.os-theme-light.os-scrollbar { - padding: 2px; - box-sizing: border-box; - background: transparent; -} -.os-theme-dark.os-scrollbar-unusable, -.os-theme-light.os-scrollbar-unusable { - background: transparent; -} -.os-theme-dark.os-scrollbar > .os-scrollbar-track, -.os-theme-light.os-scrollbar > .os-scrollbar-track { - background: transparent; -} -.os-theme-dark.os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light.os-scrollbar-horizontal > .os-scrollbar-track > .os-scrollbar-handle { - min-width: 30px; -} -.os-theme-dark.os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light.os-scrollbar-vertical > .os-scrollbar-track > .os-scrollbar-handle { - min-height: 30px; -} -.os-theme-dark.os-scrollbar-transition > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light.os-scrollbar-transition > .os-scrollbar-track > .os-scrollbar-handle { - transition: background-color 0.3s; -} -.os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle, -.os-theme-dark.os-scrollbar > .os-scrollbar-track, -.os-theme-light.os-scrollbar > .os-scrollbar-track { - border-radius: 10px; -} -.os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(0, 0, 0, 0.4); -} -.os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, 0.4); -} -.os-theme-dark.os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(0, 0, 0, 0.55); -} -.os-theme-light.os-scrollbar:hover > .os-scrollbar-track > .os-scrollbar-handle { - background: rgba(255, 255, 255, 0.55); -} -.os-theme-dark.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(0, 0, 0, 0.7); -} -.os-theme-light.os-scrollbar > .os-scrollbar-track > .os-scrollbar-handle.active { - background: rgba(255, 255, 255, 0.7); -} -.os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-light.os-scrollbar-vertical .os-scrollbar-handle:before { - content: ''; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - display: block; -} -.os-theme-dark.os-host-scrollbar-hidden > .os-scrollbar-handle:before { - display: none; -} -.os-theme-dark.os-scrollbar-horizontal .os-scrollbar-handle:before, -.os-theme-light.os-scrollbar-horizontal .os-scrollbar-handle:before { - top: -6px; - bottom: -2px; -} -.os-theme-dark.os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light.os-scrollbar-vertical .os-scrollbar-handle:before { - left: -6px; - right: -2px; -} -.os-theme-dark.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle:before, -.os-theme-light.os-scrollbar-rtl.os-scrollbar-vertical .os-scrollbar-handle:before { - right: -6px; - left: -2px; -} diff --git a/packages/overlayscrollbars/src/styles/themes.scss b/packages/overlayscrollbars/src/styles/themes.scss new file mode 100644 index 0000000..55a76a0 --- /dev/null +++ b/packages/overlayscrollbars/src/styles/themes.scss @@ -0,0 +1,311 @@ +.os-scrollbar { + // The size of the scrollbar + --os-size: 0; + // The axis-perpedicular padding of the scrollbar (horizontal: padding-y, vertical: padding-x) + --os-padding-perpendicular: 0; + // The axis padding of the scrollbar (horizontal: padding-x, vertical: padding-y) + --os-padding-axis: 0; + // The border radius of the scrollbar track + --os-track-border-radius: 0; + // The background of the scrollbar track + --os-track-bg: none; + // The :hover background of the scrollbar track + --os-track-bg-hover: none; + // The :active background of the scrollbar track + --os-track-bg-active: none; + // The border of the scrollbar track + --os-track-border: none; + // The :hover background of the scrollbar track + --os-track-border-hover: none; + // The :active background of the scrollbar track + --os-track-border-active: none; + // The border radius of the scrollbar handle + --os-handle-border-radius: 0; + // The background of the scrollbar handle + --os-handle-bg: none; + // The :hover background of the scrollbar handle + --os-handle-bg-hover: none; + // The :active background of the scrollbar handle + --os-handle-bg-active: none; + // The border of the scrollbar handle + --os-handle-border: none; + // The :hover border of the scrollbar handle + --os-handle-border-hover: none; + // The :active border of the scrollbar handle + --os-handle-border-active: none; + // The min size of the scrollbar handle + --os-handle-min-size: 33px; + // The max size of the scrollbar handle + --os-handle-max-size: none; + // The axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) + --os-handle-perpendicular-size: 100%; + // The :hover axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) + --os-handle-perpendicular-size-hover: 100%; + // The :active axis-perpedicular size of the scrollbar handle (horizontal: height, vertical: width) + --os-handle-perpendicular-size-active: 100%; + // Increases the interactive area of the scrollbar handle. + --os-handle-interactive-area-offset: 0; +} + +.os-scrollbar { + .os-scrollbar-track { + border: var(--os-track-border); + border-radius: var(--os-track-border-radius); + background: var(--os-track-bg); + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s; + } + .os-scrollbar-handle { + border: var(--os-handle-border); + border-radius: var(--os-handle-border-radius); + background: var(--os-handle-bg); + + &:before { + content: ''; + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + display: block; + } + } + &:hover { + .os-scrollbar-track { + border: var(--os-track-border-hover); + background: var(--os-track-bg-hover); + } + + .os-scrollbar-handle { + border: var(--os-handle-border-hover); + background: var(--os-handle-bg-hover); + } + } + &:active { + .os-scrollbar-track { + border: var(--os-track-border-active); + background: var(--os-track-bg-active); + } + + .os-scrollbar-handle { + border: var(--os-handle-border-active); + background: var(--os-handle-bg-active); + } + } +} + +.os-scrollbar-horizontal { + padding: var(--os-padding-perpendicular) var(--os-padding-axis); + right: var(--os-size); + height: var(--os-size); + + &.os-scrollbar-rtl { + left: var(--os-size); + right: 0; + } + + .os-scrollbar-handle { + min-width: var(--os-handle-min-size); + max-width: var(--os-handle-max-size); + height: var(--os-handle-perpendicular-size); + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s, height 0.15s; + + &:before { + top: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + bottom: calc(var(--os-padding-perpendicular) * -1); + } + } + + &:hover { + .os-scrollbar-handle { + height: var(--os-handle-perpendicular-size-hover); + } + } + + &:active { + .os-scrollbar-handle { + height: var(--os-handle-perpendicular-size-active); + } + } +} + +.os-scrollbar-vertical { + padding: var(--os-padding-axis) var(--os-padding-perpendicular); + bottom: var(--os-size); + width: var(--os-size); + + .os-scrollbar-handle { + min-height: var(--os-handle-min-size); + max-height: var(--os-handle-max-size); + width: var(--os-handle-perpendicular-size); + transition: opacity 0.15s, background-color 0.15s, border-color 0.15s, width 0.15s; + + &:before { + left: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + right: calc(var(--os-padding-perpendicular) * -1); + } + } + + &.os-scrollbar-rtl .os-scrollbar-handle:before { + right: calc((var(--os-padding-perpendicular) + var(--os-handle-interactive-area-offset)) * -1); + left: calc(var(--os-padding-perpendicular) * -1); + } + + &:hover { + .os-scrollbar-handle { + width: var(--os-handle-perpendicular-size-hover); + } + } + + &:active { + .os-scrollbar-handle { + width: var(--os-handle-perpendicular-size-active); + } + } +} + +/* NONE THEME: */ +[data-overlayscrollbars~='updating'] > .os-scrollbar, +.os-theme-none.os-scrollbar { + display: none !important; +} + +/* DARK & LIGHT THEME: */ +$os-theme-dark-light-size: 10px; +$os-theme-dark-light-padding-perpendicular: 2px; +$os-theme-dark-light-padding-axis: 2px; +$os-theme-dark-light-track-border-radius: 10px; +$os-theme-dark-light-handle-border-radius: 10px; +$os-theme-dark-light-handle-min-size: 33px; +$os-theme-dark-light-handle-max-size: none; +$os-theme-dark-light-handle-interactive-area-offset: 4px; + +$os-theme-dark-handle-bg: rgba(0, 0, 0, 0.44); +$os-theme-dark-handle-bg-hover: rgba(0, 0, 0, 0.55); +$os-theme-dark-handle-bg-active: rgba(0, 0, 0, 0.66); + +$os-theme-light-handle-bg: rgba(255, 255, 255, 0.44); +$os-theme-light-handle-bg-hover: rgba(255, 255, 255, 0.55); +$os-theme-light-handle-bg-active: rgba(255, 255, 255, 0.66); + +.os-theme-dark, +.os-theme-light { + --os-size: $os-theme-dark-light-size; + --os-padding-perpendicular: $os-theme-dark-light-padding-perpendicular; + --os-padding-axis: $os-theme-dark-light-padding-axis; + --os-track-border-radius: $os-theme-dark-light-track-border-radius; + --os-handle-interactive-area-offset: $os-theme-dark-light-handle-interactive-area-offset; + --os-handle-border-radius: $os-theme-dark-light-handle-border-radius; +} +.os-theme-dark { + --os-handle-bg: $os-theme-dark-handle-bg; + --os-handle-bg-hover: $os-theme-dark-handle-bg-hover; + --os-handle-bg-active: $os-theme-dark-handle-bg-active; +} +.os-theme-light { + --os-handle-bg: $os-theme-light-handle-bg; + --os-handle-bg-hover: $os-theme-light-handle-bg-hover; + --os-handle-bg-active: $os-theme-light-handle-bg-active; +} + +// ie11 support for default light and dark theme +.os-no-css-vars { + &.os-theme-dark, + &.os-theme-light { + &.os-scrollbar { + .os-scrollbar-handle { + border-radius: $os-theme-dark-light-handle-border-radius; + } + .os-scrollbar-track { + border-radius: $os-theme-dark-light-track-border-radius; + } + .os-scrollbar-handle { + border-radius: $os-theme-dark-light-handle-border-radius; + } + } + + &.os-scrollbar-horizontal { + padding: $os-theme-dark-light-padding-perpendicular $os-theme-dark-light-padding-axis; + right: $os-theme-dark-light-size; + height: $os-theme-dark-light-size; + + &.os-scrollbar-rtl { + left: $os-theme-dark-light-size; + right: 0; + } + + .os-scrollbar-handle { + min-width: $os-theme-dark-light-handle-min-size; + max-width: $os-theme-dark-light-handle-max-size; + + &:before { + top: calc( + ( + #{$os-theme-dark-light-padding-perpendicular} + #{$os-theme-dark-light-handle-interactive-area-offset} + ) * -1 + ); + bottom: calc(#{$os-theme-dark-light-padding-perpendicular} * -1); + } + } + } + + &.os-scrollbar-vertical { + padding: $os-theme-dark-light-padding-axis $os-theme-dark-light-padding-perpendicular; + bottom: $os-theme-dark-light-size; + width: $os-theme-dark-light-size; + + .os-scrollbar-handle { + min-height: $os-theme-dark-light-handle-min-size; + max-height: $os-theme-dark-light-handle-max-size; + + &:before { + left: calc( + ( + #{$os-theme-dark-light-padding-perpendicular} + #{$os-theme-dark-light-handle-interactive-area-offset} + ) * -1 + ); + right: calc(#{$os-theme-dark-light-padding-perpendicular} * -1); + } + } + + &.os-scrollbar-rtl .os-scrollbar-handle:before { + right: calc( + ( + #{$os-theme-dark-light-padding-perpendicular} + #{$os-theme-dark-light-handle-interactive-area-offset} + ) * -1 + ); + left: calc(#{$os-theme-dark-light-padding-perpendicular} * -1); + } + } + } + + &.os-theme-dark { + .os-scrollbar-handle { + background: $os-theme-dark-handle-bg; + } + &:hover { + .os-scrollbar-handle { + background: $os-theme-dark-handle-bg-hover; + } + } + &:active { + .os-scrollbar-handle { + background: $os-theme-dark-handle-bg-active; + } + } + } + &.os-theme-light { + .os-scrollbar-handle { + background: $os-theme-light-handle-bg; + } + &:hover { + .os-scrollbar-handle { + background: $os-theme-light-handle-bg-hover; + } + } + &:active { + .os-scrollbar-handle { + background: $os-theme-light-handle-bg-active; + } + } + } +} diff --git a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts index 6b31aa6..dff63a7 100644 --- a/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts +++ b/packages/overlayscrollbars/test/playwright/setups/structureSetup/update/index.browser.ts @@ -151,6 +151,52 @@ const initObj = hasClass(document.body, 'vpt') let updateCount = 0; +resize(target!).addResizeListener((width, height) => { + style(comparison, { width, height }); +}); +// resize(comparison!).addResizeListener((width, height) => style(target, { width, height })); +resize(targetResize!).addResizeListener((width, height) => { + style(comparisonResize, { width, height }); +}); +// resize(comparisonRes!).addResizeListener((width, height) => style(targetRes, { width, height })); + +const selectCallbackEnv = generateClassChangeSelectCallback(from(envElms)); +const envWidthSelect = document.querySelector('#envWidth'); +const envHeightSelect = document.querySelector('#envHeight'); +const containerWidthSelect = document.querySelector('#width'); +const containerHeightSelect = document.querySelector('#height'); +const containerFloatSelect = document.querySelector('#float'); +const containerPaddingSelect = document.querySelector('#padding'); +const containerBorderSelect = document.querySelector('#border'); +const containerMarginSelect = document.querySelector('#margin'); +const containerBoxSizingSelect = document.querySelector('#boxSizing'); +const containerDirectionSelect = document.querySelector('#direction'); +const containerMinMaxSelect = document.querySelector('#minMax'); + +envWidthSelect?.addEventListener('change', selectCallbackEnv); +envHeightSelect?.addEventListener('change', selectCallbackEnv); +containerWidthSelect?.addEventListener('change', selectCallbackEnv); +containerHeightSelect?.addEventListener('change', selectCallbackEnv); +containerFloatSelect?.addEventListener('change', selectCallbackEnv); +containerPaddingSelect?.addEventListener('change', selectCallbackEnv); +containerBorderSelect?.addEventListener('change', selectCallbackEnv); +containerMarginSelect?.addEventListener('change', selectCallbackEnv); +containerBoxSizingSelect?.addEventListener('change', selectCallbackEnv); +containerDirectionSelect?.addEventListener('change', selectCallbackEnv); +containerMinMaxSelect?.addEventListener('change', selectCallbackEnv); + +selectCallbackEnv(envWidthSelect); +selectCallbackEnv(envHeightSelect); +selectCallbackEnv(containerWidthSelect); +selectCallbackEnv(containerHeightSelect); +selectCallbackEnv(containerFloatSelect); +selectCallbackEnv(containerPaddingSelect); +selectCallbackEnv(containerBorderSelect); +selectCallbackEnv(containerMarginSelect); +selectCallbackEnv(containerBoxSizingSelect); +selectCallbackEnv(containerDirectionSelect); +selectCallbackEnv(containerMinMaxSelect); + // @ts-ignore const osInstance = // @ts-ignore @@ -274,58 +320,6 @@ const metricsDimensionsEqual = (a: Metrics, b: Metrics) => { return JSON.stringify(aDimensions) === JSON.stringify(bDimensions); }; -osInstance.elements().viewport.addEventListener('scroll', (e) => { - const viewport: HTMLElement | null = e.currentTarget as HTMLElement; - comparison!.scrollLeft = viewport.scrollLeft; - comparison!.scrollTop = viewport.scrollTop; -}); - -resize(target!).addResizeListener((width, height) => { - style(comparison, { width, height }); -}); -// resize(comparison!).addResizeListener((width, height) => style(target, { width, height })); -resize(targetResize!).addResizeListener((width, height) => { - style(comparisonResize, { width, height }); -}); -// resize(comparisonRes!).addResizeListener((width, height) => style(targetRes, { width, height })); - -const selectCallbackEnv = generateClassChangeSelectCallback(from(envElms)); -const envWidthSelect = document.querySelector('#envWidth'); -const envHeightSelect = document.querySelector('#envHeight'); -const containerWidthSelect = document.querySelector('#width'); -const containerHeightSelect = document.querySelector('#height'); -const containerFloatSelect = document.querySelector('#float'); -const containerPaddingSelect = document.querySelector('#padding'); -const containerBorderSelect = document.querySelector('#border'); -const containerMarginSelect = document.querySelector('#margin'); -const containerBoxSizingSelect = document.querySelector('#boxSizing'); -const containerDirectionSelect = document.querySelector('#direction'); -const containerMinMaxSelect = document.querySelector('#minMax'); - -envWidthSelect?.addEventListener('change', selectCallbackEnv); -envHeightSelect?.addEventListener('change', selectCallbackEnv); -containerWidthSelect?.addEventListener('change', selectCallbackEnv); -containerHeightSelect?.addEventListener('change', selectCallbackEnv); -containerFloatSelect?.addEventListener('change', selectCallbackEnv); -containerPaddingSelect?.addEventListener('change', selectCallbackEnv); -containerBorderSelect?.addEventListener('change', selectCallbackEnv); -containerMarginSelect?.addEventListener('change', selectCallbackEnv); -containerBoxSizingSelect?.addEventListener('change', selectCallbackEnv); -containerDirectionSelect?.addEventListener('change', selectCallbackEnv); -containerMinMaxSelect?.addEventListener('change', selectCallbackEnv); - -selectCallbackEnv(envWidthSelect); -selectCallbackEnv(envHeightSelect); -selectCallbackEnv(containerWidthSelect); -selectCallbackEnv(containerHeightSelect); -selectCallbackEnv(containerFloatSelect); -selectCallbackEnv(containerPaddingSelect); -selectCallbackEnv(containerBorderSelect); -selectCallbackEnv(containerMarginSelect); -selectCallbackEnv(containerBoxSizingSelect); -selectCallbackEnv(containerDirectionSelect); -selectCallbackEnv(containerMinMaxSelect); - const checkMetrics = async (checkComparison: CheckComparisonObj) => { const { host: targetHost,