Skip to content

Commit 447295d

Browse files
committed
feat: add divider component
1 parent 18d89f6 commit 447295d

File tree

11 files changed

+403
-0
lines changed

11 files changed

+403
-0
lines changed

packages/divider/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Divider
2+
3+
Dividers are used to separate content inline or in a stack.
4+
5+
## Getting started
6+
7+
```
8+
yarn add @weave-design/divider @weave-design/theme-context @weave-design/theme-data
9+
```
10+
11+
## Import the component
12+
13+
```
14+
import Divider from '@weave-design/divider';
15+
```
16+
17+
## Basic usage
18+
19+
```jsx
20+
<Divider
21+
length="50px"
22+
orientation="horizontal"
23+
variant="heavyweight"
24+
/>
25+
```
26+
## Custom CSS
27+
28+
Use the `className` prop to pass in a css class name to the outermost container of the component. The class name will also pass down to most of the other styled elements within the component.
29+
30+
Divider also has a `stylesheet` prop that accepts a function wherein you can modify its styles. For instance
31+
32+
```jsx
33+
import Divider from '@weave-design/divider';
34+
35+
function YourComponent() {
36+
// ...
37+
const customStylesheet = (styles, props, themeData) => ({
38+
...styles,
39+
divider: {
40+
...styles.divider,
41+
color: themeData["colorScheme.status.error"]
42+
}
43+
});
44+
45+
return (
46+
<Divider length="50px" stylesheet={customStylesheet} />
47+
);
48+
}
49+
```

packages/divider/package.json

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"name": "@weave-design/divider",
3+
"version": "1.0.0",
4+
"description": "Weave Divider component",
5+
"author": "Autodesk Inc.",
6+
"license": "Apache-2.0",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/Autodesk/hig.git"
10+
},
11+
"publishConfig": {
12+
"access": "public"
13+
},
14+
"main": "build/index.js",
15+
"module": "build/index.es.js",
16+
"files": [
17+
"build/*"
18+
],
19+
"dependencies": {
20+
"emotion": "^10.0.0",
21+
"prop-types": "^15.7.1"
22+
},
23+
"devDependencies": {
24+
"@weave-design/babel-preset": "^1.0.0",
25+
"@weave-design/eslint-config": "^1.0.0",
26+
"@weave-design/jest-preset": "^1.0.0",
27+
"@weave-design/scripts": "^1.0.0",
28+
"@weave-design/semantic-release-config": "^1.0.0"
29+
},
30+
"peerDependencies": {
31+
"@weave-design/theme-context": "^1.0.0",
32+
"@weave-design/theme-data": "^1.3.1",
33+
"react": "^17.0.0 || ^18.0.0"
34+
},
35+
"scripts": {
36+
"build": "weave-scripts-build",
37+
"lint": "weave-scripts-lint",
38+
"test": "weave-scripts-test",
39+
"release": "weave-scripts-release"
40+
},
41+
"eslintConfig": {
42+
"extends": "@weave-design"
43+
},
44+
"jest": {
45+
"preset": "@weave-design/jest-preset"
46+
},
47+
"release": {
48+
"extends": "@weave-design/semantic-release-config"
49+
},
50+
"babel": {
51+
"env": {
52+
"test": {
53+
"presets": [
54+
"@weave-design/babel-preset/test"
55+
]
56+
}
57+
}
58+
}
59+
}

