From 657552033876d4cf1133a48f41ee404a83107b94 Mon Sep 17 00:00:00 2001 From: Stefan Popov Date: Mon, 13 Jul 2020 13:23:47 +0400 Subject: [PATCH 1/5] Add some icons --- src/assets/icons/more-horizontal.svg | 3 +++ src/assets/icons/plus.svg | 3 +++ src/styles/icons.scss | 20 ++++++++++++++++++++ 3 files changed, 26 insertions(+) create mode 100644 src/assets/icons/more-horizontal.svg create mode 100644 src/assets/icons/plus.svg diff --git a/src/assets/icons/more-horizontal.svg b/src/assets/icons/more-horizontal.svg new file mode 100644 index 00000000..dc1ec966 --- /dev/null +++ b/src/assets/icons/more-horizontal.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/plus.svg b/src/assets/icons/plus.svg new file mode 100644 index 00000000..4977f632 --- /dev/null +++ b/src/assets/icons/plus.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/styles/icons.scss b/src/styles/icons.scss index a4a4ddb7..f5fbb176 100644 --- a/src/styles/icons.scss +++ b/src/styles/icons.scss @@ -7,6 +7,16 @@ height: 16px; } + &plus-small { + position: absolute; + background-image: url('~@/assets/icons/plus.svg'); + background-size: contain; + width: 12px; + height: 12px; + top: -6px; + left: -6px; + } + &back { position: absolute; background-image: url('~@/assets/icons/arrow-left.svg'); @@ -14,6 +24,16 @@ height: 20px; } + &back-small { + position: absolute; + background-image: url('~@/assets/icons/arrow-left.svg'); + background-size: contain; + width: 12px; + height: 12px; + top: -6px; + left: -6px; + } + &globe { background-image: url('~@/assets/icons/globe.svg'); width: 20px; From 7d1929c74fe93fc7d879a40b003200ccabd5c00c Mon Sep 17 00:00:00 2001 From: Stefan Popov Date: Mon, 13 Jul 2020 13:24:19 +0400 Subject: [PATCH 2/5] Fix issues --- src/components/Layout/App/SApp.vue | 4 ++-- src/components/Layout/Header/SHeader.vue | 2 +- src/components/Tooltip/STooltip.vue | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/components/Layout/App/SApp.vue b/src/components/Layout/App/SApp.vue index 2dbd63ca..837a3063 100644 --- a/src/components/Layout/App/SApp.vue +++ b/src/components/Layout/App/SApp.vue @@ -21,7 +21,7 @@ import { Vue, Component } from 'vue-property-decorator' import { SAside } from '../Aside' -import { SContainer, ContainerDirection } from '../Container' +import { SContainer } from '../Container' import { SFooter } from '../Footer' import { SHeader } from '../Header' import { SMain } from '../Main' @@ -36,7 +36,7 @@ import { SMain } from '../Main' } }) export default class SApp extends Vue { - readonly ContainerDirection = ContainerDirection + // TODO: add properties for header, footer, aside height } diff --git a/src/components/Layout/Header/SHeader.vue b/src/components/Layout/Header/SHeader.vue index e2f02fc7..263efafc 100644 --- a/src/components/Layout/Header/SHeader.vue +++ b/src/components/Layout/Header/SHeader.vue @@ -22,7 +22,7 @@ export default class SHeader extends Vue { diff --git a/src/components/Dropdown/SDropdownItem.vue b/src/components/Dropdown/SDropdownItem.vue new file mode 100644 index 00000000..9e729274 --- /dev/null +++ b/src/components/Dropdown/SDropdownItem.vue @@ -0,0 +1,56 @@ + + + + + diff --git a/src/components/Dropdown/consts.ts b/src/components/Dropdown/consts.ts new file mode 100644 index 00000000..c6d7fb5f --- /dev/null +++ b/src/components/Dropdown/consts.ts @@ -0,0 +1,23 @@ +import { Size } from '../../types/size' + +export enum DropdownType { + DEFAULT = 'default', + BUTTON = 'button', + ELLIPSIS = 'ellipsis' +} + +export enum DropdownPlacement { + TOP = 'top', + TOP_START = 'top-start', + TOP_END = 'top-end', + BOTTOM = 'bottom', + BOTTOM_START = 'bottom-start', + BOTTOM_END = 'bottom-end' +} + +export enum DropdownTrigger { + HOVER = 'hover', + CLICK = 'click' +} + +export const DropdownSize = Size diff --git a/src/components/Dropdown/index.ts b/src/components/Dropdown/index.ts new file mode 100644 index 00000000..a465ab00 --- /dev/null +++ b/src/components/Dropdown/index.ts @@ -0,0 +1,4 @@ +import SDropdown from './SDropdown.vue' +import SDropdownItem from './SDropdownItem.vue' + +export { SDropdown, SDropdownItem } diff --git a/src/components/index.ts b/src/components/index.ts index 67e726b0..2243316c 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -7,6 +7,7 @@ import { SButton, SButtonGroup } from './Button' import { SCard } from './Card' import { SCol } from './Layout/Col' import { SContainer } from './Layout/Container' +import { SDropdown, SDropdownItem } from './Dropdown' import { SFooter } from './Layout/Footer' import { SForm, SFormItem } from './Form' import { SHeader } from './Layout/Header' @@ -24,6 +25,8 @@ export { SCard, SCol, SContainer, + SDropdown, + SDropdownItem, SFooter, SForm, SFormItem, diff --git a/src/stories/Dropdown/SDropdown.stories.ts b/src/stories/Dropdown/SDropdown.stories.ts new file mode 100644 index 00000000..f9fd3c84 --- /dev/null +++ b/src/stories/Dropdown/SDropdown.stories.ts @@ -0,0 +1,23 @@ +import { text, withKnobs, select } from '@storybook/addon-knobs' + +import { SDropdown, SDropdownItem, SRow } from '../../components' + +export default { + component: SDropdown, + title: 'Design System/Dropdown', + decorators: [withKnobs], + excludeStories: /.*Data$/ +} + +export const configurable = () => ({ + components: { SDropdown, SDropdownItem }, + template: ` + Dropdown + + ` +}) From 2b17746cfdfff46c76c58ff85d4f115815f42a21 Mon Sep 17 00:00:00 2001 From: Stefan Popov Date: Tue, 14 Jul 2020 11:23:15 +0400 Subject: [PATCH 4/5] Complete dropdown implementation --- src/components/Dropdown/SDropdown.vue | 60 ++++++++++++++++++++------- src/components/Dropdown/index.ts | 10 ++++- src/styles/icons.scss | 7 ++++ 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/components/Dropdown/SDropdown.vue b/src/components/Dropdown/SDropdown.vue index 3d91b009..5b6e3091 100644 --- a/src/components/Dropdown/SDropdown.vue +++ b/src/components/Dropdown/SDropdown.vue @@ -5,7 +5,7 @@ :size="computedSize" :type="computedType" :placement="placement" - :trigger="trigger" + :trigger="computedTrigger" :hide-on-click="hideOnClick" :show-timeout="showTimeout" :hide-timeout="hideTimeout" @@ -14,21 +14,27 @@ @command="handleSelect" @visible-change="handleVisibleChange" > - + + + + - + @@ -40,10 +46,12 @@ import { ElDropdown } from 'element-ui/types/dropdown' import { DropdownType, DropdownSize, DropdownPlacement, DropdownTrigger } from './consts' import { ButtonTypes } from '../Button' -import { SButton, STooltip } from '../../components' +import { SButton } from '../../components' @Component({ - components: { SButton, STooltip } + components: { + SButton + } }) export default class SDropdown extends Vue { readonly DropdownType = DropdownType @@ -75,6 +83,7 @@ export default class SDropdown extends Vue { @Prop({ type: String, default: DropdownPlacement.BOTTOM_END }) readonly placement!: string /** * A trigger action of the dropdown component. Can be `"hover"` or `"click"`. + * When dropdown type is "ellipsis", `trigger = "click"`. * * By default, it's set to `"hover"` */ @@ -112,6 +121,8 @@ export default class SDropdown extends Vue { @Ref('dropdown') dropdown!: ElDropdown + willTooltipBeDisabled = false + get computedType () { if (this.type === DropdownType.BUTTON) { return this.computedButtonType @@ -119,6 +130,16 @@ export default class SDropdown extends Vue { return '' } + get computedTrigger (): string { + if (this.type === DropdownType.ELLIPSIS) { + return DropdownTrigger.CLICK + } + if (!(Object.values(DropdownTrigger) as Array).includes(this.trigger)) { + return DropdownTrigger.HOVER + } + return this.trigger + } + get computedSize (): string { if (this.size === DropdownSize.BIG || !(Object.values(DropdownSize) as Array).includes(this.size)) { @@ -128,7 +149,8 @@ export default class SDropdown extends Vue { } get computedButtonType (): string { - if (this.buttonType === ButtonTypes.ACTION) { + if (this.buttonType === ButtonTypes.ACTION || + !(Object.values(ButtonTypes) as Array).includes(this.buttonType)) { console.warn(`"${this.buttonType}" button type is unsupported! Secondary button type is set.`) return ButtonTypes.SECONDARY } @@ -136,13 +158,16 @@ export default class SDropdown extends Vue { } mounted (): void { - this.$nextTick(() => { - if (this.splitButton) { + if (this.splitButton) { + this.$nextTick(() => { this.dropdown.$children[0].$children.forEach(button => { button.$el.classList.add(this.size, this.computedButtonType) }) - } - }) + }) + } + if (this.type === DropdownType.ELLIPSIS) { + this.$watch('$refs.dropdown.visible', (visible) => { this.willTooltipBeDisabled = visible }) + } } handleClick (): void { @@ -190,5 +215,12 @@ export default class SDropdown extends Vue { } } } + > i { + cursor: pointer; + } +} +.ellipsis.el-popper[x-placement^=bottom] { + margin-top: 25px; + margin-left: 12px; } diff --git a/src/components/Dropdown/index.ts b/src/components/Dropdown/index.ts index a465ab00..87bb2280 100644 --- a/src/components/Dropdown/index.ts +++ b/src/components/Dropdown/index.ts @@ -1,4 +1,12 @@ import SDropdown from './SDropdown.vue' import SDropdownItem from './SDropdownItem.vue' +import { DropdownPlacement, DropdownSize, DropdownTrigger, DropdownType } from './consts' -export { SDropdown, SDropdownItem } +export { + SDropdown, + SDropdownItem, + DropdownPlacement, + DropdownSize, + DropdownTrigger, + DropdownType +} diff --git a/src/styles/icons.scss b/src/styles/icons.scss index f5fbb176..2367f2ae 100644 --- a/src/styles/icons.scss +++ b/src/styles/icons.scss @@ -24,6 +24,13 @@ height: 20px; } + &more { + position: absolute; + background-image: url('~@/assets/icons/more-horizontal.svg'); + width: 21px; + height: 20px; + } + &back-small { position: absolute; background-image: url('~@/assets/icons/arrow-left.svg'); From a3184822a145659b5c6c367d8ce4555a6abf33b9 Mon Sep 17 00:00:00 2001 From: Stefan Popov Date: Tue, 14 Jul 2020 11:23:43 +0400 Subject: [PATCH 5/5] Add new stories for dropdown components --- src/stories/Dropdown/SDropdown.stories.ts | 184 +++++++++++++++++- src/stories/Dropdown/SDropdownItem.stories.ts | 30 +++ 2 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 src/stories/Dropdown/SDropdownItem.stories.ts diff --git a/src/stories/Dropdown/SDropdown.stories.ts b/src/stories/Dropdown/SDropdown.stories.ts index f9fd3c84..b28c813b 100644 --- a/src/stories/Dropdown/SDropdown.stories.ts +++ b/src/stories/Dropdown/SDropdown.stories.ts @@ -1,6 +1,8 @@ -import { text, withKnobs, select } from '@storybook/addon-knobs' +import { number, withKnobs, select, boolean } from '@storybook/addon-knobs' -import { SDropdown, SDropdownItem, SRow } from '../../components' +import { SCol, SDropdown, SDropdownItem, SRow } from '../../components' +import { DropdownPlacement, DropdownSize, DropdownTrigger, DropdownType } from '../../components/Dropdown' +import { ButtonTypes } from '../../components/Button' export default { component: SDropdown, @@ -11,13 +13,177 @@ export default { export const configurable = () => ({ components: { SDropdown, SDropdownItem }, - template: ` - Dropdown + template: ` + Dropdown menu - ` + `, + props: { + buttonType: { + default: select('Button Type', Object.values(ButtonTypes), ButtonTypes.SECONDARY) + }, + placement: { + default: select('Placement', Object.values(DropdownPlacement), DropdownPlacement.BOTTOM_END) + }, + hideOnClick: { + default: boolean('Hide On Click', true) + }, + showTimeout: { + default: number('Show Timeout', 250) + }, + hideTimeout: { + default: number('Hide Timeout', 150) + } + }, + methods: { + handleSelect: (value: string) => alert(`${value} is selected`) + } +}) + +export const differentTypesData = Object.values(DropdownType).map(type => { + const data = { type } as any + data.label = type[0].toUpperCase() + type.slice(1) + return data +}) +export const buttonTypesData = Object.values(ButtonTypes).map(buttonType => { + const data = { buttonType, type: DropdownType.BUTTON } as any + data.label = buttonType[0].toUpperCase() + buttonType.slice(1) + ' button' + return data +}) +export const differentTypes = () => ({ + components: { SCol, SDropdown, SDropdownItem, SRow }, + template: ` + Different types + + + {{ item.label }} + + + + Different button types + + + {{ item.label }} + + + + Different button types with splitted button + + + {{ item.label }} + + + + `, + props: { + differentTypesData: { + default: () => differentTypesData + }, + buttonTypesData: { + default: () => buttonTypesData.filter(data => data.buttonType !== ButtonTypes.ACTION) + } + }, + methods: { + handleClick: () => alert('clicked') + } +}) + +export const differentSizeData = Object.values(DropdownSize).map(size => { + const data = { size, type: DropdownType.BUTTON, buttonType: ButtonTypes.PRIMARY } as any + data.label = size[0].toUpperCase() + size.slice(1) + return data +}) +export const differentSize = () => ({ + components: { SCol, SDropdown, SDropdownItem, SRow }, + template: ` + + + {{ item.label }} + + + + `, + props: { + differentSizeData: { + default: () => differentSizeData + } + } +}) + +export const differentTriggerData = Object.values(DropdownTrigger).map(trigger => { + const data = { trigger, type: DropdownType.BUTTON, buttonType: ButtonTypes.PRIMARY } as any + data.label = trigger[0].toUpperCase() + trigger.slice(1) + return data +}) +export const differentTrigger = () => ({ + components: { SCol, SDropdown, SDropdownItem, SRow }, + template: ` + + + {{ item.label }} + + + + `, + props: { + differentTriggerData: { + default: () => differentTriggerData + } + } }) diff --git a/src/stories/Dropdown/SDropdownItem.stories.ts b/src/stories/Dropdown/SDropdownItem.stories.ts new file mode 100644 index 00000000..62315af4 --- /dev/null +++ b/src/stories/Dropdown/SDropdownItem.stories.ts @@ -0,0 +1,30 @@ +import { withKnobs, boolean } from '@storybook/addon-knobs' + +import { SDropdown, SDropdownItem } from '../../components' + +export default { + component: SDropdownItem, + title: 'Design System/Dropdown/DropdownItem', + decorators: [withKnobs] +} + +export const configurable = () => ({ + components: { SDropdown, SDropdownItem }, + template: ` + Main menu + + `, + props: { + disabled: { + default: () => boolean('Disabled', false) + }, + divided: { + default: () => boolean('Divided', false) + } + } +})