From ce7d20149a864961329a1650b1b90f07305b6ae2 Mon Sep 17 00:00:00 2001 From: xidedix Date: Fri, 14 Feb 2020 21:10:48 +0100 Subject: [PATCH 1/3] fix(SidebarNav): perfect scrollbar issue on sidebar minimized --- css/scrollbar.css | 18 +++++++++ src/Shared/layout/layout.js | 57 ++++++++++++++++++++++++++-- src/SidebarNav2.js | 75 +++++++++++++++++++++++++++++++------ 3 files changed, 135 insertions(+), 15 deletions(-) create mode 100644 css/scrollbar.css diff --git a/css/scrollbar.css b/css/scrollbar.css new file mode 100644 index 00000000..a9d3bc40 --- /dev/null +++ b/css/scrollbar.css @@ -0,0 +1,18 @@ +/* rtl fix */ +.ps__rtl .ps__rail-y { + left: 0px !important; + right: unset; +} +*[dir="rtl"] .ps__rail-y { + left: 0px !important; + right: unset; +} + +.ps__rtl .ps__thumb-y { + left: 2px; + right: unset; +} +*[dir="rtl"] .ps__thumb-y { + left: 2px; + right: unset; +} diff --git a/src/Shared/layout/layout.js b/src/Shared/layout/layout.js index b5772169..48ad2338 100644 --- a/src/Shared/layout/layout.js +++ b/src/Shared/layout/layout.js @@ -10,24 +10,58 @@ class LayoutHelper { } static sidebarMinimize(force) { - // return this.elClassList.toggle('sidebar-minimized', force); return this.toggleClass('sidebar-minimized', force); } static brandMinimize(force) { - // this.elClassList.toggle('brand-minimized', force); this.toggleClass('brand-minimized', force); } - // sidebar perfect scrollbar + // sidebar perfect scrollbar ugly hack static sidebarPSToggle(toggle) { + + if (this.isOnMobile()) { + toggle = true + } else { + const isSidebarMinimized = document.body.classList.contains('sidebar-minimized') || false + toggle = !isSidebarMinimized + } + + const ps = { y: { rail: {}, thumb: {} } }; + const isRtl = getComputedStyle(document.documentElement).direction === 'rtl' const sidebar = document.querySelector('.sidebar-nav'); + ps.y.rail.on = document.querySelector('.sidebar-nav .ps__rail-y'); + ps.y.rail.off = document.querySelector('.sidebar-nav .ps__rail-y-off'); + ps.y.thumb.on = document.querySelector('.sidebar-nav .ps__thumb-y'); + ps.y.thumb.off = document.querySelector('.sidebar-nav .ps__thumb-y-off'); if (sidebar) { if (toggle) { sidebar.classList.add('ps'); sidebar.classList.add('ps-container'); sidebar.classList.add('ps--active-y'); + if (ps.y.rail.off) { + ps.y.rail.off.classList.add('ps__rail-y'); + ps.y.rail.off.removeAttribute('style'); + ps.y.rail.off.style.left = isRtl ? '0px' : 'unset'; + ps.y.rail.off.style.right = isRtl ? 'unset' : '0px'; + ps.y.rail.off.classList.remove('ps__rail-y-off'); + } + if (ps.y.thumb.off) { + ps.y.thumb.off.removeAttribute('style'); + ps.y.thumb.off.classList.add('ps__thumb-y'); + ps.y.thumb.off.classList.remove('ps__thumb-y-off'); + } } else { + if (ps.y.rail.on) { + ps.y.rail.on.classList.add('ps__rail-y-off'); + ps.y.rail.on.removeAttribute('style'); + ps.y.rail.on.classList.remove('ps__rail-y'); + } + if (ps.y.thumb.on) { + ps.y.thumb.on.classList.add('ps__thumb-y-off'); + ps.y.thumb.on.removeAttribute('style'); + ps.y.thumb.on.classList.remove('ps__thumb-y'); + } sidebar.classList.remove('ps'); sidebar.classList.remove('ps-container'); sidebar.classList.remove('ps--active-y'); @@ -46,6 +80,23 @@ class LayoutHelper { } return this.elClassList.contains(className); } + + static isOnMobile() { + let onMobile = false; + try { + const minimizerElement = document.querySelector('.sidebar-minimizer'); + if (minimizerElement) { + onMobile = getComputedStyle(minimizerElement).getPropertyValue('display') === 'none'; + } else { + const sidebarElement = document.querySelector('.sidebar .sidebar-nav'); + sidebarElement && (onMobile = getComputedStyle(sidebarElement).getPropertyValue('overflow-y') === 'auto'); + } + } catch (ignore) { + // eslint-disable-next-line + console.warn('CoreUI isOnMobile failed to getComputedStyle', ignore) + } + return onMobile + } } export default LayoutHelper; diff --git a/src/SidebarNav2.js b/src/SidebarNav2.js index b839f8d6..9ae699e4 100644 --- a/src/SidebarNav2.js +++ b/src/SidebarNav2.js @@ -4,6 +4,9 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import PerfectScrollbar from 'react-perfect-scrollbar'; import 'react-perfect-scrollbar/dist/css/styles.css'; +import '../css/scrollbar.css'; + +import LayoutHelper from './Shared/layout/layout' const propTypes = { children: PropTypes.node, @@ -39,17 +42,26 @@ class AppSidebarNav2 extends Component { this.handleClick = this.handleClick.bind(this); this.activeRoute = this.activeRoute.bind(this); this.hideMobile = this.hideMobile.bind(this); + + this.changes = null; + this.state = { sidebarMinimized: false } } + _scrollBarRef = null; + handleClick(e) { e.preventDefault(); e.currentTarget.parentElement.classList.toggle('open'); } - activeRoute(routeName, props) { + isActiveRoute(routeName, props) { return props.location.pathname.indexOf(routeName) > -1 - ? 'nav-item nav-dropdown open' - : 'nav-item nav-dropdown'; + } + + activeRoute(routeName, props) { + return this.isActiveRoute(routeName, props) ? + 'nav-item nav-dropdown open' : + 'nav-item nav-dropdown'; } hideMobile() { @@ -148,6 +160,7 @@ class AppSidebarNav2 extends Component { // nav link navLink(item, key, classes) { + const ref = React.createRef(); const url = item.url || ''; const itemIcon = const itemBadge = this.navBadge(item.badge) @@ -171,7 +184,7 @@ class AppSidebarNav2 extends Component { {itemIcon}{item.name}{itemBadge} : - + this.hideMobile(ref)} ref={ref} {...attributes}> {itemIcon}{item.name}{itemBadge} } @@ -200,6 +213,45 @@ class AppSidebarNav2 extends Component { return link.substring(0, 4) === 'http'; } + observeDomMutations() { + if (window.MutationObserver) { + + // eslint-disable-next-line + this.changes = new MutationObserver((mutations) => { + + const isSidebarMinimized = document.body.classList.contains('sidebar-minimized') || false + this.setState({ sidebarMinimized: isSidebarMinimized }) + + LayoutHelper.sidebarPSToggle(!isSidebarMinimized) + + }); + const element = document.body; + this.changes.observe(element, { + attributes: true, + attributeFilter: ['class'] + }); + } + window.addEventListener('resize', this.onResize); + } + + onResize() { + LayoutHelper.sidebarPSToggle(true) + } + + componentDidMount() { + this.observeDomMutations() + } + + componentWillUnmount() { + try { + this.changes.disconnect() + window.removeEventListener('resize', this.onResize); + } catch (ignore) { + // eslint-disable-next-line + console.warn('CoreUI SidebarNav failed to disconnect from MutationObserver', ignore) + } + } + render() { const { className, children, navConfig, ...attributes } = this.props; @@ -208,18 +260,17 @@ class AppSidebarNav2 extends Component { delete attributes.Tag delete attributes.router - const navClasses = classNames(className, 'sidebar-nav'); + const navClasses = classNames(className, 'sidebar-nav') - // ToDo: find better rtl fix - const isRtl = getComputedStyle(document.documentElement).direction === 'rtl' + const options = Object.assign({}, { suppressScrollX: true, suppressScrollY: this.state.sidebarMinimized }) // sidebar-nav root return ( - - - + { this._scrollBarRef = ref; }} > + + ); } } From cd135fe5e0f316e0ed7de4f29331a71af4a4e6a1 Mon Sep 17 00:00:00 2001 From: xidedix Date: Fri, 14 Feb 2020 21:13:19 +0100 Subject: [PATCH 2/3] chore: dependencies update and config refactor --- .gitignore | 1 + nwb.config.js | 3 ++- package.json | 30 +++++++++++++++--------------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index 20d98978..01612b6a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies +node_modules /node_modules package-lock.json diff --git a/nwb.config.js b/nwb.config.js index 402187db..daf1fac2 100644 --- a/nwb.config.js +++ b/nwb.config.js @@ -5,7 +5,8 @@ module.exports = { umd: { global: 'CoreUIReact', externals: { - react: 'React' + react: 'React', + 'react-router': 'ReactRouter' } } } diff --git a/package.json b/package.json index 899e6377..501f124a 100644 --- a/package.json +++ b/package.json @@ -35,32 +35,32 @@ "lint": "eslint src" }, "dependencies": { - "@coreui/icons": "0.3.0", "classnames": "^2.2.6", - "core-js": "^2.6.9", + "core-js": "^2.6.11", "prop-types": "^15.7.2", "react-onclickout": "^2.0.8", - "react-perfect-scrollbar": "^1.5.3", - "reactstrap": "^8.0.1" + "react-perfect-scrollbar": "~1.5.8" }, "peerDependencies": { - "@coreui/coreui": "^2.1.12", - "react": "^16.10.1", - "react-router-dom": "^5.1.2" + "@coreui/coreui": "^2.1.16", + "react": "^16.12.0", + "react-router-dom": "^5.1.2", + "mutationobserver-shim": "^0.3.3" }, "devDependencies": { + "@coreui/icons": "~0.3.0", "babel-eslint": "^10.0.3", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.2", "eslint": "^5.16.0", - "eslint-plugin-import": "^2.18.2", - "eslint-plugin-react": "^7.15.1", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-react": "^7.18.3", "nwb": "^0.23.0", - "react": "^16.10.1", - "react-dom": "^16.10.1", + "react": "^16.12.0", + "react-dom": "^16.12.0", "react-router-dom": "^5.1.2", - "sinon": "^5.1.1", - "webpack-dev-server": "^3.8.1" + "reactstrap": "^8.4.1", + "sinon": "^5.1.1" }, "repository": { "type": "git", From 36461f684a937089eea69a07d3fbb9274bd06cb3 Mon Sep 17 00:00:00 2001 From: xidedix Date: Fri, 14 Feb 2020 21:13:32 +0100 Subject: [PATCH 3/3] Ship: v2.5.5 --- CHANGELOG.md | 4 ++++ package.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 46be123d..54cb3f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ### [@coreui/react](https://coreui.io/) changelog +##### `v2.5.5` +- fix(SidebarNav): perfect scrollbar issue on sidebar minimized / rtl +- chore: dependencies update and config refactor + ##### `v2.5.4` - fix(SidebarNav): allow location object as navConfig item url parameter diff --git a/package.json b/package.json index 501f124a..06e160ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@coreui/react", - "version": "2.5.4", + "version": "2.5.5", "description": "CoreUI React Bootstrap 4 components", "license": "MIT", "author": {