Skip to content

Commit

Permalink
feat: add divider component
Browse files Browse the repository at this point in the history
  • Loading branch information
wmui51 committed Sep 16, 2023
1 parent 18d89f6 commit 447295d
Show file tree
Hide file tree
Showing 11 changed files with 403 additions and 0 deletions.
49 changes: 49 additions & 0 deletions packages/divider/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Divider

Dividers are used to separate content inline or in a stack.

## Getting started

```
yarn add @weave-design/divider @weave-design/theme-context @weave-design/theme-data
```

## Import the component

```
import Divider from '@weave-design/divider';
```

## Basic usage

```jsx
<Divider
length="50px"
orientation="horizontal"
variant="heavyweight"
/>
```
## Custom CSS

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.

Divider also has a `stylesheet` prop that accepts a function wherein you can modify its styles. For instance

```jsx
import Divider from '@weave-design/divider';

function YourComponent() {
// ...
const customStylesheet = (styles, props, themeData) => ({
...styles,
divider: {
...styles.divider,
color: themeData["colorScheme.status.error"]
}
});

return (
<Divider length="50px" stylesheet={customStylesheet} />
);
}
```
59 changes: 59 additions & 0 deletions packages/divider/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{
"name": "@weave-design/divider",
"version": "1.0.0",
"description": "Weave Divider component",
"author": "Autodesk Inc.",
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/Autodesk/hig.git"
},
"publishConfig": {
"access": "public"
},
"main": "build/index.js",
"module": "build/index.es.js",
"files": [
"build/*"
],
"dependencies": {
"emotion": "^10.0.0",
"prop-types": "^15.7.1"
},
"devDependencies": {
"@weave-design/babel-preset": "^1.0.0",
"@weave-design/eslint-config": "^1.0.0",
"@weave-design/jest-preset": "^1.0.0",
"@weave-design/scripts": "^1.0.0",
"@weave-design/semantic-release-config": "^1.0.0"
},
"peerDependencies": {
"@weave-design/theme-context": "^1.0.0",
"@weave-design/theme-data": "^1.3.1",
"react": "^17.0.0 || ^18.0.0"
},
"scripts": {
"build": "weave-scripts-build",
"lint": "weave-scripts-lint",
"test": "weave-scripts-test",
"release": "weave-scripts-release"
},
"eslintConfig": {
"extends": "@weave-design"
},
"jest": {
"preset": "@weave-design/jest-preset"
},
"release": {
"extends": "@weave-design/semantic-release-config"
},
"babel": {
"env": {
"test": {
"presets": [
"@weave-design/babel-preset/test"
]
}
}
}
}
69 changes: 69 additions & 0 deletions packages/divider/src/Divider.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from "react";
import PropTypes from "prop-types";
import { ThemeContext } from "@weave-design/theme-context";
import { css, cx } from "emotion";
import stylesheet from "./Divider.stylesheet";
import { AVAILABLE_ORIENTATIONS, AVAILABLE_VARIANTS } from "./constants";

const Divider = (props) => {
const {
display,
length,
orientation,
stylesheet: customStylesheet,
variant,
...otherProps
} = props;
const { className } = otherProps;
return (
<ThemeContext.Consumer>
{({ resolvedRoles }) => {
const styles = stylesheet(
{
display,
length,
orientation,
stylesheet: customStylesheet,
variant,
},
resolvedRoles
);

return <div className={cx(css(styles.divider), className)} />;
}}
</ThemeContext.Consumer>
);
};

Divider.displayName = "Divider";

Divider.propTypes = {
/**
* Specifies the the height/width of the divider depending on the orientation.
* Takes any value that can be passed in the css properties height and width.
*/
length: PropTypes.string.isRequired,
/**
* Orientation of the divider.
*/
orientation: PropTypes.oneOf(AVAILABLE_ORIENTATIONS),
/**
* Variant of the divider.
*/
variant: PropTypes.oneOf(AVAILABLE_VARIANTS),
/**
* Value passed into the css display property
*/
display: PropTypes.string,
/**
* Adds custom/overriding styles
*/
stylesheet: PropTypes.func,
};

Divider.defaultProps = {
orientation: "horizontal",
variant: "lightweight",
};

export default Divider;
26 changes: 26 additions & 0 deletions packages/divider/src/Divider.stylesheet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export default function stylesheet(props, themeData) {
const {
display,
length,
orientation,
stylesheet: customStylesheet,
variant,
} = props;
const dividerWeightKey =
variant === "lightweight"
? "colorScheme.divider.lightweight"
: "colorScheme.divider.heavyweight";
const isHorizontal = orientation === "horizontal";
const orientationBorder = isHorizontal ? "borderBottom" : "borderLeft";

const styles = {
divider: {
[orientationBorder]: `1px solid ${themeData[dividerWeightKey]}`,
display: display || "inline-block",
height: isHorizontal ? "1px" : length,
width: isHorizontal ? length : "1px",
},
};

return customStylesheet ? customStylesheet(styles, props, themeData) : styles;
}
30 changes: 30 additions & 0 deletions packages/divider/src/Divider.stylesheet.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import stylesheet from "./Divider.stylesheet";

