Skip to content

Commit

Permalink
feat(comp: popover): add component popover
Browse files Browse the repository at this point in the history
  • Loading branch information
LaamGinghong committed Feb 15, 2021
1 parent d8bb853 commit bdfd45f
Show file tree
Hide file tree
Showing 23 changed files with 592 additions and 1 deletion.
2 changes: 1 addition & 1 deletion packages/cdk/utils/vNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function getChildren(node: VNode, depth: number): VNode | undefined {
* @param maxDepth depth to be searched, default is 3
*/
export function getFirstValidNode(nodes: VNodeChild, maxDepth = 3): VNode | undefined {
if (isNil(nodes)) {
if (isNil(nodes) || (Array.isArray(nodes) && !nodes.length)) {
return
}
if (Array.isArray(nodes) && nodes.length > 0) {
Expand Down
1 change: 1 addition & 0 deletions packages/components/components.less
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
@import './input/style/index.less';
@import './back-top/style/index.less';
@import './title/style/index.less';
@import './tooltip/style/index.less';
11 changes: 11 additions & 0 deletions packages/components/core/config/defaultConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
InputConfig,
TextareaConfig,
BackTopConfig,
TooltipConfig,
} from './types'

import { shallowReactive } from 'vue'
Expand Down Expand Up @@ -73,6 +74,15 @@ const backTop = shallowReactive<BackTopConfig>({
visibilityHeight: 400,
})

const tooltip = shallowReactive<TooltipConfig>({
placement: 'top',
trigger: 'hover',
showDelay: 100,
hideDelay: 500,
destroyOnHide: false,
autoAdjust: true,
})

export const defaultConfig: GlobalConfig = {
button,
icon,
Expand All @@ -86,4 +96,5 @@ export const defaultConfig: GlobalConfig = {
input,
textarea,
backTop,
tooltip,
}
13 changes: 13 additions & 0 deletions packages/components/core/config/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import type { Placement } from '@popperjs/core'
import type { OverlayTrigger } from '@idux/cdk/overlay'

export type GlobalConfigKey = keyof GlobalConfig

export interface GlobalConfig {
Expand All @@ -13,6 +16,7 @@ export interface GlobalConfig {
input: InputConfig
textarea: TextareaConfig
backTop: BackTopConfig
tooltip: TooltipConfig
}

export type ButtonMode = 'primary' | 'default' | 'dashed' | 'text' | 'link'
Expand Down Expand Up @@ -96,3 +100,12 @@ export interface BackTopConfig {
duration: number
visibilityHeight: number
}

export interface TooltipConfig {
placement: Placement
trigger: OverlayTrigger
showDelay: number
hideDelay: number
destroyOnHide: boolean
autoAdjust: boolean
}
3 changes: 3 additions & 0 deletions packages/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { IxCheckbox, IxCheckboxGroup } from './checkbox'
import { IxInput, IxTextarea } from './input'
import { IxBackTop } from './back-top'
import { IxTitle } from './title'
import { IxTooltip } from './tooltip'

const components = [
IxButton,
Expand All @@ -33,6 +34,7 @@ const components = [
IxTextarea,
IxBackTop,
IxTitle,
IxTooltip,
]

const directives: Record<string, Directive> = {
Expand Down Expand Up @@ -73,3 +75,4 @@ export { IxCheckbox, IxCheckboxGroup }
export { IxInput, IxTextarea }
export { IxBackTop }
export { IxTitle }
export { IxTooltip }
13 changes: 13 additions & 0 deletions packages/components/style/default.less
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,16 @@
@title-prefix-margin: @margin-md;
@title-content-margin: @margin-md;
@title-extra-margin: @margin-sm;

/* tooltip -------------------------- */
@tooltip-max-width: 250px;
@tooltip-font-size: 14px;
@tooltip-color: @black-l20;
@tooltip-inner-min-width: 30px;
@tooltip-inner-min-height: 32px;
@tooltip-inner-padding: @spacing-gutter - 2 @padding-sm;
@tooltip-inner-color: @white;
@tooltip-inner-background: rgba(0,0,0, 0.75);
@tooltip-inner-border-radius: @border-radius-sm;
@tooltip-inner-box-shadow: 0 3px 6px -4px rgb(0 0 0 / 12%), 0 6px 16px 0 rgb(0 0 0 / 8%), 0 9px 28px 8px rgb(0 0 0 / 5%);
@tooltip-arrow-size: 3px;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`tooltip.tsx render work 1`] = `"<!---->"`;
65 changes: 65 additions & 0 deletions packages/components/tooltip/__tests__/tooltip.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { MountingOptions } from '@vue/test-utils'
import type { TooltipProps } from '@idux/components/tooltip'

import { renderWork, wait } from '@tests'
import IxTooltip from '../src/tooltip'
import { mount, VueWrapper } from '@vue/test-utils'

const TestComponent = {
components: { IxTooltip },
props: ['title', 'placement', 'visible', 'trigger', 'destroyOnHide'],
template: `
<ix-tooltip :title='title' :placement='placement' :visible='visible' :trigger='trigger' :destroy-on-hide='destroyOnHide'>
<template v-if='!!$slots.title' #title><slot name='title'/></template>
<span>Tooltip will show when it's hovered.</span>
</ix-tooltip>
`,
}

describe('tooltip.tsx', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let tooltipMount: (options?: MountingOptions<TooltipProps>) => VueWrapper<any>

beforeEach(() => {
tooltipMount = options => mount(TestComponent, options)
})

afterEach(() => {
document.body.querySelectorAll('.ix-tooltip').forEach(value => {
value.remove()
})
})

renderWork(IxTooltip)

test('title work', async () => {
const textWrapper = tooltipMount({ props: { title: 'prompt text' } })
expect(document.body.querySelector('.ix-tooltip')!.getAttribute('style')).toEqual('display: none;')
await textWrapper.get('span').trigger('mouseenter')
await wait(100)
expect(document.body.querySelector('.ix-tooltip')!.getAttribute('style')).toContain('display: block;')

const title = '<div id="custom-title">prompt text</div>'
const slotWrapper = tooltipMount({ slots: { title } })
expect(document.body.querySelectorAll('.ix-tooltip')[1]!.getAttribute('style')).toEqual('display: none;')
await slotWrapper.get('span').trigger('mouseenter')
await wait(100)
expect(document.body.querySelectorAll('.ix-tooltip')[1]!.getAttribute('style')).toContain('display: block;')
})

test('destroyOnHide work', async () => {
const wrapper = tooltipMount({ props: { destroyOnHide: true, title: 'prompt text' } })
expect(document.body.querySelector('.ix-tooltip')!.querySelector('.ix-tooltip-inner')).toBeNull()
await wrapper.get('span').trigger('mouseenter')
await wait(100)
expect(document.body.querySelector('.ix-tooltip')!.querySelector('.ix-tooltip-inner')).toBeDefined()
await wrapper.get('span').trigger('mouseleave')
await wait(500)
expect(document.body.querySelector('.ix-tooltip')!.querySelector('.ix-tooltip-inner')).toBeNull()
})

test('without title', () => {
tooltipMount()
expect(document.body.querySelector('.ix-tooltip')).toBeNull()
})
})
5 changes: 5 additions & 0 deletions packages/components/tooltip/demo/Basic.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<ix-tooltip title="prompt text">
<span>Tooltip will show when it's hovered.</span>
</ix-tooltip>
</template>
5 changes: 5 additions & 0 deletions packages/components/tooltip/demo/Destroy.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<template>
<ix-tooltip title="prompt text" destroyOnHide>
<span>Tooltip will show when it's hovered.</span>
</ix-tooltip>
</template>
117 changes: 117 additions & 0 deletions packages/components/tooltip/demo/Placement.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<template>
<table>
<tbody>
<tr>
<td></td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="top-start">
<ix-button>TL</ix-button>
</ix-tooltip>
</td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="top">
<ix-button>Top</ix-button>
</ix-tooltip>
</td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="top-end">
<ix-button>TR</ix-button>
</ix-tooltip>
</td>
<td></td>
</tr>
<tr>
<td>
<ix-tooltip placement="left-start">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>LT</ix-button>
</ix-tooltip>
</td>
<td></td>
<td></td>
<td></td>
<td>
<ix-tooltip placement="right-start">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>RT</ix-button>
</ix-tooltip>
</td>
</tr>
<tr>
<td>
<ix-tooltip placement="left">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>Left</ix-button>
</ix-tooltip>
</td>
<td></td>
<td></td>
<td></td>
<td>
<ix-tooltip placement="right">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>Right</ix-button>
</ix-tooltip>
</td>
</tr>
<tr>
<td>
<ix-tooltip placement="left-end">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>LB</ix-button>
</ix-tooltip>
</td>
<td></td>
<td></td>
<td></td>
<td>
<ix-tooltip placement="right-end">
<template #title>
<p>This is a very long prompt text.</p>
</template>
<ix-button>RB</ix-button>
</ix-tooltip>
</td>
</tr>
<tr>
<td></td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="bottom-start">
<ix-button>BL</ix-button>
</ix-tooltip>
</td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="bottom">
<ix-button>Bottom</ix-button>
</ix-tooltip>
</td>
<td>
<ix-tooltip title="This is a very long prompt text." placement="bottom-end">
<ix-button>BR</ix-button>
</ix-tooltip>
</td>
<td></td>
</tr>
</tbody>
</table>
</template>

<style scoped lang="less">
.ix-button {
width: 80px;
}
p {
max-width: 50px;
}
</style>
17 changes: 17 additions & 0 deletions packages/components/tooltip/demo/Trigger.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<template>
<ix-tooltip title="prompt text">
<ix-button>Hover</ix-button>
</ix-tooltip>
<ix-tooltip trigger="focus" title="prompt text">
<ix-button>Focus</ix-button>
</ix-tooltip>
<ix-tooltip trigger="click" title="prompt text">
<ix-button>Click</ix-button>
</ix-tooltip>
</template>

<style scoped lang="less">
.ix-button {
margin-right: 4px;
}
</style>
14 changes: 14 additions & 0 deletions packages/components/tooltip/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 use.
14 changes: 14 additions & 0 deletions packages/components/tooltip/demo/destroy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 隐藏时销毁
en: Destroy on hide
order: 3
---

## zh

浮层隐藏时销毁。

## en

Overlay is destroyed on hide.
14 changes: 14 additions & 0 deletions packages/components/tooltip/demo/placement.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 位置
en: Placement
order: 2
---

## zh

位置有 12 个固定方向和 3 个自动方向。

## en

There are 12 fixed placement and 3 auto placement.
14 changes: 14 additions & 0 deletions packages/components/tooltip/demo/trigger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
---
title:
zh: 三种触发方式
en: Three ways to trigger
order: 1
---

## zh

鼠标移入、聚焦、点击。

## en

Mouse in, focus, click.
Loading

0 comments on commit bdfd45f

Please sign in to comment.