Skip to content

Commit

Permalink
feat(comp:breadcrumb): add breadcrumb component (#71) (#633)
Browse files Browse the repository at this point in the history
fix #71
  • Loading branch information
imguolao committed Dec 21, 2021
1 parent 4e446fc commit 18ef292
Show file tree
Hide file tree
Showing 24 changed files with 432 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Breadcrumb render work 1`] = `
"<nav class=\\"ix-breadcrumb\\" aria-label=\\"Breadcrumb\\">
<ol>
<!---->
</ol>
</nav>"
`;
73 changes: 73 additions & 0 deletions packages/components/breadcrumb/__tests__/breadcrumb.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { MountingOptions, mount } from '@vue/test-utils'
import { h } from 'vue'

import { renderWork } from '@tests'

import Breadcrumb from '../src/Breadcrumb'
import BreadcrumbItem from '../src/BreadcrumbItem'
import { BreadcrumbProps } from '../src/types'

const defaultSlots = [
h(BreadcrumbItem, null, { default: () => 'item1' }),
h(BreadcrumbItem, null, { default: () => 'item2' }),
h(BreadcrumbItem, null, { default: () => 'item3' }),
]

describe('Breadcrumb', () => {
const BreadcrumbMount = (options?: MountingOptions<Partial<BreadcrumbProps>>) => {
const { slots, ...rest } = options || {}
const mergedOptions = {
slots: { default: () => defaultSlots, ...slots },
...rest,
} as MountingOptions<BreadcrumbProps>
return mount(Breadcrumb, mergedOptions)
}

renderWork<BreadcrumbProps>(Breadcrumb)

test('BreadcrumbItem not placed inside Breadcrumb', () => {
const mockErrorLogger = jest.spyOn(console, 'error').mockImplementation()
const wrapper = mount(BreadcrumbItem)

expect(wrapper.isVisible()).toBe(false)
expect(mockErrorLogger).toBeCalled()
})

test("should work with Breadcrumb's `separator` prop", async () => {
const wrapper = BreadcrumbMount({
props: {
separator: '>',
},
})
const separatorDomList = wrapper.findAll('.ix-breadcrumb-item-separator')
expect(separatorDomList.every(i => i.text() === '>')).toBe(true)
})

test("should work with BreadcrumbItem's `separator` prop", async () => {
const wrapper = BreadcrumbMount({
slots: {
default: () => [
h(BreadcrumbItem, { separator: '>' }, { default: () => 'item1' }),
h(BreadcrumbItem, null, { default: () => 'item2' }),
],
},
})
const separatorDomList = wrapper.findAll('.ix-breadcrumb-item-separator')
expect(separatorDomList[0].text()).toBe('>')
expect(separatorDomList[1].text()).toBe('/')
})

test("should work with BreadcrumbItem's `separator` slot", async () => {
const wrapper = BreadcrumbMount({
slots: {
default: () => [
h(BreadcrumbItem, null, { default: () => 'item2' }),
h(BreadcrumbItem, null, { default: () => 'item2', separator: () => '>' }),
],
},
})
const separatorDomList = wrapper.findAll('.ix-breadcrumb-item-separator')
expect(separatorDomList[0].text()).toBe('/')
expect(separatorDomList[1].text()).toBe('>')
})
})
14 changes: 14 additions & 0 deletions packages/components/breadcrumb/demo/Basic.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 基本使用
en: Basic usage
order: 0
---

## zh

最简单的用法。

## en

The simplest usage.
10 changes: 10 additions & 0 deletions packages/components/breadcrumb/demo/Basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<template>
<IxBreadcrumb>
<IxBreadcrumbItem><IxIcon name="transmit" /> 巴黎</IxBreadcrumbItem>
<IxBreadcrumbItem><IxIcon name="cloud" /> 北京</IxBreadcrumbItem>
<IxBreadcrumbItem>
<a href="#"><IxIcon name="link" /> 热情的岛屿</a>
</IxBreadcrumbItem>
<IxBreadcrumbItem><IxIcon name="tag" /> 土耳其</IxBreadcrumbItem>
</IxBreadcrumb>
</template>
12 changes: 12 additions & 0 deletions packages/components/breadcrumb/demo/Custom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title:
zh: 自定义分隔符
en: Customized Separator
order: 1
---

## zh

使用 `separator` 可以自定义分隔符。

## en
11 changes: 11 additions & 0 deletions packages/components/breadcrumb/demo/Custom.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<template>
<IxBreadcrumb separator=">">
<IxBreadcrumbItem>高架桥</IxBreadcrumbItem>
<IxBreadcrumbItem separator="~">路口</IxBreadcrumbItem>
<IxBreadcrumbItem>
<template #separator>→</template>
<a href="#">旅途</a>
</IxBreadcrumbItem>
<IxBreadcrumbItem>路灯</IxBreadcrumbItem>
</IxBreadcrumb>
</template>
12 changes: 12 additions & 0 deletions packages/components/breadcrumb/demo/Dropdown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title:
zh: 下拉菜单
en: Dropdown
order: 2
---

## zh

[下拉菜单](/components/dropdown/zh) 一起使用。

## en
18 changes: 18 additions & 0 deletions packages/components/breadcrumb/demo/Dropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<IxBreadcrumb>
<IxBreadcrumbItem>Somewhere</IxBreadcrumbItem>
<IxBreadcrumbItem>
<IxDropdown>
<a class="ix-dropdown-trigger">over the rainbow <IxIcon name="down"></IxIcon></a>
<template #overlay>
<IxMenu>
<IxMenuItem key="one">skies are blue</IxMenuItem>
<IxMenuItem key="two">wish upon a star</IxMenuItem>
<IxMenuDivider />
<IxMenuItem key="three" disabled>troubles melt like lemon drops</IxMenuItem>
</IxMenu>
</template>
</IxDropdown>
</IxBreadcrumbItem>
</IxBreadcrumb>
</template>
31 changes: 31 additions & 0 deletions packages/components/breadcrumb/docs/Index.en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
category: components
type: Navigation
title: Breadcrumb
subtitle:
order: 0
---



## API

### IxBreadcrumb

#### BreadcrumbProps

| Name | Description | Type | Default | Global Config | Remark |
| --- | --- | --- | --- | --- | --- |
| - | - | - | - || - |

#### BreadcrumbSlots

| Name | Description | Parameter Type | Remark |
| --- | --- | --- | --- |
| - | - | - | - |

#### BreadcrumbMethods

| Name | Description | Parameter Type | Remark |
| --- | --- | --- | --- |
| - | - | - | - |
23 changes: 23 additions & 0 deletions packages/components/breadcrumb/docs/Index.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
category: components
type: 导航
title: Breadcrumb
subtitle: 面包屑
order: 0
---

## API

### IxBreadcrumb

#### BreadcrumbProps

| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `separator` | 分隔符 | `string` | `/` | - | - |

#### BreadcrumbItemProps

| 名称 | 说明 | 类型 | 默认值 | 全局配置 | 备注 |
| --- | --- | --- | --- | --- | --- |
| `separator` | 分隔符 | `string \| #separator` | - | - | - |
25 changes: 25 additions & 0 deletions packages/components/breadcrumb/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { BreadcrumbComponent, BreadcrumbItemComponent } from './src/types'

import Breadcrumb from './src/Breadcrumb'
import BreadcrumbItem from './src/BreadcrumbItem'

const IxBreadcrumb = Breadcrumb as unknown as BreadcrumbComponent
const IxBreadcrumbItem = BreadcrumbItem as unknown as BreadcrumbItemComponent

export { IxBreadcrumb, IxBreadcrumbItem }

export type {
BreadcrumbInstance,
BreadcrumbComponent,
BreadcrumbPublicProps as BreadcrumbProps,
BreadcrumbItemInstance,
BreadcrumbItemComponent,
BreadcrumbItemPublicProps as BreadcrumbItemProps,
} from './src/types'
33 changes: 33 additions & 0 deletions packages/components/breadcrumb/src/Breadcrumb.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import { computed, defineComponent, provide, toRef } from 'vue'

import { useGlobalConfig } from '@idux/components/config'

import { breadcrumbToken } from './token'
import { breadcrumbProps } from './types'

export default defineComponent({
name: 'IxBreadcrumb',
props: breadcrumbProps,
setup(props, { slots }) {
const common = useGlobalConfig('common')
const mergedPrefixCls = computed(() => `${common.prefixCls}-breadcrumb`)

provide(breadcrumbToken, {
mergedPrefixCls,
separatorRef: toRef(props, 'separator'),
})

return () => (
<nav class={mergedPrefixCls.value} aria-label="Breadcrumb">
<ol>{slots.default?.()}</ol>
</nav>
)
},
})
37 changes: 37 additions & 0 deletions packages/components/breadcrumb/src/BreadcrumbItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import { defineComponent, inject } from 'vue'

import { Logger } from '@idux/cdk/utils'

import { breadcrumbToken } from './token'
import { breadcrumbItemProps } from './types'

export default defineComponent({
name: 'IxBreadcrumbItem',
props: breadcrumbItemProps,
setup(props, { slots }) {
const breadcrumbInjection = inject(breadcrumbToken, null)
if (!breadcrumbInjection) {
if (__DEV__) {
Logger.error('components/breadcrumb', '`breadcrumb-item` must be placed inside `breadcrumb`.')
}
return () => null
}

const { mergedPrefixCls, separatorRef } = breadcrumbInjection
return () => (
<li class={`${mergedPrefixCls.value}-item`}>
<span class={`${mergedPrefixCls.value}-item-link`}>{slots.default?.()}</span>
<span class={`${mergedPrefixCls.value}-item-separator`} aria-hidden="true">
{slots.separator ? slots.separator() : props.separator ?? separatorRef.value}
</span>
</li>
)
},
})
16 changes: 16 additions & 0 deletions packages/components/breadcrumb/src/token.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { BreadcrumbProps } from './types'
import type { ComputedRef, InjectionKey, Ref } from 'vue'

export interface BreadcrumbContext {
mergedPrefixCls: ComputedRef<string>
separatorRef: Ref<BreadcrumbProps['separator']>
}

export const breadcrumbToken: InjectionKey<BreadcrumbContext> = Symbol('breadcrumbToken')
33 changes: 33 additions & 0 deletions packages/components/breadcrumb/src/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* @license
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://github.com/IDuxFE/idux/blob/main/LICENSE
*/

import type { IxInnerPropTypes, IxPublicPropTypes } from '@idux/cdk/utils'
import type { DefineComponent, HTMLAttributes } from 'vue'

import { IxPropTypes } from '@idux/cdk/utils'

export const breadcrumbProps = {
separator: IxPropTypes.string.def('/'),
}

export type BreadcrumbProps = IxInnerPropTypes<typeof breadcrumbProps>
export type BreadcrumbPublicProps = IxPublicPropTypes<typeof breadcrumbProps>
export type BreadcrumbComponent = DefineComponent<
Omit<HTMLAttributes, keyof BreadcrumbPublicProps> & BreadcrumbPublicProps
>
export type BreadcrumbInstance = InstanceType<DefineComponent<BreadcrumbProps>>

export const breadcrumbItemProps = {
separator: IxPropTypes.string,
}

export type BreadcrumbItemProps = IxInnerPropTypes<typeof breadcrumbItemProps>
export type BreadcrumbItemPublicProps = IxPublicPropTypes<typeof breadcrumbItemProps>
export type BreadcrumbItemComponent = DefineComponent<
Omit<HTMLAttributes, keyof BreadcrumbItemPublicProps> & BreadcrumbItemPublicProps
>
export type BreadcrumbItemInstance = InstanceType<DefineComponent<BreadcrumbItemProps>>

0 comments on commit 18ef292

Please sign in to comment.