describe("Divider.stylesheet", () => {
const themeData = { "colorScheme.divider.lightweight": "blue" };

it("returns an object", () => {
const props = {
length: "50px",
orientation: "vertical",
variant: "lightweight",
};

expect(stylesheet(props, themeData)).toEqual(expect.any(Object));
});

it("returned object contains property of divider", () => {
expect(stylesheet({}, themeData)).toHaveProperty(
"divider",
expect.any(Object)
);
});

it("returns the custom stylesheet", () => {
expect(
stylesheet({ stylesheet: () => ({ padding: 0 }) }, themeData)
).toEqual({
padding: 0,
});
});
});
30 changes: 30 additions & 0 deletions packages/divider/src/Divider.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { takeSnapshotsOf } from "@weave-design/jest-preset/helpers";

import Divider from "./Divider";

describe("divider/Divider", () => {
const requiredProps = { length: "500px" };

takeSnapshotsOf(Divider, [
{
desc: "renders with length",
props: { ...requiredProps },
},
{
desc: "renders with orientation",
props: { orientation: "vertical", ...requiredProps },
},
{
desc: "renders with variant",
props: { variant: "lightweight", ...requiredProps },
},
{
desc: "renders with display",
props: { display: "flex", ...requiredProps },
},
{
desc: "renders with custom className",
props: { className: "test-classname", ...requiredProps },
},
]);
});
69 changes: 69 additions & 0 deletions packages/divider/src/__snapshots__/Divider.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`divider/Divider renders with custom className 1`] = `
.emotion-0 {
border-bottom: 1px solid rgba(60,60,60,0.1);
display: inline-block;
height: 1px;
width: 500px;
}
<div
className="emotion-0 test-classname"
/>
`;

exports[`divider/Divider renders with display 1`] = `
.emotion-0 {
border-bottom: 1px solid rgba(60,60,60,0.1);
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
height: 1px;
width: 500px;
}
<div
className="emotion-0"
/>
`;

exports[`divider/Divider renders with length 1`] = `
.emotion-0 {
border-bottom: 1px solid rgba(60,60,60,0.1);
display: inline-block;
height: 1px;
width: 500px;
}
<div
className="emotion-0"
/>
`;

exports[`divider/Divider renders with orientation 1`] = `
.emotion-0 {
border-left: 1px solid rgba(60,60,60,0.1);
display: inline-block;
height: 500px;
width: 1px;
}
<div
className="emotion-0"
/>
`;

exports[`divider/Divider renders with variant 1`] = `
.emotion-0 {
border-bottom: 1px solid rgba(60,60,60,0.1);
display: inline-block;
height: 1px;
width: 500px;
}
<div
className="emotion-0"
/>
`;
42 changes: 42 additions & 0 deletions packages/divider/src/__stories__/Divider.story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";
import { ArgsTable, Primary } from "@storybook/addon-docs";

import Divider from "../index";
import Readme from "../../README.md";
import { AVAILABLE_ORIENTATIONS, AVAILABLE_VARIANTS } from "../constants";

export default {
title: "Basics/Divider",
component: Divider,
argTypes: {
orientation: {
control: "select",
options: AVAILABLE_ORIENTATIONS,
},
variant: {
control: "select",
options: AVAILABLE_VARIANTS,
},
},
parameters: {
docs: {
page: () => (
<>
<Primary />
<Readme />
<ArgsTable />
</>
),
},
},
};

const Template = (args) => <Divider {...args} />;

export const Default = Template.bind({});

Default.args = {
length: "100px",
orientation: "horizontal",
variant: "lightweight",
};
13 changes: 13 additions & 0 deletions packages/divider/src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
export const VARIANTS = Object.freeze({
heavyweight: "heavyweight",
lightweight: "lightweight",
});

export const AVAILABLE_VARIANTS = Object.freeze(Object.keys(VARIANTS));

export const ORIENTATIONS = Object.freeze({
horizontal: "horizontal",
vertical: "vertical",
});

export const AVAILABLE_ORIENTATIONS = Object.freeze(Object.keys(ORIENTATIONS));
2 changes: 2 additions & 0 deletions packages/divider/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from "./Divider";
export { ORIENTATIONS, VARIANTS } from "./constants";
Loading

0 comments on commit 447295d

Please sign in to comment.