Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kmenu): update kmenu for vue 3 #573

Merged
merged 1 commit into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions TEMP-MIGRATION-CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,7 @@ export default defineConfig({

- `v-model` is now mapped to `modelValue` prop instead of `selected` prop.
- Added type interface for `options` prop.

### KMenu & KMenuItem

- Added type interface for `items` prop.
1 change: 1 addition & 0 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export default defineUserConfig<DefaultThemeOptions, ViteBundlerOptions>({
'/components/input',
'/components/input-switch',
'/components/label',
'/components/menu',
'/components/modal',
'/components/pagination',
'/components/popover',
Expand Down
228 changes: 228 additions & 0 deletions docs/components/menu.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
# Menu

**KMenu** - Menu component

<KMenu :items="getMenuItems(5)" />

```vue
<KMenu :items="items" />
```

## Props

### items

An array of items to populate the menu with. The value passed for the `items` prop should adhere to this type interface:

```ts
export interface MenuItem {
title: string
description?: string
}

export interface KMenuItemType extends MenuItem {
expandable: boolean
type: 'string' | 'number' | 'divider'
}
```

Properties:

- `title` - menu item label
- `description` - text displayed when `expandable` item is expanded
- `expandable` - boolean of whether or not this item is expandable
- `type` - supported values: `string`, `number`, `divider`

> Note: `type='divider'` will insert an empty item that is just an `<hr>`.

<KMenu :items="getMenuItems(6)" />

```vue
<template>
<KMenu :items="getMenuItems(6)" />
</template>

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
setup () {
const getMenuItems = (count: number): [] => {
let menuItems = []
for (let i = 0; i < count; i++) {
menuItems.push({
title: 'Item ' + i,
type: 'string',
expandable: false,
description: 'The item description for number ' + i
})
}
return menuItems
}

return {
getMenuItems,
}
}
})
</script>
```

### width

You can pass a `width` string for **KMenu**. Either the string `auto` or a string width, like `120`.

By default the `width` is set to `284px`.

<KMenu :items="getMenuItems(3)" />

```vue
<KMenu :items="getMenuItems(3)" width="735" />
```

## KMenuItem

**KMenu** generates a **KMenuItem** for each item in the `items` property.

### Properties

- `item` - the menu item content is built from this.
- Properties:
- `title` - menu item label
- `description` - text displayed when `expandable` item is expanded
- Interface:
```ts
export interface MenuItem {
title: string
description?: string
}
```
- `type` - supported values: `string`, `number`, `divider`
- `expandable` - boolean of whether or not this item is expandable
- `lastMenuItem` - boolean of whether or not this is the last item in the menu (for styling)

```vue
<KMenuItem :item="{ title: 'some title', description: 'some description' }" :expandable="true" type="string" />
```

### Item Slots

- `itemTitle` - the title content for the menu item
- `itemBody` - the body content for the menu item

```vue
<KMenuItem>
<template v-slot:itemTitle>
Custom Title!
</template>
<template v-slot:itemBody>
Vivamus blandit metus eu nisi venenatis, vel convallis neque mollis. In enim lectus.
</template>
</KMenuItem>
```

## Slots

- `body` - The body of the menu, we expect this to be an array of `KMenuItem` components. This should be used instead of the `items` property.
- `actionButton` - the button at the bottom of the menu

<KMenu>
<template v-slot:body>
<KMenuItem v-for="item in getMenuItems(3)" :key="item.title" :item="item" />
<KMenuItem>
<template v-slot:itemTitle>
Look mah!
</template>
<template v-slot:itemBody>
<div>Cowabunga dude!</div>
</template>
</KMenuItem>
<KMenuItem type="divider" />
<KMenuItem :expandable="true" :item="customItem" type="string" />
<KMenuItem :expandable="true" last-menu-item >
<template v-slot:itemTitle>
<span>Updated</span>
</template>
<template v-slot:itemBody>
<div>Vivamus blandit metus eu nisi venenatis, vel convallis neque mollis. In enim lectus, dignissim nec iaculis id, sodales quis nulla. Mauris pellentesque bibendum dui sed dictum.</div>
</template>
</KMenuItem>
</template>
<template v-slot:actionButton>
<KButton>Clear all the filters</KButton>
</template>
</KMenu>

```vue
<KMenu>
<template v-slot:body>
<KMenuItem v-for="item in getMenuItems(3)" :item="item" />
<KMenuItem>
<template v-slot:itemTitle>
Look mah!
</template>
<template v-slot:itemBody>
<div>Cowabunga dude!</div>
</template>
</KMenuItem>

<KMenuItem type="divider" />

<KMenuItem :expandable="true" :item="customItem" type="string" />
<KMenuItem :expandable="true" last-menu-item>
<template v-slot:itemTitle>
<span>Updated</span>
</template>
<template v-slot:itemBody>
<div>Vivamus blandit metus eu nisi venenatis, vel convallis neque mollis. In enim lectus, dignissim nec iaculis id, sodales quis nulla. Mauris pellentesque bibendum dui sed dictum.</div>
</template>
</KMenuItem>
</template>
<template v-slot:actionButton>
<KButton>Clear all the filters</KButton>
</template>
</KMenu>
```

<script lang="ts">
import { defineComponent } from 'vue'

export default defineComponent({
setup () {
const getMenuItems = (count: number) => {
let menuItems = []
for (let i = 0; i < count; i++) {
menuItems.push({
title: 'Item ' + i,
type: 'string',
expandable: false,
description: 'The item description for number ' + i
})
}
return menuItems
}

const customItem = {
title: "Item #",
description: "Cras aliquet auctor ex ut hendrerit. Donec sagittis est nec aliquet semper. Quisque feugiat metus orci, at ullamcorper odio molestie non. Nam dignissim sed ligula ut commodo."
}

return {
getMenuItems,
customItem,
}
}
})
</script>

<style lang="scss">
.KMenu-wrapper {
--KMenu-wrapperBorderColor: lime;
}

div.menu-content div {
white-space: normal;
margin-right: 22px;
text-align: justify;
}
</style>
62 changes: 62 additions & 0 deletions src/components/KMenu/KMenu.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Import types for custom commands
/// <reference types="../../cypress/support" />

import { mount } from '@cypress/vue'
import KMenu from '@/components/KMenu/KMenu.vue'
import type { KMenuItemType } from '@/components/KMenu/KMenu.vue'

/**
* ALL TESTS MUST USE testMode: true
* We generate unique IDs for reference by aria properties. Test mode strips these out
* allowing for successful snapshot verification.
* props: {
* testMode: true
* }
*/

const getItems = (count: number): KMenuItemType[] => {
const myItems = []

for (let i = 0; i < count; i++) {
myItems.push({
title: 'Item ' + i,
type: Math.random() < 0.5 ? 'string' : 'number',
expandable: Math.random() < 0.5,
description: "The item's description for number " + i,
})
}

return myItems
}

const customItem = {
title: 'Item #',
description: 'Cras aliquet auctor ex ut hendrerit. Donec sagittis est nec aliquet semper. Quisque feugiat metus orci, at ullamcorper odio molestie non. Nam dignissim sed ligula ut commodo.',
expandable: true,
}

describe('KMenu', () => {
it('renders proper menu when using props', () => {
mount(KMenu, {
props: {
items: getItems(5),
testMode: true,
},
})

cy.get('.k-menu').should('be.visible')
cy.get('.k-menu-item').should('have.length', 5)
})

it('shows chevron down icon', () => {
mount(KMenu, {
props: {
items: [customItem],
testMode: true,
},
})

cy.get('.k-menu').should('be.visible')
cy.get('.k-menu-item .k-button .span-icon-container').should('be.visible')
})
})
Loading