Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Package | Version | Dependencies
[`@zendeskgarden/react-pagination`](packages/pagination) | [![npm version][pagination npm version]][pagination npm link] | [![Dependency Status][pagination dependency status]][pagination dependency link]
[`@zendeskgarden/react-radios`](packages/radios) | [![npm version][radios npm version]][radios npm link] | [![Dependency Status][radios dependency status]][radios dependency link]
[`@zendeskgarden/react-ranges`](packages/ranges) | [![npm version][ranges npm version]][ranges npm link] | [![Dependency Status][ranges dependency status]][ranges dependency link]
[`@zendeskgarden/react-scrollbars`](packages/scrollbars) | [![npm version][scrollbars npm version]][scrollbars npm link] | [![Dependency Status][scrollbars dependency status]][scrollbars dependency link]
[`@zendeskgarden/react-select`](packages/select) | [![npm version][select npm version]][select npm link] | [![Dependency Status][select dependency status]][select dependency link]
[`@zendeskgarden/react-selection`](packages/selection) | [![npm version][selection npm version]][selection npm link] | [![Dependency Status][selection dependency status]][selection dependency link]
[`@zendeskgarden/react-tabs`](packages/tabs) | [![npm version][tabs npm version]][tabs npm link] | [![Dependency Status][tabs dependency status]][tabs dependency link]
Expand Down Expand Up @@ -94,6 +95,10 @@ Package | Version | Dependencies
[ranges npm link]: https://www.npmjs.com/package/@zendeskgarden/react-ranges
[ranges dependency status]: https://img.shields.io/david/zendeskgarden/react-components.svg?path=packages/ranges&style=flat-square
[ranges dependency link]: https://david-dm.org/zendeskgarden/react-components?path=packages/ranges
[scrollbars npm version]: https://img.shields.io/npm/v/@zendeskgarden/react-scrollbars.svg?style=flat-square
[scrollbars npm link]: https://www.npmjs.com/package/@zendeskgarden/react-scrollbars
[scrollbars dependency status]: https://img.shields.io/david/zendeskgarden/react-components.svg?path=packages/scrollbars&style=flat-square
[scrollbars dependency link]: https://david-dm.org/zendeskgarden/react-components?path=packages/scrollbars
[select npm version]: https://img.shields.io/npm/v/@zendeskgarden/react-select.svg?style=flat-square
[select npm link]: https://www.npmjs.com/package/@zendeskgarden/react-select
[select dependency status]: https://img.shields.io/david/zendeskgarden/react-components.svg?path=packages/select&style=flat-square
Expand Down
3 changes: 3 additions & 0 deletions demo/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,9 @@ <h1 class="c-main__title">React Components</h1>
<div class="u-mb-sm">
<a class="u-fg-inherit" href="ranges">Ranges</a>
</div>
<div class="u-mb-sm">
<a class="u-fg-inherit" href="scrollbars">Scrollbars</a>
</div>
<div class="u-mb-sm">
<a class="u-fg-inherit" href="select">Select</a>
</div>
Expand Down
1 change: 1 addition & 0 deletions packages/scrollbars/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

34 changes: 34 additions & 0 deletions packages/scrollbars/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# @zendeskgarden/react-scrollbars [![npm version](https://img.shields.io/npm/v/@zendeskgarden/react-scrollbars.svg?style=flat-square)](https://www.npmjs.com/package/@zendeskgarden/react-scrollbars)

