completed submenu
This commit is contained in:
parent
8428ef730c
commit
74becd6437
71
packages/asc-web-components/submenu/README.md
Normal file
71
packages/asc-web-components/submenu/README.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Submenu
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Submenu from "@appserver/components/submenu";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Submenu
|
||||
data={[
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "ToggleButton",
|
||||
name: "Toggle Button",
|
||||
content: (
|
||||
<ToggleButton
|
||||
className="toggle className"
|
||||
id="toggle id"
|
||||
label="label text"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
startSelect={1}
|
||||
/>
|
||||
```
|
||||
|
||||
#### Data is an array of objects with following fields:
|
||||
|
||||
- id - unique id
|
||||
- name - header in submenu
|
||||
- content - HTML object that will be rendered under submenu
|
||||
|
||||
##### Example:
|
||||
|
||||
```jsx
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------- | :-------------: | :------: | :----: | :-----: | ----------------------------------------------------------------------------- |
|
||||
| `data` | `array` | ✅ | - | - | List of elements |
|
||||
| `startSelect` | `obj`, `number` | - | - | 0 | Object from data that will be chosen first **OR** Its index in **data** array |
|
89
packages/asc-web-components/submenu/data.js
Normal file
89
packages/asc-web-components/submenu/data.js
Normal file
@ -0,0 +1,89 @@
|
||||
import React from "react";
|
||||
import FileInput from "@appserver/components/file-input";
|
||||
import Row from "@appserver/components/row";
|
||||
import Textarea from "@appserver/components/textarea";
|
||||
import Text from "../text";
|
||||
|
||||
export const data = [
|
||||
{
|
||||
id: "Overview",
|
||||
name: "Overview",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={() => {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Documents",
|
||||
name: "Documents",
|
||||
content: (
|
||||
<Textarea
|
||||
onChange={() => {}}
|
||||
value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor. Aenean massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, justo. Nullam dictum felis eu pede mollis pretium. Integer tincidunt. Cras dapibus. Vivamus elementum semper nisi. Aenean vulputate eleifend tellus. Aenean leo ligula, porttitor eu, consequat vitae"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Milestones",
|
||||
name: "Milestones",
|
||||
content: (
|
||||
<Row
|
||||
key="1"
|
||||
checked
|
||||
contextOptions={[
|
||||
{
|
||||
key: "key1",
|
||||
label: "Edit",
|
||||
onClick: () => {},
|
||||
},
|
||||
{
|
||||
key: "key2",
|
||||
label: "Delete",
|
||||
onClick: function noRefCheck() {},
|
||||
},
|
||||
]}
|
||||
onRowClick={function noRefCheck() {}}
|
||||
onSelect={function noRefCheck() {}}
|
||||
>
|
||||
<Text truncate>Sample text</Text>
|
||||
</Row>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "Time tracking",
|
||||
name: "Time tracking",
|
||||
content: <p>Time tracking</p>,
|
||||
},
|
||||
{
|
||||
id: "Contacts",
|
||||
name: "Contacts",
|
||||
content: <p>Contacts</p>,
|
||||
},
|
||||
{
|
||||
id: "Team",
|
||||
name: "Team",
|
||||
content: <p>Team</p>,
|
||||
},
|
||||
];
|
||||
|
||||
export const startSelect = data[2];
|
||||
|
||||
export const testData = [
|
||||
{
|
||||
id: "Tab1",
|
||||
name: "Tab1",
|
||||
content: <p>1</p>,
|
||||
},
|
||||
{
|
||||
id: "Tab2",
|
||||
name: "Tab2",
|
||||
content: <p>2</p>,
|
||||
},
|
||||
];
|
||||
|
||||
export const testStartSelect = testData[1];
|
69
packages/asc-web-components/submenu/index.js
Normal file
69
packages/asc-web-components/submenu/index.js
Normal file
@ -0,0 +1,69 @@
|
||||
import PropTypes from "prop-types";
|
||||
import React, { useState } from "react";
|
||||
|
||||
import Text from "../text";
|
||||
import {
|
||||
StyledSubmenu,
|
||||
StyledSubmenuBottomLine,
|
||||
StyledSubmenuContentWrapper,
|
||||
StyledSubmenuItem,
|
||||
StyledSubmenuItemLabel,
|
||||
StyledSubmenuItems,
|
||||
StyledSubmenuItemText,
|
||||
} from "./styled-submenu";
|
||||
|
||||
const Submenu = ({ data, startSelect = 0 }) => {
|
||||
if (!data) return null;
|
||||
|
||||
const [currentItem, setCurrentItem] = useState(
|
||||
data[startSelect] || startSelect || null
|
||||
);
|
||||
|
||||
const onSelectSubmenuItem = (e) => {
|
||||
const item = data.find((el) => el.id === e.target.title);
|
||||
console.log(e.toString());
|
||||
if (item) setCurrentItem(item);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledSubmenu>
|
||||
<StyledSubmenuItems>
|
||||
{data.map((d) => {
|
||||
const isActive = d === currentItem;
|
||||
return (
|
||||
<StyledSubmenuItem
|
||||
key={d.id}
|
||||
onClick={(e) => onSelectSubmenuItem(e)}
|
||||
>
|
||||
<StyledSubmenuItemText>
|
||||
<Text
|
||||
style={{ cursor: "pointer" }}
|
||||
title={d.id}
|
||||
color={isActive ? "#316DAA" : "#657077"}
|
||||
fontSize="13px"
|
||||
fontWeight="600"
|
||||
truncate="false"
|
||||
>
|
||||
{d.name}
|
||||
</Text>
|
||||
</StyledSubmenuItemText>
|
||||
<StyledSubmenuItemLabel color={isActive ? "#316DAA" : "none"} />
|
||||
</StyledSubmenuItem>
|
||||
);
|
||||
})}
|
||||
</StyledSubmenuItems>
|
||||
<StyledSubmenuBottomLine />
|
||||
|
||||
<StyledSubmenuContentWrapper>
|
||||
{currentItem.content}
|
||||
</StyledSubmenuContentWrapper>
|
||||
</StyledSubmenu>
|
||||
);
|
||||
};
|
||||
|
||||
Submenu.propTypes = {
|
||||
data: PropTypes.arrayOf(PropTypes.object.isRequired).isRequired,
|
||||
startSelect: PropTypes.oneOfType([PropTypes.object, PropTypes.number]),
|
||||
};
|
||||
|
||||
export default Submenu;
|
51
packages/asc-web-components/submenu/styled-submenu.js
Normal file
51
packages/asc-web-components/submenu/styled-submenu.js
Normal file
@ -0,0 +1,51 @@
|
||||
import styled from "styled-components";
|
||||
|
||||
export const StyledSubmenu = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuBottomLine = styled.div`
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
margin: -1px 0 15px 0;
|
||||
background: #eceef1;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuContentWrapper = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItems = styled.div`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 4px;
|
||||
padding: 0 20px;
|
||||
@media (max-width: 768px) {
|
||||
padding: 0 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItem = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
line-height: 20px;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItemText = styled.div`
|
||||
width: 100%;
|
||||
display: flex;
|
||||
padding: 4px 14px;
|
||||
`;
|
||||
|
||||
export const StyledSubmenuItemLabel = styled.div`
|
||||
positin: absolute;
|
||||
width: 100%;
|
||||
height: 4px;
|
||||
bottom: 0px;
|
||||
border-radius: 4px 4px 0 0;
|
||||
background-color: ${(props) => props.color};
|
||||
`;
|
25
packages/asc-web-components/submenu/submenu.stories.js
Normal file
25
packages/asc-web-components/submenu/submenu.stories.js
Normal file
@ -0,0 +1,25 @@
|
||||
import Submenu from ".";
|
||||
import React from "react";
|
||||
import { data, startSelect } from "./data";
|
||||
|
||||
const Wrapper = (props) => (
|
||||
<div
|
||||
style={{
|
||||
height: "170px",
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
|
||||
const Template = (args) => (
|
||||
<Wrapper>
|
||||
<Submenu {...args} />
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
data: data,
|
||||
startSelect: startSelect,
|
||||
};
|
64
packages/asc-web-components/submenu/submenu.stories.mdx
Normal file
64
packages/asc-web-components/submenu/submenu.stories.mdx
Normal file
@ -0,0 +1,64 @@
|
||||
import { Canvas, Meta, Story } from "@storybook/addon-docs/blocks";
|
||||
|
||||
import Submenu from "./";
|
||||
import * as stories from "./submenu.stories.js";
|
||||
|
||||
<Meta
|
||||
title="Components/Submenu"
|
||||
component={Submenu}
|
||||
argTypes={{
|
||||
data: { required: true },
|
||||
}}
|
||||
/>
|
||||
|
||||
# Submenu
|
||||
|
||||
<Canvas>
|
||||
<Story story={stories.Default} name="Default" />
|
||||
</Canvas>
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import Submenu from "@appserver/components/submenu";
|
||||
```
|
||||
|
||||
```jsx
|
||||
<Submenu
|
||||
data={[
|
||||
{
|
||||
id: "FileInput",
|
||||
name: "File Input",
|
||||
content: (
|
||||
<FileInput
|
||||
accept=".doc, .docx"
|
||||
id="file-input-id"
|
||||
name="demoFileInputName"
|
||||
onInput={function noRefCheck() {}}
|
||||
placeholder="Input file"
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: "ToggleButton",
|
||||
name: "Toggle Button",
|
||||
content: (
|
||||
<ToggleButton
|
||||
className="toggle className"
|
||||
id="toggle id"
|
||||
label="label text"
|
||||
onChange={() => {}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
]}
|
||||
startSelect={1}
|
||||
/>
|
||||
```
|
||||
|
||||
### Properties
|
||||
|
||||
| Props | Type | Required | Values | Default | Description |
|
||||
| ------------- | :-------------: | :------: | :----: | :-----: | ----------------------------------------------------------------------------------- |
|
||||
| `data` | `array` | ✅ | - | - | List of elements |
|
||||
| `startSelect` | `obj`, `number` | - | - | 0 | Object from **`data`** **OR** Its index in **`data`** that will be a default select |
|
76
packages/asc-web-components/submenu/submenu.test.js
Normal file
76
packages/asc-web-components/submenu/submenu.test.js
Normal file
@ -0,0 +1,76 @@
|
||||
import { mount, shallow } from "enzyme";
|
||||
import React from "react";
|
||||
|
||||
import Submenu from "./";
|
||||
import { testData, testStartSelect } from "./data";
|
||||
|
||||
const props = {
|
||||
data: testData,
|
||||
startSelect: testStartSelect,
|
||||
};
|
||||
|
||||
const onlyData = {
|
||||
data: testData,
|
||||
};
|
||||
|
||||
describe("<Submenu />", () => {
|
||||
it("renders without error", () => {
|
||||
const wrapper = mount(<Submenu {...props} />);
|
||||
expect(wrapper).toExist(true);
|
||||
});
|
||||
|
||||
it("gets data prop", () => {
|
||||
const wrapper = mount(<Submenu {...onlyData} />);
|
||||
expect(wrapper.prop("data")).toEqual(testData);
|
||||
});
|
||||
|
||||
it("doesnt render without data prop", () => {
|
||||
const wrapper = mount(<Submenu />);
|
||||
expect(wrapper).toExist(false);
|
||||
});
|
||||
|
||||
it("gets startSelect prop", () => {
|
||||
const wrapper = mount(<Submenu {...props} />);
|
||||
expect(wrapper.prop("startSelect")).toEqual(testStartSelect);
|
||||
});
|
||||
|
||||
it("selects first data item as currentItem without startSelect prop", () => {
|
||||
const wrapper = shallow(<Submenu {...onlyData} />)
|
||||
.find("styled-submenu__StyledSubmenuContentWrapper")
|
||||
.childAt(0);
|
||||
const currentItemWrapper = shallow(testData[0].content);
|
||||
expect(wrapper.debug()).toEqual(currentItemWrapper.debug());
|
||||
});
|
||||
|
||||
// TODO : Develop a test that will monitor content after tab clicks
|
||||
// it("changes currentItem after clicking on SubmenuItem", () => {
|
||||
// let wrapper = shallow(<Submenu data={testData} startSelect={1} />);
|
||||
// const tabs = wrapper.find("styled-submenu__StyledSubmenuItem");
|
||||
// console.log(wrapper.debug());
|
||||
// tabs.forEach((t, i = 0) => {
|
||||
// console.log("\n\n --- ITERATION", i, " ---\n");
|
||||
// console.log(t.debug());
|
||||
|
||||
// const text = mount();
|
||||
// t.simulate("click", { target: { text } });
|
||||
|
||||
// const newDisplayedContent = wrapper
|
||||
// .update()
|
||||
// .find("styled-submenu__StyledSubmenuContentWrapper")
|
||||
// .childAt(0);
|
||||
|
||||
// const newCurrentItem = mount(testData[i].content);
|
||||
// i++;
|
||||
|
||||
// console.log(
|
||||
// "\nCONTENT ON THE PAGE - \n",
|
||||
// newDisplayedContent.debug(),
|
||||
// "\n",
|
||||
// "\nCONTENT FROM THE DATA - \n",
|
||||
// newCurrentItem.debug(),
|
||||
// "\n\n\n"
|
||||
// );
|
||||
// expect(newDisplayedContent.debug()).toEqual(newCurrentItem.debug());
|
||||
// });
|
||||
// });
|
||||
});
|
Loading…
Reference in New Issue
Block a user