packages/divider/src/Divider.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React from "react";
2+
import PropTypes from "prop-types";
3+
import { ThemeContext } from "@weave-design/theme-context";
4+
import { css, cx } from "emotion";
5+
import stylesheet from "./Divider.stylesheet";
6+
import { AVAILABLE_ORIENTATIONS, AVAILABLE_VARIANTS } from "./constants";
7+
8+
const Divider = (props) => {
9+
const {
10+
display,
11+
length,
12+
orientation,
13+
stylesheet: customStylesheet,
14+
variant,
15+
...otherProps
16+
} = props;
17+
const { className } = otherProps;
18+
return (
19+
<ThemeContext.Consumer>
20+
{({ resolvedRoles }) => {
21+
const styles = stylesheet(
22+
{
23+
display,
24+
length,
25+
orientation,
26+
stylesheet: customStylesheet,
27+
variant,
28+
},
29+
resolvedRoles
30+
);
31+
32+
return <div className={cx(css(styles.divider), className)} />;
33+
}}
34+
</ThemeContext.Consumer>
35+
);
36+
};
37+
38+
Divider.displayName = "Divider";
39+
40+
Divider.propTypes = {
41+
/**
42+
* Specifies the the height/width of the divider depending on the orientation.
43+
* Takes any value that can be passed in the css properties height and width.
44+
*/
45+
length: PropTypes.string.isRequired,
46+
/**
47+
* Orientation of the divider.
48+
*/
49+
orientation: PropTypes.oneOf(AVAILABLE_ORIENTATIONS),
50+
/**
51+
* Variant of the divider.
52+
*/
53+
variant: PropTypes.oneOf(AVAILABLE_VARIANTS),
54+
/**
55+
* Value passed into the css display property
56+
*/
57+
display: PropTypes.string,
58+
/**
59+
* Adds custom/overriding styles
60+
*/
61+
stylesheet: PropTypes.func,
62+
};
63+
64+
Divider.defaultProps = {
65+
orientation: "horizontal",
66+
variant: "lightweight",
67+
};
68+
69+
export default Divider;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
export default function stylesheet(props, themeData) {
2+
const {
3+
display,
4+
length,
5+
orientation,
6+
stylesheet: customStylesheet,
7+
variant,
8+
} = props;
9+
const dividerWeightKey =
10+
variant === "lightweight"
11+
? "colorScheme.divider.lightweight"
12+
: "colorScheme.divider.heavyweight";
13+
const isHorizontal = orientation === "horizontal";
14+
const orientationBorder = isHorizontal ? "borderBottom" : "borderLeft";
15+
16+
const styles = {
17+
divider: {
18+
[orientationBorder]: `1px solid ${themeData[dividerWeightKey]}`,
19+
display: display || "inline-block",
20+
height: isHorizontal ? "1px" : length,
21+
width: isHorizontal ? length : "1px",
22+
},
23+
};
24+
25+
return customStylesheet ? customStylesheet(styles, props, themeData) : styles;
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import stylesheet from "./Divider.stylesheet";
2+
3+
describe("Divider.stylesheet", () => {
4+
const themeData = { "colorScheme.divider.lightweight": "blue" };
5+
6+
it("returns an object", () => {
7+
const props = {
8+
length: "50px",
9+
orientation: "vertical",
10+
variant: "lightweight",
11+
};
12+
13+
expect(stylesheet(props, themeData)).toEqual(expect.any(Object));
14+
});
15+
16+
it("returned object contains property of divider", () => {
17+
expect(stylesheet({}, themeData)).toHaveProperty(
18+
"divider",
19+
expect.any(Object)
20+
);
21+
});
22+
23+
it("returns the custom stylesheet", () => {
24+
expect(
25+
stylesheet({ stylesheet: () => ({ padding: 0 }) }, themeData)
26+
).toEqual({
27+
padding: 0,
28+
});
29+
});
30+
});

packages/divider/src/Divider.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { takeSnapshotsOf } from "@weave-design/jest-preset/helpers";
2+
3+
import Divider from "./Divider";
4+
5+
describe("divider/Divider", () => {
6+
const requiredProps = { length: "500px" };
7+
8+
takeSnapshotsOf(Divider, [
9+
{
10+
desc: "renders with length",
11+
props: { ...requiredProps },
12+
},
13+
{
14+
desc: "renders with orientation",
15+
props: { orientation: "vertical", ...requiredProps },
16+
},
17+
{
18+
desc: "renders with variant",
19+
props: { variant: "lightweight", ...requiredProps },
20+
},
21+
{
22+
desc: "renders with display",
23+
props: { display: "flex", ...requiredProps },
24+
},
25+
{
26+
desc: "renders with custom className",
27+
props: { className: "test-classname", ...requiredProps },
28+
},
29+
]);
30+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`divider/Divider renders with custom className 1`] = `
4+
.emotion-0 {
5+
border-bottom: 1px solid rgba(60,60,60,0.1);
6+
display: inline-block;
7+
height: 1px;
8+
width: 500px;
9+
}
10+
11+
<div
12+
className="emotion-0 test-classname"
13+
/>
14+
`;
15+
16+
exports[`divider/Divider renders with display 1`] = `
17+
.emotion-0 {
18+
border-bottom: 1px solid rgba(60,60,60,0.1);
19+
display: -webkit-box;
20+
display: -webkit-flex;
21+
display: -ms-flexbox;
22+
display: flex;
23+
height: 1px;
24+
width: 500px;
25+
}
26+
27+
<div
28+
className="emotion-0"
29+
/>
30+
`;
31+
32+
exports[`divider/Divider renders with length 1`] = `
33+
.emotion-0 {
34+
border-bottom: 1px solid rgba(60,60,60,0.1);
35+
display: inline-block;
36+
height: 1px;
37+
width: 500px;
38+
}
39+
40+
<div
41+
className="emotion-0"
42+
/>
43+
`;
44+
45+
exports[`divider/Divider renders with orientation 1`] = `
46+
.emotion-0 {
47+
border-left: 1px solid rgba(60,60,60,0.1);
48+
display: inline-block;
49+
height: 500px;
50+
width: 1px;
51+
}
52+
53+
<div
54+
className="emotion-0"
55+
/>
56+
`;
57+
58+
exports[`divider/Divider renders with variant 1`] = `
59+
.emotion-0 {
60+
border-bottom: 1px solid rgba(60,60,60,0.1);
61+
display: inline-block;
62+
height: 1px;
63+
width: 500px;
64+
}
65+
66+
<div
67+
className="emotion-0"
68+
/>
69+
`;
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React from "react";
2+
import { ArgsTable, Primary } from "@storybook/addon-docs";
3+
4+
import Divider from "../index";
5+
import Readme from "../../README.md";
6+
import { AVAILABLE_ORIENTATIONS, AVAILABLE_VARIANTS } from "../constants";
7+
8+
export default {
9+
title: "Basics/Divider",
10+
component: Divider,
11+
argTypes: {
12+
orientation: {
13+
control: "select",
14+
options: AVAILABLE_ORIENTATIONS,
15+
},
16+
variant: {
17+
control: "select",
18+
options: AVAILABLE_VARIANTS,
19+
},
20+
},
21+
parameters: {
22+
docs: {
23+
page: () => (
24+
<>
25+
<Primary />
26+
<Readme />
27+
<ArgsTable />
28+
</>
29+
),
30+
},
31+
},
32+
};
33+
34+
const Template = (args) => <Divider {...args} />;
35+
36+
export const Default = Template.bind({});
37+
38+
Default.args = {
39+
length: "100px",
40+
orientation: "horizontal",
41+
variant: "lightweight",
42+
};

packages/divider/src/constants.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const VARIANTS = Object.freeze({
2+
heavyweight: "heavyweight",
3+
lightweight: "lightweight",
4+
});
5+
6+
export const AVAILABLE_VARIANTS = Object.freeze(Object.keys(VARIANTS));
7+
8+
export const ORIENTATIONS = Object.freeze({
9+
horizontal: "horizontal",
10+
vertical: "vertical",
11+
});
12+
13+
export const AVAILABLE_ORIENTATIONS = Object.freeze(Object.keys(ORIENTATIONS));

packages/divider/src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default } from "./Divider";
2+
export { ORIENTATIONS, VARIANTS } from "./constants";

0 commit comments

Comments
 (0)