This package includes components relating to scrollbars in the
[Garden Design System](https://zendeskgarden.github.io/).

## Installation

```sh
npm install @zendeskgarden/react-scrollbars

# Peer Dependencies - Also Required
npm install react react-dom prop-types styled-components @zendeskgarden/react-theming
```

## Usage

```jsx static
/**
* Include scrollbars styling at the root of your application
*/
import '@zendeskgarden/react-scrollbars/dist/styles.css';

import { ThemeProvider } from '@zendeskgarden/react-theming';
import { Scrollbar } from '@zendeskgarden/react-scrollbars';

/**
* Place a `ThemeProvider` at the root of your React application
*/
<ThemeProvider>
<Scrollbar style={{ width: 200, height: 200 }}>
Lorem ipsum dolor sit amet, consectetur adipiscing elit...
</Scrollbar>
</ThemeProvider>;
```
47 changes: 47 additions & 0 deletions packages/scrollbars/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@zendeskgarden/react-scrollbars",
"description": "Components relating to scrollbars in the Garden Design System",
"license": "Apache-2.0",
"author": "Zendesk Garden <garden@zendesk.com>",
"homepage": "https://garden.zendesk.com/",
"repository": "https://github.com/zendeskgarden/react-components",
"bugs": {
"url": "https://github.com/zendeskgarden/react-components/issues"
},
"version": "0.0.0",
"main": "./dist/index.js",
"files": [
"dist"
],
"scripts": {
"build": "../../utils/scripts/build.sh",
"build:demo": "../../utils/scripts/build-demo.sh",
"start": "../../utils/scripts/start.sh"
},
"dependencies": {
"classnames": "^2.2.5",
"perfect-scrollbar": "^1.4.0"
},
"peerDependencies": {
"@zendeskgarden/react-theming": "^1.0.0 || ^2.0.0 || ^3.0.0",
"prop-types": "^15.6.1",
"react": "^0.14.0 || ^15.0.0 || ^16.0.0",
"react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0",
"styled-components": "^3.2.6"
},
"devDependencies": {
"@zendeskgarden/css-scrollbars": "0.1.0",
"@zendeskgarden/css-variables": "5.1.0"
},
"keywords": [
"components",
"garden",
"react",
"zendesk"
],
"publishConfig": {
"access": "public"
},
"zendeskgarden:library": "GardenScrollbars",
"zendeskgarden:src": "src/index.js"
}
115 changes: 115 additions & 0 deletions packages/scrollbars/src/Scrollbar.example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
### Basic Scrollable Example

