@gitlab/ui
Version:
GitLab UI Components
575 lines (548 loc) • 15.5 kB
JavaScript
import iconSpriteInfo from '@gitlab/svgs/dist/icons.json';
import GlAvatar from '../avatar/avatar.vue';
import GlIcon from '../icon/icon.vue';
import GlButton from '../button/button.vue';
import GlSearchBoxByType from '../search_box_by_type/search_box_by_type.vue';
import {
buttonCategoryOptions,
buttonSizeOptions,
dropdownVariantOptions,
} from '../../../utils/constants';
import GlDropdownDivider from './dropdown_divider.vue';
import GlDropdownSectionHeader from './dropdown_section_header.vue';
import GlDropdownItem from './dropdown_item.vue';
import GlDropdownText from './dropdown_text.vue';
import GlDropdownForm from './dropdown_form.vue';
import GlDropdown from './dropdown.vue';
import readme from './dropdown.md';
const components = {
GlAvatar,
GlIcon,
GlDropdown,
GlDropdownDivider,
GlDropdownSectionHeader,
GlDropdownItem,
GlDropdownText,
GlDropdownForm,
};
function addClass(component) {
component.$el.querySelectorAll('.btn').forEach((el) => el.classList.add('gl-button'));
}
const defaultValue = (prop) => GlDropdown.props[prop].default;
const generateProps = ({
headerText = defaultValue('headerText'),
hideHeaderBorder = defaultValue('hideHeaderBorder'),
showClearAll = defaultValue('showClearAll'),
clearAllText = defaultValue('clearAllText'),
clearAllTextClass = defaultValue('clearAllTextClass'),
text = defaultValue('text'),
showHighlightedItemsTitle = defaultValue('showHighlightedItemsTitle'),
highlightedItemsTitle = defaultValue('highlightedItemsTitle'),
highlightedItemsTitleClass = defaultValue('highlightedItemsTitleClass'),
textSrOnly = defaultValue('textSrOnly'),
split = defaultValue('split'),
category = defaultValue('category'),
variant = defaultValue('variant'),
size = defaultValue('size'),
icon = defaultValue('icon'),
block = defaultValue('block'),
disabled = defaultValue('disabled'),
loading = defaultValue('loading'),
toggleClass = defaultValue('toggleClass'),
right = defaultValue('right'),
} = {}) => ({
headerText,
hideHeaderBorder,
showClearAll,
clearAllText,
clearAllTextClass,
text,
showHighlightedItemsTitle,
highlightedItemsTitle,
highlightedItemsTitleClass,
textSrOnly,
split,
category,
variant,
size,
icon,
block,
disabled,
loading,
toggleClass,
right,
});
const withContainer = (template, containerHeight = 150) => `
<div style="height: ${containerHeight}px;">
${template}
</div>`;
function wrap(template, containerHeight, cssClass) {
return withContainer(
`
<gl-dropdown
ref="dropdown"
:category="category"
:variant="variant"
:size="size"
:block="block"
:disabled="disabled"
:text="text"
:text-sr-only="textSrOnly"
:icon="icon"
:split="split"
:toggle-class="toggleClass"
:header-text="headerText"
:hide-header-border="hideHeaderBorder"
:show-clear-all="showClearAll"
:clear-all-text="clearAllText"
:clear-all-text-class="clearAllTextClass"
:show-highlighted-items-title="showHighlightedItemsTitle"
:highlighted-items-title="highlightedItemsTitle"
:highlighted-items-title-class="highlightedItemsTitleClass"
:loading="loading"
:right="right"
class="${cssClass}"
>
${template}
</gl-dropdown>`,
containerHeight
);
}
function clickDropdown(component) {
component.$nextTick(() => component.$el.querySelector('.dropdown-toggle').click());
}
export const Default = (_args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>
<gl-dropdown-item>Fifth item</gl-dropdown-item>
<gl-dropdown-item>Sixth item</gl-dropdown-item>
<gl-dropdown-item>Seventh item</gl-dropdown-item>
<gl-dropdown-item>Eighth item</gl-dropdown-item>
<gl-dropdown-item>Ninth item</gl-dropdown-item>
<gl-dropdown-item>Tenth item</gl-dropdown-item>
<gl-dropdown-item>Eleventh item</gl-dropdown-item>`,
340
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
Default.args = generateProps({ text: 'Some dropdown' });
export const Secondary = (_args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Third item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
Secondary.args = generateProps({
text: 'Some dropdown',
category: buttonCategoryOptions.secondary,
variant: dropdownVariantOptions.confirm,
});
export const WithForm = (_args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { ...components, GlButton },
template: wrap(`
<gl-dropdown-form class="gl-px-4">
<gl-button>One</gl-button>
<gl-button>Two</gl-button>
<gl-button>Three</gl-button>
</gl-dropdown-form>`),
mounted() {
clickDropdown(this);
},
});
WithForm.args = generateProps({ text: 'Some dropdown' });
export const WithDivider = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-divider />
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>`,
200
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithDivider.args = generateProps({ text: 'Some dropdown' });
export const WithHeaderAndFooter = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components: { ...components, GlSearchBoxByType },
template: wrap(
`
<template #header>
<gl-search-box-by-type />
</template>
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>
<gl-dropdown-item>Fifth item</gl-dropdown-item>
<gl-dropdown-item>Sixth item</gl-dropdown-item>
<gl-dropdown-item>Seventh item</gl-dropdown-item>
<gl-dropdown-item>Eighth item</gl-dropdown-item>
<template #footer>
<gl-dropdown-item>First footer item</gl-dropdown-item>
<gl-dropdown-item>Second footer item</gl-dropdown-item>
</template>`,
340
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithHeaderAndFooter.args = generateProps({
text: 'Some dropdown',
headerText: 'Header',
hideHeaderBorder: true,
});
export const WithSectionHeader = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<gl-dropdown-section-header>Header title</gl-dropdown-section-header>
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-section-header>I am a really long header title which should wrap</gl-dropdown-section-header>
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>`,
300
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithSectionHeader.args = generateProps({ text: 'Some dropdown' });
export const WithCheckedItems = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item :is-check-item="true" :is-checked="true">Checked item</gl-dropdown-item>
<gl-dropdown-item :is-check-item="true">Unchecked item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithCheckedItems.args = generateProps({ text: 'Some dropdown' });
export const WithAvatarAndSecondaryText = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item
avatar-url="./img/avatar.png"
secondary-text="@sytses"
>
Sid Sijbrandij
</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithAvatarAndSecondaryText.args = generateProps({ text: 'Some dropdown' });
export const WithIcons = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<gl-dropdown-item
icon-color="info"
icon-name="status_running"
icon-right-name="retry"
icon-right-aria-label="Retry"
>
Status running
</gl-dropdown-item>
<gl-dropdown-item
icon-color="success"
icon-name="status_success"
icon-right-name="cancel"
icon-right-aria-label="Cancel"
>
Status success
</gl-dropdown-item>
<gl-dropdown-item
icon-color="warning"
icon-name="status_warning"
icon-right-name="cancel"
icon-right-aria-label="Cancel"
>
Status warning
</gl-dropdown-item>
<gl-dropdown-item
icon-color="danger"
icon-name="status_failed"
icon-right-name="cancel"
icon-right-aria-label="Cancel"
>
Status failed
</gl-dropdown-item>
<gl-dropdown-item
icon-name="status_manual"
icon-right-name="cancel"
icon-right-aria-label="Cancel"
>
Status manual
</gl-dropdown-item>`,
200
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithIcons.args = generateProps({ text: 'Some dropdown' });
export const FullWidth = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Last item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
FullWidth.args = generateProps({ text: 'Some dropdown', block: true });
export const WithShortTextAndWideWidth = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: withContainer(`
<gl-dropdown
text="Some dropdown"
:category="category"
:variant="variant"
:size="size"
:block="block"
:disabled="disabled"
style="width: 300px;"
>
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Last item</gl-dropdown-item>
</gl-dropdown>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithShortTextAndWideWidth.args = generateProps();
export const WithLongTextAndNarrowWidth = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: withContainer(`
<gl-dropdown
text="Truncated text dropdown"
:category="category"
:variant="variant"
:size="size"
:block="block"
:disabled="disabled"
style="width: 160px;"
>
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Last item</gl-dropdown-item>
</gl-dropdown>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithLongTextAndNarrowWidth.args = generateProps({ block: true });
export const WithItemTextThatDoesNotWrap = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item icon-right-name="star" icon-right-aria-label="Some action">
Normal item
</gl-dropdown-item>
<gl-dropdown-item icon-right-name="star" icon-right-aria-label="Some action">
<div class="gl-text-truncate">ellipsis/should/truncate/this/item</div>
</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithItemTextThatDoesNotWrap.args = generateProps({ text: 'Some dropdown' });
export const IconOnly = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Last item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
IconOnly.args = generateProps({ icon: 'ellipsis_v', text: 'More actions', textSrOnly: true });
export const WithLoadingState = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Last item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithLoadingState.args = generateProps({ text: 'Some dropdown', loading: true });
export const WithClearAll = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(`
<gl-dropdown-item :is-check-item="true" :is-checked="true">First item</gl-dropdown-item>
<gl-dropdown-item :is-check-item="true" :is-checked="true">Second item</gl-dropdown-item>
<gl-dropdown-item :is-check-item="true" :is-checked="true">Third item</gl-dropdown-item>`),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithClearAll.args = generateProps({
text: 'Some dropdown',
showClearAll: true,
clearAllText: 'Clear all',
clearAllTextClass: 'gl-px-5',
});
export const WithHighlightedItems = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<template #highlighted-items>
<gl-dropdown-item :is-check-item="true" :is-checked="true">First item</gl-dropdown-item>
<gl-dropdown-item :is-check-item="true" :is-checked="true">Second item</gl-dropdown-item>
</template>
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>
`,
200
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
WithHighlightedItems.args = generateProps({
text: 'Some dropdown',
showHighlightedItemsTitle: true,
highlightedItemsTitle: 'Highlights',
highlightedItemsTitleClass: 'gl-px-5',
});
export const OnRightEdge = (args, { argTypes }) => ({
props: Object.keys(argTypes),
components,
template: wrap(
`
<gl-dropdown-item>First item</gl-dropdown-item>
<gl-dropdown-item>Second item</gl-dropdown-item>
<gl-dropdown-item>Third item</gl-dropdown-item>
<gl-dropdown-item>Fourth item</gl-dropdown-item>
`,
200,
'gl-display-block gl-text-right'
),
mounted() {
clickDropdown(this);
},
updated() {
addClass(this);
},
});
OnRightEdge.args = generateProps({ text: 'Some dropdown' });
export default {
title: 'base/dropdown/deprecated',
component: GlDropdown,
subcomponents: {
GlDropdownDivider,
GlDropdownForm,
GlDropdownItem,
GlDropdownSectionHeader,
GlDropdownText,
},
parameters: {
bootstrapComponent: 'b-dropdown',
docs: {
description: {
component: readme,
},
},
},
argTypes: {
category: {
options: Object.keys(buttonCategoryOptions),
control: 'select',
},
variant: {
options: Object.keys(dropdownVariantOptions),
control: 'select',
},
size: {
options: Object.keys(buttonSizeOptions),
control: 'select',
},
icon: {
options: iconSpriteInfo.icons,
control: 'select',
},
},
};