diff --git a/packages/clay-sidebar/.yarnrc b/packages/clay-sidebar/.yarnrc new file mode 100644 index 0000000000..4effba9a12 --- /dev/null +++ b/packages/clay-sidebar/.yarnrc @@ -0,0 +1,3 @@ +# Make `yarn version` produce the right commit message and tag for this package. +version-tag-prefix "@clayui/sidebar@" +version-git-message "chore: prepare @clayui/sidebar@%s" diff --git a/packages/clay-sidebar/README.md b/packages/clay-sidebar/README.md new file mode 100644 index 0000000000..47e6c9fcc5 --- /dev/null +++ b/packages/clay-sidebar/README.md @@ -0,0 +1,17 @@ +# clay-sidebar + +My awesome Clay component + +## Setup + +1. Install `yarn` + +2. Install local dependencies: + +``` +yarn +``` + +## Contribute + +We'd love to get contributions from you! Please, check our [Contributing Guidelines](https://github.com/liferay/clay/blob/master/CONTRIBUTING.md) to see how you can help us improve. diff --git a/packages/clay-sidebar/package.json b/packages/clay-sidebar/package.json new file mode 100644 index 0000000000..f78bffe908 --- /dev/null +++ b/packages/clay-sidebar/package.json @@ -0,0 +1,39 @@ +{ + "name": "@clayui/sidebar", + "version": "3.0.0", + "description": "ClaySidebar component", + "license": "BSD-3-Clause", + "repository": "https://github.com/liferay/clay/tree/master/packages/clay-sidebar", + "engines": { + "node": ">=0.12.0", + "npm": ">=3.0.0" + }, + "main": "lib/index.js", + "types": "lib/index.d.ts", + "ts:main": "src/index.tsx", + "files": [ + "lib", + "src" + ], + "scripts": { + "build": "cross-env NODE_ENV=production babel src --root-mode upward --out-dir lib --extensions .ts,.tsx", + "build:types": "cross-env NODE_ENV=production tsc --project ./tsconfig.declarations.json", + "prepublishOnly": "yarn build && yarn build:types", + "test": "jest --config ../../jest.config.js" + }, + "keywords": [ + "clay", + "react" + ], + "dependencies": { + "classnames": "^2.2.6" + }, + "peerDependencies": { + "@clayui/css": "3.x", + "react": "^16.8.1", + "react-dom": "^16.8.1" + }, + "browserslist": [ + "extends browserslist-config-clay" + ] +} diff --git a/packages/clay-sidebar/src/Divider.tsx b/packages/clay-sidebar/src/Divider.tsx new file mode 100644 index 0000000000..113c663f91 --- /dev/null +++ b/packages/clay-sidebar/src/Divider.tsx @@ -0,0 +1,17 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import React from 'react'; + +interface IDividerProps extends React.HTMLAttributes {} + +const Divider: React.FunctionComponent = ({...otherProps}) => { + return
{'Should be a divider'}
; +}; + +Divider.displayName = 'Divider'; + +export default Divider; diff --git a/packages/clay-sidebar/src/Panel.tsx b/packages/clay-sidebar/src/Panel.tsx new file mode 100644 index 0000000000..d601627286 --- /dev/null +++ b/packages/clay-sidebar/src/Panel.tsx @@ -0,0 +1,31 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import React from 'react'; + +interface IPanelProps extends React.HTMLAttributes { + show?: boolean; +} + +const Panel: React.FunctionComponent = ({ + children, + show = false, + ...otherProps +}) => { + if (show) { + return ( +
+ {children} +
+ ); + } + + return null; +}; + +Panel.displayName = 'Panel'; + +export default Panel; diff --git a/packages/clay-sidebar/src/Search.tsx b/packages/clay-sidebar/src/Search.tsx new file mode 100644 index 0000000000..db4ff5d51d --- /dev/null +++ b/packages/clay-sidebar/src/Search.tsx @@ -0,0 +1,49 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import ClayButton from '@clayui/button'; +import ClayForm, {ClayInput} from '@clayui/form'; +import ClayIcon from '@clayui/icon'; +import classNames from 'classnames'; +import React from 'react'; + +interface ISearchProps extends React.HTMLAttributes { + spritemap: string; +} + +const Search: React.FunctionComponent = ({ + className, + placeholder, + spritemap, + ...otherProps +}) => { + return ( + + + + + + + + + + + + + + ); +}; + +Search.displayName = 'Search'; + +export default Search; diff --git a/packages/clay-sidebar/src/Sidebar.scss b/packages/clay-sidebar/src/Sidebar.scss new file mode 100644 index 0000000000..62185d83a5 --- /dev/null +++ b/packages/clay-sidebar/src/Sidebar.scss @@ -0,0 +1,242 @@ +@import "@clayui/css/src/scss/atlas.scss"; + +// Variables + +$cmWidth: 3rem; +$cmBorderRight: 17rem; + +// CM +.cm { + color: $secondary-l1; + width: $cmWidth; + border-right: 0rem solid $dark; + box-sizing: content-box; + transition: border-right 300ms ease-in-out, width 300ms ease-in-out; + will-change: border-right, width; + + &.cm-active { + border-right-width: $cmBorderRight; + } + + &.cm-deactive { + width: 0rem; + } + + @include media-breakpoint-down(sm) { + position: absolute; + } +} + +.cm-bar { + position: fixed; + z-index: 1; + display: flex; + width: $cmWidth; + height: 100vh; + padding-bottom: $cmWidth; + flex-direction: column; + // transform: translateX(-100%); + transition: transform 300ms ease-in-out; + will-change: transform; + + &:after { + content: ""; + position: absolute; + z-index: 1; + top: 0; + right: 0; + bottom: 0; + // height: 100%; + left: 0; + background-color: $dark-d1; + } + + .cm-deactive & { + // transition-delay: 300ms; + transform: translateX(-100%); + } + + &.cm-open { + // transform: translateX(0%); + } +} + +.cm-submenu, +.cm-menu { + list-style: none; + margin-bottom: 0; + padding-left: 0; + overflow-y: auto; +} + +.cm-submenu { + // display: none; + overflow-y: hidden; + transition: max-height 300ms ease-in-out; + will-change: max-height; + max-height: 0px; + + &.cm-open { + // display: block; + max-height: 1000px; + } +} + +.cm-menu-button { + position: relative; + z-index: 2; + display: flex; + justify-content: center; + align-items: center; + transition: color 300ms ease-in-out, border-color 300ms ease-in-out, + background-color 300ms ease-in-out; + will-change: color, border-color, background-color; + border-radius: 0; + border-top: none; + border-right: 4px solid transparent; + border-bottom: none; + border-left: 4px solid transparent; + + &:hover, + &:focus { + color: $white; + } + + &.cm-active { + color: $white; + border-left-color: $primary-l1; + background-color: $dark; + } +} + +.cm-toggle { + position: fixed; + z-index: 3; + bottom: 0; + left: 0; + // background-color: $dark; + background-color: $dark-d1; + + .lexicon-icon { + transition: transform 300ms ease-in-out; + will-change: transform; + .cm-deactive & { + transform: rotateY(180deg); + } + } +} + +.cm-panel { + position: absolute; + background-color: $dark; + padding: 1rem; + top: 0; + left: 100%; + bottom: 0; + overflow-y: auto; + width: $cmBorderRight; + transition: transform 300ms ease-in-out; + will-change: transform; + transform: translateX(-100%); + + .cm-active & { + transition-delay: 300ms; + } + + &.cm-active { + transition-delay: 0ms; + transform: translateX(0%); + z-index: 1; + } +} + +// Panel Components + +.cm-panel-close { + position: absolute; + right: 0.5rem; + top: 0.5rem; + z-index: 2; + + &:focus, + &:hover { + color: inherit; + } +} + +.cm-panel-title { + font-size: 1rem; + font-weight: 600; + margin-bottom: 1.5rem; + line-height: 1.5; +} + +// Panel Content + +.cm-panel-search { + .form-control, + .btn { + background-color: $dark-l2; + border-color: $dark-l1; + } + + .form-control { + border-right: none; + color: inherit; + + &::placeholder { + color: $secondary-l1; + } + + // :not(:placeholder-shown) ~ .btn { + // color: $white; + // } + } + + .btn { + border-left: none; + color: $secondary-l1; + } +} + +.cm-panel-subtitle { + color: $secondary-l1; + font-size: 0.75rem; + font-weight: 400; + text-transform: uppercase; + margin-top: 1.25rem; + line-height: 1.5; +} + +.cm-panel-list { + list-style: none; + margin-bottom: 0; + padding-left: 0; +} + +.cm-panel-button { + text-align: left; + padding: 0.3215rem 0.75rem; + margin-top: 0.5rem; + font-size: 0.875rem; + color: $secondary-l2; + + img { + padding-top: 0.4375rem; + padding-bottom: 0.4375rem; + } + + .autofit-col:nth-child(2) { + margin-left: 0.5rem; + } + + &:hover, + &:focus { + color: $white; + } + + &.cm-active { + color: $white; + background-color: $dark-l1; + } +} diff --git a/packages/clay-sidebar/src/Toolbar.tsx b/packages/clay-sidebar/src/Toolbar.tsx new file mode 100644 index 0000000000..0152b25af0 --- /dev/null +++ b/packages/clay-sidebar/src/Toolbar.tsx @@ -0,0 +1,24 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import React from 'react'; + +interface IToolbarProps extends React.HTMLAttributes {} + +const Toolbar: React.FunctionComponent = ({ + children, + ...otherProps +}) => { + return ( + + ); +}; + +Toolbar.displayName = 'Toolbar'; + +export default Toolbar; diff --git a/packages/clay-sidebar/src/ToolbarItem.tsx b/packages/clay-sidebar/src/ToolbarItem.tsx new file mode 100644 index 0000000000..cf250c4271 --- /dev/null +++ b/packages/clay-sidebar/src/ToolbarItem.tsx @@ -0,0 +1,36 @@ +/* eslint-disable no-console */ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import classNames from 'classnames'; +import React from 'react'; + +interface IToolbarItemProps + extends React.HTMLAttributes { + active?: boolean; + expand?: boolean; +} + +const ToolbarItem: React.FunctionComponent = ({ + active, + children, + expand = false, +}) => { + return ( +
  • + {children} +
  • + ); +}; + +ToolbarItem.displayName = 'ToolbarItem'; + +export default ToolbarItem; diff --git a/packages/clay-sidebar/src/__tests__/__snapshots__/index.tsx.snap b/packages/clay-sidebar/src/__tests__/__snapshots__/index.tsx.snap new file mode 100644 index 0000000000..d1e5c85a7a --- /dev/null +++ b/packages/clay-sidebar/src/__tests__/__snapshots__/index.tsx.snap @@ -0,0 +1 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP diff --git a/packages/clay-sidebar/src/__tests__/index.tsx b/packages/clay-sidebar/src/__tests__/index.tsx new file mode 100644 index 0000000000..4636998523 --- /dev/null +++ b/packages/clay-sidebar/src/__tests__/index.tsx @@ -0,0 +1,19 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import ClaySidebar from '..'; +import {cleanup, render} from '@testing-library/react'; +import React from 'react'; + +describe('ClaySidebar', () => { + afterEach(cleanup); + + it('renders', () => { + const {container} = render(); + + expect(container).toMatchSnapshot(); + }); +}); diff --git a/packages/clay-sidebar/src/index.tsx b/packages/clay-sidebar/src/index.tsx new file mode 100644 index 0000000000..8745b1a5a7 --- /dev/null +++ b/packages/clay-sidebar/src/index.tsx @@ -0,0 +1,50 @@ +/* eslint-disable no-console */ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import React from 'react'; + +import Divider from './Divider'; +import Panel from './Panel'; +import Search from './Search'; +import Toolbar from './Toolbar'; +import ToolbarItem from './ToolbarItem'; + +type TDirection = 'left' | 'right'; + +type TDisplayType = 'dark' | 'light'; + +type TOpeningMode = 'overlay' | 'hover'; + +interface IProps extends React.HTMLAttributes { + direction?: TDirection; + displayType?: TDisplayType; + openingMode?: TOpeningMode; +} + +const ClaySidebar: React.FunctionComponent = ({ + children, + direction = 'left', + displayType = 'light', + openingMode = 'overlay', + ...otherProps +}) => { + console.log({direction, displayType, openingMode}); + + return ( +
    +
      {children}
    +
    + ); +}; + +export default Object.assign(ClaySidebar, { + Divider, + Panel, + Search, + Toolbar, + ToolbarItem, +}); diff --git a/packages/clay-sidebar/stories/index.tsx b/packages/clay-sidebar/stories/index.tsx new file mode 100644 index 0000000000..84f47af7f1 --- /dev/null +++ b/packages/clay-sidebar/stories/index.tsx @@ -0,0 +1,84 @@ +/** + * © 2019 Liferay, Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +import '@clayui/css/lib/css/atlas.css'; +import {ClayButtonWithIcon} from '@clayui/button'; +const spritemap = require('@clayui/css/lib/images/icons/icons.svg'); +import {storiesOf} from '@storybook/react'; +import React, {useState} from 'react'; + +import ClaySidebar from '../src'; + +const panels = [ + { + expand: true, + icon: 'chip', + label: 'Infrastructure', + panelId: 'infra', + }, + { + icon: 'calendar', + label: 'Calendar', + panelId: 'cal', + }, + { + expand: true, + icon: 'bolt', + label: 'Speed', + panelId: 'speed', + }, +]; + +storiesOf('Components|ClaySidebar', module).add('default', () => { + const [activePanelId, setActivePanelId] = useState(''); + + return ( + + +

    {'Panel 1'}

    + +
    + +

    {'Panel 2'}

    + +
    + +

    {'Panel 3'}

    + +
    + + {panels.map(({expand, icon, label, panelId}) => ( + + { + if (activePanelId === panelId) { + setActivePanelId(''); + return; + } + setActivePanelId(panelId); + }} + spritemap={spritemap} + symbol={icon} + /> + + ))} + +
    + ); +}); diff --git a/packages/clay-sidebar/tsconfig.declarations.json b/packages/clay-sidebar/tsconfig.declarations.json new file mode 100644 index 0000000000..24ffcb6625 --- /dev/null +++ b/packages/clay-sidebar/tsconfig.declarations.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "declarationDir": "./lib" + }, + "extends": "../../tsconfig.declarations.json", + "include": ["src"] +} diff --git a/packages/clay-sidebar/tsconfig.json b/packages/clay-sidebar/tsconfig.json new file mode 100644 index 0000000000..0c91d62848 --- /dev/null +++ b/packages/clay-sidebar/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src"] +}