Our custom scrollbar implementation is uses the
[perfect-scrollbars](https://github.com/utatti/perfect-scrollbar)
library internally.

Take a look at their [API documentation](https://github.com/utatti/perfect-scrollbar#options)
to view all of the available customization options and events.

```jsx
const { MD } = require('@zendeskgarden/react-typography');
const { zdSpacing } = require('@zendeskgarden/css-variables');

const StyledSection = styled(MD)`
margin-bottom: ${zdSpacing};
`;

const ExampleText = () => (
<StyledSection>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto
beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit,
sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat
voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit
laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui
in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat
quo voluptas nulla pariatur?
</StyledSection>
);

<Scrollbar style={{ height: 200 }}>
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
</Scrollbar>;
```

### Dark Mode

```jsx
<Scrollbar style={{ width: '100%', height: 500 }} dark>
<img
src="images/beach-dark.jpg"
alt="Dark Beach Example"
style={{ width: 2000, display: 'block' }}
/>
</Scrollbar>
```

## Scroll Jumping

```jsx
const { Button } = require('@zendeskgarden/react-buttons/src');

const StyledSection = styled.div`
margin-bottom: 16px;
`;

const ExampleText = () => (
<StyledSection>
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto
beatae vitae dicta sunt explicabo. Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut
odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.
Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit,
sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat
voluptatem. Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit
laboriosam, nisi ut aliquid ex ea commodi consequatur? Quis autem vel eum iure reprehenderit qui
in ea voluptate velit esse quam nihil molestiae consequatur, vel illum qui dolorem eum fugiat
quo voluptas nulla pariatur?
</StyledSection>
);

<Grid>
<Row>
<Col sm>
<Button
stretched
onClick={() => {
this.scrollbarRef.scrollTop = 0;
}}
>
Scroll to top
</Button>
</Col>
<Col sm>
<Button
stretched
onClick={() => {
this.scrollbarRef.scrollTop = this.scrollbarRef.scrollHeight;
}}
>
Scroll to bottom
</Button>
</Col>
</Row>
<Row>
<Col>
<Scrollbar style={{ height: 250, marginTop: 40 }} innerRef={ref => (this.scrollbarRef = ref)}>
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
<ExampleText />
</Scrollbar>
</Col>
</Row>
</Grid>;
```
165 changes: 165 additions & 0 deletions packages/scrollbars/src/Scrollbar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/**
* Copyright Zendesk, Inc.
*
* Use of this source code is governed under the Apache License, Version 2.0
* found at http://www.apache.org/licenses/LICENSE-2.0.
*/

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import styled from 'styled-components';
import PerfectScrollbar from 'perfect-scrollbar';
import { isRtl, retrieveTheme } from '@zendeskgarden/react-theming';
Copy link
Member

Choose a reason for hiding this comment

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

Horizontal scrolling for (not so)PerfectScrollbar is completely broken for RTL. Vertical isn't great, either.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah I'm seeing some weird behaviour with rtl mode on


/**
* These styles are NOT consumed through CSS Modules to allow
* interaction with with perfect-scrollbars.
*/
import '@zendeskgarden/css-scrollbars';

const EVENT_KEYS = {
SCROLL_Y: 'ps-scroll-y',
SCROLL_X: 'ps-scroll-x',
SCROLL_UP: 'ps-scroll-up',
SCROLL_DOWN: 'ps-scroll-down',
SCROLL_LEFT: 'ps-scroll-left',
SCROLL_RIGHT: 'ps-scroll-right',
REACH_START_Y: 'ps-y-reach-start',
REACH_END_Y: 'ps-y-reach-end',
REACH_START_X: 'ps-x-reach-start',
REACH_END_X: 'ps-x-reach-end'
};

const COMPONENT_ID = 'scrollbars.scrollbar';

/**
* Accepts all `<div>` props
*/
const ScrollbarContainer = styled.div.attrs({
'data-garden-id': COMPONENT_ID,
'data-garden-version': PACKAGE_VERSION,
className: props =>
classNames('c-scrollbar', {
'c-scrollbar--dark': props.dark,
'is-rtl': isRtl(props)
})
})`
${props => retrieveTheme(COMPONENT_ID, props)};
`;

export default class Scrollbar extends Component {
static propTypes = {
/** Apply dark mode styling */
dark: PropTypes.bool,
/** Customizations provided to [perfect-scrollbars](https://github.com/utatti/perfect-scrollbar) */
perfectScrollbarOptions: PropTypes.object,
/** Container ref */
innerRef: PropTypes.func,
/** Custom tag for the containing element */
tagName: PropTypes.any,
onScrollY: PropTypes.func,
onScrollX: PropTypes.func,
onScrollUp: PropTypes.func,
onScrollDown: PropTypes.func,
onScrollLeft: PropTypes.func,
onScrollRight: PropTypes.func,
onReachStartY: PropTypes.func,
onReachEndY: PropTypes.func,
onReachStartX: PropTypes.func,
onReachEndX: PropTypes.func
};

static defaultProps = {
tagName: 'div',
dark: false
};

componentDidMount() {
const { perfectScrollbarOptions } = this.props;

if (this.scrollbarContainerRef) {
this.perfectScrollbar = new PerfectScrollbar(
this.scrollbarContainerRef,
perfectScrollbarOptions
);

for (const eventKey in EVENT_KEYS) {
if (Object.prototype.hasOwnProperty.call(EVENT_KEYS, eventKey)) {
this.scrollbarContainerRef.addEventListener(
EVENT_KEYS[eventKey],
this.onCustomEvent(EVENT_KEYS[eventKey])
);
}
}
}
}

componentDidUpdate() {
if (this.perfectScrollbar) {
this.perfectScrollbar.update();
}
}

componentWillUnmount() {
this.perfectScrollbar.destroy();
this.perfectScrollbar = null;

for (const eventKey in EVENT_KEYS) {
if (Object.prototype.hasOwnProperty.call(EVENT_KEYS, eventKey)) {
this.scrollbarContainerRef.removeEventListener(
EVENT_KEYS[eventKey],
this.onCustomEvent(EVENT_KEYS[eventKey])
);
}
}
}

onCustomEvent = eventKey => {
const {
onScrollY,
onScrollX,
onScrollUp,
onScrollDown,
onScrollLeft,
onScrollRight,
onReachStartY,
onReachEndY,
onReachStartX,
onReachEndX
} = this.props;

const EVENTS = {
[EVENT_KEYS.SCROLL_Y]: onScrollY,
[EVENT_KEYS.SCROLL_X]: onScrollX,
[EVENT_KEYS.SCROLL_UP]: onScrollUp,
[EVENT_KEYS.SCROLL_DOWN]: onScrollDown,
[EVENT_KEYS.SCROLL_LEFT]: onScrollLeft,
[EVENT_KEYS.SCROLL_RIGHT]: onScrollRight,
[EVENT_KEYS.REACH_START_Y]: onReachStartY,
[EVENT_KEYS.REACH_END_Y]: onReachEndY,
[EVENT_KEYS.REACH_START_X]: onReachStartX,
[EVENT_KEYS.REACH_END_X]: onReachEndX
};

return (...args) => EVENTS[eventKey] && EVENTS[eventKey](...args);
};

render() {
const { children, innerRef, tagName, ...other } = this.props;

const CustomScrollbarContainer = ScrollbarContainer.withComponent(tagName);

return (
<CustomScrollbarContainer
{...other}
innerRef={ref => {
this.scrollbarContainerRef = ref;
innerRef && innerRef(ref);
}}
>
{children}
</CustomScrollbarContainer>
);
}
}
Loading