diff --git a/src/components/register.ts b/src/components/register.ts
index 8976593180..69470f5254 100644
--- a/src/components/register.ts
+++ b/src/components/register.ts
@@ -14,7 +14,8 @@ import VList, {
VListItemContent,
VListItemIcon,
VListItemSubtitle,
- VListItemTitle
+ VListItemTitle,
+ VListGroup
} from './v-list/';
import VOverlay from './v-overlay/';
import VProgressLinear from './v-progress/linear/';
@@ -40,6 +41,7 @@ Vue.component('v-list-item-content', VListItemContent);
Vue.component('v-list-item-icon', VListItemIcon);
Vue.component('v-list-item-subtitle', VListItemSubtitle);
Vue.component('v-list-item-title', VListItemTitle);
+Vue.component('v-list-group', VListGroup);
Vue.component('v-overlay', VOverlay);
Vue.component('v-progress-linear', VProgressLinear);
Vue.component('v-progress-circular', VProgressCircular);
@@ -51,3 +53,7 @@ Vue.component('v-table', VTable);
import DrawerDetail from '@/views/private-view/drawer-detail/';
Vue.component('drawer-detail', DrawerDetail);
+
+import TransitionExpand from './transition/expand';
+
+Vue.component('transition-expand', TransitionExpand);
diff --git a/src/components/transition/expand/index.ts b/src/components/transition/expand/index.ts
new file mode 100644
index 0000000000..fb7fa3137d
--- /dev/null
+++ b/src/components/transition/expand/index.ts
@@ -0,0 +1,4 @@
+import TransitionExpand from './transition-expand.vue';
+
+export { TransitionExpand };
+export default TransitionExpand;
diff --git a/src/components/transition/expand/readme.md b/src/components/transition/expand/readme.md
new file mode 100644
index 0000000000..df67addaea
--- /dev/null
+++ b/src/components/transition/expand/readme.md
@@ -0,0 +1,50 @@
+# `transition-expand`
+
+Use around a `v-if` or `v-show` component to have it expand in and out of view.
+
+## Usage
+
+```html
+
+
+
Click me!
+
+
+
+ More content
+
+
+
+
+
+
+```
+
+## Props
+| Prop | Description | Default |
+|-------------------------|----------------------------------------------------|---------|
+| `x-axis` | Expand on the horizontal instead vertical axis | `false` |
+| `expanded-parent-class` | Add a custom class to the element that is expanded | `''` |
+
+## Slots
+| Slot | Description | Data |
+|-----------|-------------|------|
+| _default_ | | |
+
+## Events
+n/a
+
+## CSS Variables
+n/a
diff --git a/src/components/transition/expand/transition-expand-methods.ts b/src/components/transition/expand/transition-expand-methods.ts
new file mode 100644
index 0000000000..40a63a1e1d
--- /dev/null
+++ b/src/components/transition/expand/transition-expand-methods.ts
@@ -0,0 +1,92 @@
+import capitalizeFirst from '@/utils/capitalize-first';
+
+interface HTMLExpandElement extends HTMLElement {
+ _parent?: (Node & ParentNode & HTMLElement) | null;
+ _initialStyle: {
+ transition: string;
+ visibility: string;
+ overflow: string;
+ height?: string | null;
+ width?: string | null;
+ };
+}
+
+export default function(expandedParentClass = '', xAxis = false) {
+ const sizeProperty = xAxis ? 'width' : ('height' as 'width' | 'height');
+ const offsetProperty = `offset${capitalizeFirst(sizeProperty)}` as
+ | 'offsetHeight'
+ | 'offsetWidth';
+
+ return {
+ beforeEnter(el: HTMLExpandElement) {
+ el._parent = el.parentNode as (Node & ParentNode & HTMLElement) | null;
+ el._initialStyle = {
+ transition: el.style.transition,
+ visibility: el.style.visibility,
+ overflow: el.style.overflow,
+ [sizeProperty]: el.style[sizeProperty]
+ };
+ },
+
+ enter(el: HTMLExpandElement) {
+ const initialStyle = el._initialStyle;
+ const offset = `${el[offsetProperty]}px`;
+
+ el.style.setProperty('transition', 'none', 'important');
+ el.style.visibility = 'hidden';
+ el.style.visibility = initialStyle.visibility;
+ el.style.overflow = 'hidden';
+ el.style[sizeProperty] = '0';
+
+ void el.offsetHeight; // force reflow
+
+ el.style.transition =
+ initialStyle.transition !== ''
+ ? initialStyle.transition
+ : `${sizeProperty} var(--medium) var(--transition)`;
+
+ if (expandedParentClass && el._parent) {
+ el._parent.classList.add(expandedParentClass);
+ }
+
+ requestAnimationFrame(() => {
+ el.style[sizeProperty] = offset;
+ });
+ },
+
+ afterEnter: resetStyles,
+ enterCancelled: resetStyles,
+
+ leave(el: HTMLExpandElement) {
+ el._initialStyle = {
+ transition: '',
+ visibility: '',
+ overflow: el.style.overflow,
+ [sizeProperty]: el.style[sizeProperty]
+ };
+
+ el.style.overflow = 'hidden';
+ el.style[sizeProperty] = `${el[offsetProperty]}px`;
+ void el.offsetHeight; // force reflow
+
+ requestAnimationFrame(() => (el.style[sizeProperty] = '0'));
+ },
+
+ afterLeave,
+ leaveCancelled: afterLeave
+ };
+
+ function afterLeave(el: HTMLExpandElement) {
+ if (expandedParentClass && el._parent) {
+ el._parent.classList.remove(expandedParentClass);
+ }
+ resetStyles(el);
+ }
+
+ function resetStyles(el: HTMLExpandElement) {
+ const size = el._initialStyle[sizeProperty];
+ el.style.overflow = el._initialStyle.overflow;
+ if (size != null) el.style[sizeProperty] = size;
+ delete el._initialStyle;
+ }
+}
diff --git a/src/components/transition/expand/transition-expand.story.ts b/src/components/transition/expand/transition-expand.story.ts
new file mode 100644
index 0000000000..0db0708acc
--- /dev/null
+++ b/src/components/transition/expand/transition-expand.story.ts
@@ -0,0 +1,40 @@
+import markdown from './readme.md';
+import { defineComponent, ref } from '@vue/composition-api';
+import TransitionExpand from './transition-expand.vue';
+import withPadding from '../../../../.storybook/decorators/with-padding';
+
+export default {
+ title: 'Transition / Expand',
+ parameters: {
+ notes: markdown
+ },
+ decorators: [withPadding]
+};
+
+export const basic = () =>
+ defineComponent({
+ components: { TransitionExpand },
+ props: {},
+ setup() {
+ const active = ref(false);
+
+ return { active, toggle };
+
+ function toggle() {
+ active.value = !active.value;
+ }
+ },
+ template: `
+
+
Click me!
+
+
+
+
+ Hello, world!
+
+
+
+
+ `
+ });
diff --git a/src/components/transition/expand/transition-expand.test.ts b/src/components/transition/expand/transition-expand.test.ts
new file mode 100644
index 0000000000..06eb6bd43e
--- /dev/null
+++ b/src/components/transition/expand/transition-expand.test.ts
@@ -0,0 +1,44 @@
+import { mount, createLocalVue } from '@vue/test-utils';
+import VueCompositionAPI, { defineComponent, ref } from '@vue/composition-api';
+import TransitionExpand from './transition-expand.vue';
+
+const localVue = createLocalVue();
+localVue.use(VueCompositionAPI);
+
+localVue.component('transition-expand', TransitionExpand);
+
+const ExpandTestUtil = defineComponent({
+ setup() {
+ const active = ref(false);
+ const toggle = () => (active.value = !active.value);
+ return { active, toggle };
+ },
+ template: `
+
+
+
+ `
+});
+
+describe('Expand Transition', () => {
+ it('Renders the provided markup in the default slot', async () => {
+ const component = mount(ExpandTestUtil, {
+ localVue,
+ scopedSlots: {
+ default: `
+
+ `
+ }
+ });
+
+ expect(component.find('.test').isVisible()).toBe(false);
+ component.find('button').trigger('click');
+ await component.vm.$nextTick();
+ expect(component.find('.test').isVisible()).toBe(true);
+ });
+});
diff --git a/src/components/transition/expand/transition-expand.vue b/src/components/transition/expand/transition-expand.vue
new file mode 100644
index 0000000000..f6a26fc286
--- /dev/null
+++ b/src/components/transition/expand/transition-expand.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
diff --git a/src/components/transition/index.ts b/src/components/transition/index.ts
new file mode 100644
index 0000000000..aaafc65f71
--- /dev/null
+++ b/src/components/transition/index.ts
@@ -0,0 +1,4 @@
+import TransitionExpand from './expand';
+
+export { TransitionExpand };
+export default { TransitionExpand };
diff --git a/src/components/transition/readme.md b/src/components/transition/readme.md
new file mode 100644
index 0000000000..3001627c24
--- /dev/null
+++ b/src/components/transition/readme.md
@@ -0,0 +1,7 @@
+# Transitions
+
+Preset extensions of the Vue `transition` element.
+
+## Table of Contents
+
+- [`Expand`](./expand)
diff --git a/src/components/v-form/v-form.test.ts b/src/components/v-form/v-form.test.ts
index b01ca728f6..a80aeaf647 100644
--- a/src/components/v-form/v-form.test.ts
+++ b/src/components/v-form/v-form.test.ts
@@ -8,7 +8,7 @@ localVue.use(VueCompositionAPI);
describe('Components / Form', () => {
it('Renders', () => {
- const component = shallowMount(VForm, { localVue });
+ const component = shallowMount(VForm, { localVue, propsData: { collection: 'test' } });
expect(component.isVueInstance()).toBe(true);
});
});
diff --git a/src/components/v-item-group/v-item-group.story.ts b/src/components/v-item-group/v-item-group.story.ts
index d48495a7be..cea45f8d1f 100644
--- a/src/components/v-item-group/v-item-group.story.ts
+++ b/src/components/v-item-group/v-item-group.story.ts
@@ -9,7 +9,7 @@ Vue.component('v-item-group', VItemGroup);
Vue.component('v-item', VItem);
export default {
- title: 'Components / Groups / Item Group',
+ title: 'Components / Item Group',
component: VItemGroup,
decorators: [withKnobs, withPadding],
parameters: {
diff --git a/src/components/v-list/index.ts b/src/components/v-list/index.ts
index e950783a13..e86c791294 100644
--- a/src/components/v-list/index.ts
+++ b/src/components/v-list/index.ts
@@ -4,6 +4,15 @@ import VListItemContent from './v-list-item-content.vue';
import VListItemTitle from './v-list-item-title.vue';
import VListItemSubtitle from './v-list-item-subtitle.vue';
import VListItemIcon from './v-list-item-icon.vue';
+import VListGroup from './v-list-group.vue';
-export { VList, VListItem, VListItemContent, VListItemTitle, VListItemSubtitle, VListItemIcon };
+export {
+ VList,
+ VListItem,
+ VListItemContent,
+ VListItemTitle,
+ VListItemSubtitle,
+ VListItemIcon,
+ VListGroup
+};
export default VList;
diff --git a/src/components/v-list/readme.md b/src/components/v-list/readme.md
index 4c2f753269..9cbb0ae565 100644
--- a/src/components/v-list/readme.md
+++ b/src/components/v-list/readme.md
@@ -10,129 +10,23 @@
```
-## Subcomponents
-
-### List Item
-
-A wrapper for list items that formats children nicely. Can be used on its own or inside a list component. Best used with subcomponents (see below).
-
-### List Item Content
-
-A wrapper for the main text content of a list item. It adds some padding and helps control overflow. The parent of `v-list-title` and `v-list-subtitle` components, it's also the main controller of the `dense` option on lists.
-
-### List Item Title
-
-Wrapper that adds typographic styling and margin for the title of the list item. Responsive to `dense` styling.
-
-### List Item Subtitle
-
-Wrapper that adds typographic styling and margin for the subtitle/description of the list item. Responsive to `dense` and `threeLine` props.
-
-```html
-
-
- {{ item.title }}
- {{ item.description }}
-
-
-```
-
-### List Item Icon
-
-Wrapper for icon, action, or avatar type elements in a list item. Can be used on the left or right of an item.
-
-```html
-
-
-
- {{ item.title }}
-
-
-```
-
-## Colors
-
-You can set the default, active, and hover colors and background colors with css variables. You can also set them on individual list items, which will override the list vars. Hover styles will only be set if the list item has a to link or an onClick handler.
-
-```html
-
-
-
- {{ item.text }}
-
-
-
-
-
-```
-
## Props
-
-### List (`v-list`)
-
| Prop | Description | Default |
|-------------|-------------------------------------------------------------------------------------------------------------|---------|
| `dense` | Removes some padding to make the list items closer together | `false` |
| `threeLine` | Limits list items to three lines of text (1 of title, 2 of subtitle). Only works in webkit enabled browsers | `false` |
| `nav` | Adds a small margin and border-radius for nav menu styling | `false` |
-
-### List Item (`v-list-item`)
-
-| Prop | Description | Default |
-|-------------|------------------------------------------------------------------------------------------------------------|---------|
-| `dense` | Removes some padding to make the individual list item shorter | `false` |
-| `threeLine` | Limits list item to three lines of text (1 of title, 2 of subtitle). Only works in webkit enabled browsers | `false` |
-| `to` | Render as vue router-link with to link | `null` |
-
-### List Item Content (`v-list-item-content`)
-
-### List Item Title (`v-list-item-title`)
-
-### List Item Subtitle (`v-list-item-subtitle`)
-
-n/a
-
-### List Item Icon (`v-list-item-icon`)
-
-| Prop | Description | Default |
-|----------|---------------------------------------------------------------------|---------|
-| `center` | Whether to center the element (good for action elements or avatars) | `false` |
-
-## Slots
-
-### List (`v-list`)
-
-### List Item (`v-list-item`)
-
-### List Item Content (`v-list-item-content`)
-
-### List Item Title (`v-list-item-title`)
-
-### List Item Subtitle (`v-list-item-subtitle`)
-
-### List Item Icon (`v-list-item-icon`)
-
-| Slot | Description |
-|-----------|---------------|
-| _default_ | Content, etc. |
+| `multiple` | Allows multiple child groups to be open at once | `true` |
## Events
-
n/a
+## Slots
+| Slot | Description | Data |
+|-----------|--------------|------|
+| _default_ | List content | |
+
## CSS Variables
-
-### List (`v-list`)
-
| Variable | Default |
|------------------------------------|----------------------------------|
| `--v-list-padding` | `8px 0` |
@@ -147,34 +41,223 @@ n/a
| `--v-list-background-color-hover` | `var(--background-color-hover)` |
| `--v-list-background-color-active` | `var(--background-color-active)` |
-### List Item (`v-list-item`)
+---
-| Variable | Default |
-|-----------------------------------------|-----------------------------------------------------------------------|
-| `--v-list-item-padding` | `0 16px` |
-| `--v-list-item-min-width` | `none` |
-| `--v-list-item-max-width` | `none` |
-| `--v-list-item-min-height` | `48px` |
-| `--v-list-item-max-height` | `auto` |
-| `--v-list-item-border-radius` | `0` |
-| `--v-list-item-margin-bottom` | `0` |
-| `--v-list-item-color` | `var(--v-list-color, var(--foreground-color))` |
-| `--v-list-item-color-hover` | `var(--v-list-color-hover, var(--foreground-color))` |
-| `--v-list-item-color-active` | `var(--v-list-color-active, var(--foreground-color))` |
-| `--v-list-item-background-color` | `var(--v-list-background-color, var(--background-color))` |
-| `--v-list-item-background-color-hover` | `var(---list-background-color-hover, var(--background-color-hover))` |
-| `--v-list-item-background-color-active` | `var(--vlist-background-color-active,var(--background-color-active))` |
+# List Item
-### List Item Content (`v-list-item-content`)
+A wrapper for list items that formats children nicely. Can be used on its own or inside a list component. Best used with subcomponents (see below).
+## Usage
+
+```html
+
+ Hello, world!
+
+```
+
+## Props
+| Prop | Description | Default |
+|---------|----------------------------------------------------------------------|---------|
+| `dense` | Removes some padding to make the individual list item shorter | `false` |
+| `lines` | Sets if the list item will support `1`, `2`, or `3` lines of content | `null` |
+| `to` | Render as vue router-link with to link | `null` |
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|-------------------|------|
+| _default_ | List item content | |
+
+## CSS Variables
+| Variable | Default |
+|---------------------------------------------|-------------------------------------------------------------------------|
+| `--v-list-item-one-line-min-height` | `48px` |
+| `--v-list-item-two-line-min-height` | `60px` |
+| `--v-list-item-three-line-min-height` | `76px` |
+| `--v-list-item-one-line-min-height-dense` | `40px` |
+| `--v-list-item-two-line-min-height-dense` | `48px` |
+| `--v-list-item-three-line-min-height-dense` | `64px` |
+| `--v-list-item-padding` | `0 16px 0 calc(16px + var(--v-list-item-indent, 0px))` |
+| `--v-list-item-min-width` | `none` |
+| `--v-list-item-max-width` | `none` |
+| `--v-list-item-min-height` | `var(--v-list-item-one-line-min-height)` |
+| `--v-list-item-max-height` | `auto` |
+| `--v-list-item-border-radius` | `0` |
+| `--v-list-item-margin-bottom` | `0` |
+| `--v-list-item-color` | `var(--v-list-color, var(--foreground-color))` |
+| `--v-list-item-color-hover` | `var(--v-list-color-hover, var(--foreground-color))` |
+| `--v-list-item-color-active` | `var(--v-list-color-active, var(--foreground-color))` |
+| `--v-list-item-background-color` | `var(--v-list-background-color, var(--background-color))` |
+| `--v-list-item-background-color-hover` | `var(--v-list-background-color-hover, var(--background-color-hover))` |
+| `--v-list-item-background-color-active` | `var(--v-list-background-color-active, var(--background-color-active))` |
+
+
+---
+
+# List Item Content
+
+A wrapper for the main text content of a list item. It adds some padding and helps control overflow. The parent of `v-list-title` and `v-list-subtitle` components, it's also the main controller of the `dense` option on lists.
+
+## Usage
+
+```html
+Hello, world!
+```
+
+## Props
+n/a
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|---------------------------|------|
+| _default_ | List item content content | |
+
+## CSS Variables
| Variable | Default |
|---------------------------------|----------|
| `--v-list-item-content-padding` | `12px 0` |
-### List Item Title (`v-list-item-title`)
+---
-### List Item Subtitle (`v-list-item-subtitle`)
+# List Item Title
-### List Item Icon (`v-list-item-icon`)
+Wrapper that adds typographic styling and margin for the subtitle/description of the list item. Responsive to `dense` and `threeLine` props.
+## Usage
+
+```html
+Hello, world
+```
+
+## Props
+n/a
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|-------------------------|------|
+| _default_ | List item title content | |
+
+## CSS Variables
+n/a
+
+---
+
+# List Item Subtitle
+
+Wrapper that adds typographic styling and margin for the subtitle/description of the list item. Responsive to `dense` and `threeLine` props.
+
+## Usage
+
+```html
+This is the subtitle
+```
+
+## Props
+n/a
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|----------------------------|------|
+| _default_ | List item subtitle content | |
+
+## CSS Variables
+n/a
+
+---
+
+# List Item Icon
+
+Wrapper for icon, action, or avatar type elements in a list item. Can be used on the left or right of an item.
+
+## Usage
+
+```html
+
+
+
+```
+
+## Props
+| Prop | Description | Default |
+|----------|---------------------------------------------------------------------|---------|
+| `center` | Whether to center the element (good for action elements or avatars) | `false` |
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|------------------------|------|
+| _default_ | List item icon content | |
+
+## CSS Variables
+n/a
+
+---
+
+# List Group
+
+Provides the ability to make a collapsable (sub)group of list items, within a list or independently. List groups can be nested to an arbitrary depth.
+
+```html
+
+
+
+
+
+
+
+ ... Click me to expand! ...
+
+
+
+ ...item content etc.
+
+
+
+
+ ... Click me to expand this subgroup! ...
+
+
+
+
+
+
+
+ ... Click me to expand next subgroup! ...
+
+
+
+
+
+
+
+
+```
+
+## Props
+| Prop | Description | Default |
+|------|-------------|---------|
+| `multiple` | Allow multiple subgroups to be open at the same time | `true` |
+
+## Events
+n/a
+
+## Slots
+| Slot | Description | Data |
+|-----------|---------------|------|
+| _default_ | Group content | |
+
+## CSS Variables
n/a
diff --git a/src/components/v-list/v-list-group.vue b/src/components/v-list/v-list-group.vue
index e69de29bb2..d432191710 100644
--- a/src/components/v-list/v-list-group.vue
+++ b/src/components/v-list/v-list-group.vue
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/v-list/v-list-item-icon.vue b/src/components/v-list/v-list-item-icon.vue
index d23ba91063..660b9971c2 100644
--- a/src/components/v-list/v-list-item-icon.vue
+++ b/src/components/v-list/v-list-item-icon.vue
@@ -31,32 +31,34 @@ export default defineComponent({
&:first-child {
margin-right: 12px;
}
-
&:last-child {
margin-left: 12px;
}
}
- .v-list,
- .v-list-item {
- &.three-line,
- &.two-line {
- align-self: flex-start;
- #{$this}.center {
- align-self: center;
- }
- }
- &.dense {
- #{$this} {
- margin-top: 8px;
- margin-bottom: 8px;
- &:not(:only-child) {
- &:first-child {
- margin-right: 16px;
+ @at-root {
+ .v-list,
+ .v-list-item {
+ &.three-line,
+ &.two-line {
+ #{$this} {
+ align-self: flex-start;
+ &.center {
+ align-self: center;
}
-
- &:last-child {
- margin-left: 8px;
+ }
+ }
+ &.dense {
+ #{$this} {
+ margin-top: 8px;
+ margin-bottom: 8px;
+ &:not(:only-child) {
+ &:first-child {
+ margin-right: 8px;
+ }
+ &:last-child {
+ margin-left: 8px;
+ }
}
}
}
diff --git a/src/components/v-list/v-list-item.vue b/src/components/v-list/v-list-item.vue
index 7a7286f66a..a66f160f02 100644
--- a/src/components/v-list/v-list-item.vue
+++ b/src/components/v-list/v-list-item.vue
@@ -54,7 +54,7 @@ export default defineComponent({
--v-list-item-one-line-min-height-dense: 40px;
--v-list-item-two-line-min-height-dense: 48px;
--v-list-item-three-line-min-height-dense: 64px;
- --v-list-item-padding: 0 16px;
+ --v-list-item-padding: 0 16px 0 calc(16px + var(--v-list-item-indent, 0px));
--v-list-item-min-width: none;
--v-list-item-max-width: none;
--v-list-item-min-height: var(--v-list-item-one-line-min-height);
@@ -66,11 +66,11 @@ export default defineComponent({
--v-list-item-color-active: var(--v-list-color-active, var(--foreground-color));
--v-list-item-background-color: var(--v-list-background-color, var(--background-color));
--v-list-item-background-color-hover: var(
- ---list-background-color-hover,
+ --v-list-background-color-hover,
var(--background-color-hover)
);
--v-list-item-background-color-active: var(
- --vlist-background-color-active,
+ --v-list-background-color-active,
var(--background-color-active)
);
@@ -136,11 +136,13 @@ export default defineComponent({
}
}
}
- .v-list.nav #{$this} {
- --v-list-item-padding: 0 8px;
- --v-list-item-border-radius: 4px;
- #{$this}:not(:last-child):not(:only-child) {
- --v-list-item-margin-bottom: 8px;
+ .v-list.nav {
+ & #{$this} {
+ --v-list-item-padding: 0 8px;
+ --v-list-item-border-radius: 4px;
+ &:not(:last-child):not(:only-child) {
+ --v-list-item-margin-bottom: 8px;
+ }
}
&.dense #{$this},
#{$this}.dense {
diff --git a/src/components/v-list/v-list.story.ts b/src/components/v-list/v-list.story.ts
index 1fdc3d110f..c9a756fa20 100644
--- a/src/components/v-list/v-list.story.ts
+++ b/src/components/v-list/v-list.story.ts
@@ -8,6 +8,7 @@ import VListItemContent from './v-list-item-content.vue';
import VListItemTitle from './v-list-item-title.vue';
import VListItemSubTitle from './v-list-item-subtitle.vue';
import VListItemIcon from './v-list-item-icon.vue';
+import VListGroup from './v-list-group.vue';
import VSheet from '../v-sheet';
import VCheckbox from '../v-checkbox';
import VueRouter from 'vue-router';
@@ -22,6 +23,7 @@ Vue.component('v-list-item-title', VListItemTitle);
Vue.component('v-list-item-subtitle', VListItemSubTitle);
Vue.component('v-list-item-icon', VListItemIcon);
Vue.component('v-checkbox', VCheckbox);
+Vue.component('v-list-group', VListGroup);
Vue.component('v-sheet', VSheet);
@@ -76,6 +78,123 @@ export const basic = () =>
`
});
+export const listGroups = () =>
+ defineComponent({
+ router: router,
+ props: {
+ multiple: {
+ default: boolean('Multiple', true)
+ },
+ multipleGroup: {
+ default: boolean('Multiple (in the nested groups)', true)
+ }
+ },
+ setup() {
+ return {
+ items: [0, 1, 2, 3]
+ };
+ },
+ template: `
+
+
+
+
+
+
+ Home
+
+
+
+
+
+
+ Collections
+
+
+
+
+ Users
+
+
+
+
+
+
+
+ Files
+
+
+
+
+
+
+
+ Download
+
+
+
+
+ Section 1
+
+
+
+ Section 2
+
+
+
+ Section 3
+
+
+
+
+
+
+
+
+ Upload
+
+
+
+
+ Section 1
+
+
+
+ Section 2
+
+
+
+ Section 3
+
+
+
+
+
+
+
+ Sub-sub-sub section
+
+
+
+
+ Section 1
+
+
+
+ Section 2
+
+
+
+ Section 3
+
+
+
+
+
+
+ `
+ });
+
export const withSubtitle = () =>
defineComponent({
router: router,
diff --git a/src/components/v-list/v-list.test.ts b/src/components/v-list/v-list.test.ts
index 4753b2e7d4..d7ba9014b4 100644
--- a/src/components/v-list/v-list.test.ts
+++ b/src/components/v-list/v-list.test.ts
@@ -5,6 +5,9 @@ import router from '@/router';
import VList from './v-list.vue';
import VListItem from './v-list-item.vue';
import VListItemIcon from './v-list-item-icon.vue';
+import VListGroup from './v-list-group.vue';
+import VIcon from '@/components/v-icon';
+import TransitionExpand from '@/components/transition/expand';
const localVue = createLocalVue();
localVue.use(VueCompositionAPI);
@@ -12,6 +15,9 @@ localVue.use(VueRouter);
localVue.component('v-list-item', VListItem);
localVue.component('v-list', VList);
localVue.component('v-list-item-icon', VListItemIcon);
+localVue.component('v-list-group', VListGroup);
+localVue.component('v-icon', VIcon);
+localVue.component('transition-expand', TransitionExpand);
describe('List', () => {
it('Renders the provided markup in the default slot', () => {
@@ -191,4 +197,27 @@ describe('List', () => {
component.find('.v-list-item').trigger('click');
expect(onClick).toHaveBeenCalled();
});
+
+ it('Opens a list group when activator item is clicked', async () => {
+ const component = mount(VList, {
+ localVue,
+ slots: {
+ default: `
+
+
+ Click me!
+
+
+
+
+
+
+ `
+ }
+ });
+ expect(component.find('.test').isVisible()).toBe(false);
+ component.find('.activator').trigger('click');
+ await component.vm.$nextTick();
+ expect(component.find('.test').isVisible()).toBe(true);
+ });
});
diff --git a/src/components/v-list/v-list.vue b/src/components/v-list/v-list.vue
index 606dab3e5c..3ab45ee763 100644
--- a/src/components/v-list/v-list.vue
+++ b/src/components/v-list/v-list.vue
@@ -14,7 +14,8 @@