mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
feat: DropDownButton支持分组,菜单CSS类名,添加下拉菜单max-width (#3302)
This commit is contained in:
parent
1aa45a631f
commit
548f3cccfd
@ -18,10 +18,10 @@ exports[`Renderer:dropdown-button 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<ul
|
||||
class="cxd-DropDown-menu"
|
||||
class="cxd-DropDown-menu-root cxd-DropDown-menu"
|
||||
>
|
||||
<li
|
||||
class=""
|
||||
class="cxd-DropDown-button"
|
||||
>
|
||||
<a
|
||||
class=""
|
||||
@ -32,7 +32,7 @@ exports[`Renderer:dropdown-button 1`] = `
|
||||
</a>
|
||||
</li>
|
||||
<li
|
||||
class=""
|
||||
class="cxd-DropDown-button"
|
||||
>
|
||||
<a
|
||||
class=""
|
||||
|
124
__tests__/renderers/__snapshots__/Timeline.test.tsx.snap
Normal file
124
__tests__/renderers/__snapshots__/Timeline.test.tsx.snap
Normal file
@ -0,0 +1,124 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Renderer:timeline 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="cxd-Timeline cxd-Timeline-vertical cxd-Timeline-right"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-axle"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-line"
|
||||
/>
|
||||
<div
|
||||
class="cxd-TimelineItem-round"
|
||||
style="background-color: rgb(255, 178, 0);"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-time"
|
||||
>
|
||||
2019-02-07
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-title"
|
||||
>
|
||||
节点数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-axle"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-line"
|
||||
/>
|
||||
<div
|
||||
class="cxd-TimelineItem-round"
|
||||
style="background-color: rgb(79, 134, 244);"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-time"
|
||||
>
|
||||
2019-02-08
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-title"
|
||||
>
|
||||
节点数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-axle"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-line"
|
||||
/>
|
||||
<div
|
||||
class="cxd-TimelineItem-round cxd-TimelineItem-round--success"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-time"
|
||||
>
|
||||
2019-02-09
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-title"
|
||||
>
|
||||
节点数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-axle"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-line"
|
||||
/>
|
||||
<div
|
||||
class="cxd-TimelineItem-round cxd-TimelineItem-round--warning"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-content"
|
||||
>
|
||||
<div
|
||||
class="cxd-TimelineItem-time"
|
||||
>
|
||||
2019-02-09
|
||||
</div>
|
||||
<div
|
||||
class="cxd-TimelineItem-title"
|
||||
>
|
||||
节点数据
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
@ -35,6 +35,68 @@ order: 44
|
||||
}
|
||||
```
|
||||
|
||||
## 分组展示模式
|
||||
|
||||
配置`children`可以实现分组展示,分组标题支持配置`icon`。
|
||||
|
||||
> 1.5.7 及以上版本
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "dropdown-button",
|
||||
"label": "下拉菜单",
|
||||
"buttons": [
|
||||
{
|
||||
"label": "RD",
|
||||
"icon": "fa fa-user",
|
||||
"children": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "前端FE"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "后端RD"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "QA",
|
||||
"icon": "fa fa-user",
|
||||
"children": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "测试QA",
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "交付测试DQA",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"type": "divider"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "Manager",
|
||||
"icon": "fa fa-user",
|
||||
"children": [
|
||||
{
|
||||
"type": "button",
|
||||
"label": "项目经理PM"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"label": "项目管理中心PMO",
|
||||
"visible": false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 关闭下拉菜单
|
||||
|
||||
配置`"closeOnClick": true`可以实现点击按钮后自动关闭下拉菜单。
|
||||
@ -197,18 +259,20 @@ order: 44
|
||||
|
||||
## 属性表
|
||||
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| --------------- | ------------------ | ----------------- | ----------------------------------------- |
|
||||
| type | `string` | `dropdown-button` | 类型 |
|
||||
| label | `string` | | 按钮文本 |
|
||||
| className | `string` | | 外层 CSS 类名 |
|
||||
| block | `boolean` | | 块状样式 |
|
||||
| size | `string` | | 尺寸,支持`'xs'`、`'sm'`、`'md'` 、`'lg'` |
|
||||
| align | `string` | | 位置,可选`'left'`或`'right'` |
|
||||
| buttons | `Array<action>` | | 配置下拉按钮 |
|
||||
| iconOnly | `boolean` | | 只显示 icon |
|
||||
| defaultIsOpened | `boolean` | | 默认是否打开 |
|
||||
| closeOnOutside | `boolean` | `true` | 点击外侧区域是否收起 |
|
||||
| closeOnClick | `boolean` | `false` | 点击按钮后自动关闭下拉菜单 |
|
||||
| trigger | `click` 或 `hover` | `click` | 触发方式 |
|
||||
| hideCaret | `boolean` | false | 隐藏下拉图标 |
|
||||
| 属性名 | 类型 | 默认值 | 说明 |
|
||||
| --------------- | ----------------------- | ----------------- | ----------------------------------------- |
|
||||
| type | `string` | `dropdown-button` | 类型 |
|
||||
| label | `string` | | 按钮文本 |
|
||||
| className | `string` | | 外层 CSS 类名 |
|
||||
| btnClassName | `string` | | 按钮 CSS 类名 |
|
||||
| menuClassName | `string` | | 下拉菜单 CSS 类名 |
|
||||
| block | `boolean` | | 块状样式 |
|
||||
| size | `string` | | 尺寸,支持`'xs'`、`'sm'`、`'md'` 、`'lg'` |
|
||||
| align | `string` | | 位置,可选`'left'`或`'right'` |
|
||||
| buttons | `Array<DropdownButton>` | | 配置下拉按钮 |
|
||||
| iconOnly | `boolean` | | 只显示 icon |
|
||||
| defaultIsOpened | `boolean` | | 默认是否打开 |
|
||||
| closeOnOutside | `boolean` | `true` | 点击外侧区域是否收起 |
|
||||
| closeOnClick | `boolean` | `false` | 点击按钮后自动关闭下拉菜单 |
|
||||
| trigger | `click` 或 `hover` | `click` | 触发方式 |
|
||||
| hideCaret | `boolean` | false | 隐藏下拉图标 |
|
||||
|
@ -626,10 +626,11 @@
|
||||
--DropDown-menu-paddingX: 0;
|
||||
--DropDown-menu-paddingY: var(--gap-xs);
|
||||
--DropDown-menuItem-onHover-bg: var(--ListMenu-item--onHover-bg);
|
||||
--DropDown-menuItem-color: var(--text-color);
|
||||
--DropDown-group-color: #848b99;
|
||||
--DropDown-menuItem-color: #151a26;
|
||||
--DropDown-menuItem-onHover-color: var(--primary);
|
||||
--DropDown-menuItem-onActive-color: var(--primary);
|
||||
--DropDown-menuItem-onDisabled-color: var(--text--muted-color);
|
||||
--DropDown-menuItem-onDisabled-color: #b4b6ba;
|
||||
--DropDown-menuItem-paddingX: var(--gap-sm);
|
||||
--DropDown-menuItem-paddingY: calc(
|
||||
(var(--DropDown-menu-height) - var(--fontSizeBase) * var(--lineHeightBase)) /
|
||||
|
@ -34,20 +34,28 @@
|
||||
}
|
||||
|
||||
&-menu {
|
||||
position: absolute;
|
||||
z-index: $zindex-dropdown;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin: px2rem(1px) 0 0;
|
||||
background: var(--DropDown-menu-bg);
|
||||
list-style: none;
|
||||
padding: var(--DropDown-menu-paddingY) var(--DropDown-menu-paddingX);
|
||||
border: var(--DropDown-menu-borderWidth) solid
|
||||
var(--DropDown-menu-borderColor);
|
||||
border-radius: var(--DropDown-menu-borderRadius);
|
||||
box-shadow: var(--DropDown-menu-boxShadow);
|
||||
min-width: var(--DropDown-menu-minWidth);
|
||||
text-align: left;
|
||||
border: none;
|
||||
user-select: none;
|
||||
|
||||
&-root {
|
||||
position: absolute;
|
||||
z-index: $zindex-dropdown;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
margin: px2rem(1px) 0 0;
|
||||
border: none;
|
||||
border-radius: var(--DropDown-menu-borderRadius);
|
||||
box-shadow: var(--DropDown-menu-boxShadow);
|
||||
min-width: var(--DropDown-menu-minWidth);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
max-height: px2rem(300px);
|
||||
}
|
||||
}
|
||||
|
||||
&--alignRight &-menu {
|
||||
@ -95,6 +103,28 @@
|
||||
background: var(--DropDown-menu-borderColor);
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&.#{$ns}DropDown-groupTitle {
|
||||
height: inherit;
|
||||
font-size: var(--fontSizeSm);
|
||||
padding: var(--gap-xs) var(--gap-xs);
|
||||
padding-left: var(--gap-sm);
|
||||
color: var(--DropDown-group-color);
|
||||
flex-grow: 1;
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
|
||||
span {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
& ~ .#{$ns}DropDown-button {
|
||||
padding-left: var(--gap-lg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-menu > li a {
|
||||
|
@ -639,7 +639,8 @@ $L1: 0px 4px 6px 0px rgba(8, 14, 26, 0.06),
|
||||
--TimelineItem--round-radius: #{$R8};
|
||||
--TimelineItem--content-radius: #{$R2};
|
||||
|
||||
--TimelineItem-detail-visible-shadow: 0 #{px2rem(1px)} #{px2rem(10px)} 0 rgba(0 0 0 / 10%);
|
||||
--TimelineItem-detail-visible-shadow: 0 #{px2rem(1px)} #{px2rem(10px)} 0
|
||||
rgba(0 0 0 / 10%);
|
||||
|
||||
--TimelineItem--font-size: #{$T2};
|
||||
|
||||
@ -655,7 +656,6 @@ $L1: 0px 4px 6px 0px rgba(8, 14, 26, 0.06),
|
||||
--Timeline--warning-bg: var(--warning);
|
||||
--Timeline--danger-bg: var(--danger);
|
||||
|
||||
|
||||
// Formula
|
||||
--Formula-header-bgColor: #{$G10};
|
||||
--Formula-funcItem-bgColor-onActive: #{$light};
|
||||
|
@ -96,18 +96,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}DropDown {
|
||||
.#{$ns}DropDown-menu {
|
||||
border: none;
|
||||
> li {
|
||||
color: #{$G2};
|
||||
}
|
||||
> li.is-disabled {
|
||||
color: #{$G6};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}Toast {
|
||||
.#{$ns}Toast-icon {
|
||||
margin-right: #{px2rem(8px)};
|
||||
|
@ -13,6 +13,13 @@ import {DividerSchema} from './Divider';
|
||||
import {RootClose} from '../utils/RootClose';
|
||||
import {generateIcon} from '../utils/icon';
|
||||
|
||||
import type {Option} from '../components/Select';
|
||||
|
||||
export type DropdownButton =
|
||||
| (ActionSchema & {children?: Array<DropdownButton>})
|
||||
| DividerSchema
|
||||
| 'divider';
|
||||
|
||||
/**
|
||||
* 下拉按钮渲染器。
|
||||
* 文档:https://baidu.gitee.io/amis/docs/components/dropdown-button
|
||||
@ -34,9 +41,9 @@ export interface DropdownButtonSchema extends BaseSchema {
|
||||
btnClassName?: SchemaClassName;
|
||||
|
||||
/**
|
||||
* 按钮集合
|
||||
* 按钮集合,支持分组
|
||||
*/
|
||||
buttons?: Array<ActionSchema | DividerSchema | 'divider'>;
|
||||
buttons?: Array<DropdownButton>;
|
||||
|
||||
/**
|
||||
* 按钮文字
|
||||
@ -92,6 +99,11 @@ export interface DropdownButtonSchema extends BaseSchema {
|
||||
* 是否显示下拉按钮
|
||||
*/
|
||||
hideCaret?: boolean;
|
||||
|
||||
/**
|
||||
* 菜单 CSS 样式
|
||||
*/
|
||||
menuClassName?: string;
|
||||
}
|
||||
|
||||
export interface DropDownButtonProps
|
||||
@ -110,6 +122,7 @@ export interface DropDownButtonProps
|
||||
label?: any;
|
||||
// 激活状态
|
||||
isActived?: boolean;
|
||||
menuClassName?: string;
|
||||
}
|
||||
|
||||
export interface DropDownButtonState {
|
||||
@ -175,6 +188,49 @@ export default class DropDownButton extends React.Component<
|
||||
});
|
||||
}
|
||||
|
||||
renderButton(
|
||||
button: DropdownButton,
|
||||
index: number | string
|
||||
): React.ReactNode {
|
||||
const {render, classnames: cx, data} = this.props;
|
||||
index = typeof index === 'number' ? index.toString() : index;
|
||||
|
||||
if (typeof button !== 'string' && Array.isArray(button?.children)) {
|
||||
return (
|
||||
<div key={index} className={cx('DropDown-menu')}>
|
||||
<li key={`${index}/0`} className={cx('DropDown-groupTitle')}>
|
||||
{button.icon ? generateIcon(cx, button.icon, 'm-r-xs') : null}
|
||||
<span>{button.label}</span>
|
||||
</li>
|
||||
{button.children.map((child, childIndex) =>
|
||||
this.renderButton(child, `${index}/${childIndex + 1}`)
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof button !== 'string' && !isVisible(button, data)) {
|
||||
return null;
|
||||
} else if (button === 'divider' || button.type === 'divider') {
|
||||
return <li key={index} className={cx('DropDown-divider')} />;
|
||||
} else {
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
className={cx('DropDown-button', {
|
||||
['is-disabled']: isDisabled(button, data)
|
||||
})}
|
||||
>
|
||||
{render(`button/${index}`, {
|
||||
type: 'button',
|
||||
...(button as any),
|
||||
isMenuItem: true
|
||||
})}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
renderOuter() {
|
||||
const {
|
||||
render,
|
||||
@ -186,7 +242,8 @@ export default class DropDownButton extends React.Component<
|
||||
children,
|
||||
align,
|
||||
closeOnClick,
|
||||
closeOnOutside
|
||||
closeOnOutside,
|
||||
menuClassName
|
||||
} = this.props;
|
||||
|
||||
let body = (
|
||||
@ -197,43 +254,20 @@ export default class DropDownButton extends React.Component<
|
||||
{(ref: any) => {
|
||||
return (
|
||||
<ul
|
||||
className={cx('DropDown-menu')}
|
||||
className={cx(
|
||||
'DropDown-menu-root',
|
||||
'DropDown-menu',
|
||||
menuClassName
|
||||
)}
|
||||
onClick={closeOnClick ? this.close : noop}
|
||||
ref={ref}
|
||||
>
|
||||
{children
|
||||
? children
|
||||
: Array.isArray(buttons)
|
||||
? buttons.map((button, index) => {
|
||||
if (
|
||||
typeof button !== 'string' &&
|
||||
!isVisible(button, data)
|
||||
) {
|
||||
return null;
|
||||
} else if (
|
||||
button === 'divider' ||
|
||||
button.type === 'divider'
|
||||
) {
|
||||
return (
|
||||
<li key={index} className={cx('DropDown-divider')} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li
|
||||
key={index}
|
||||
className={
|
||||
isDisabled(button, data) ? 'is-disabled' : ''
|
||||
}
|
||||
>
|
||||
{render(`button/${index}`, {
|
||||
type: 'button',
|
||||
...(button as any),
|
||||
isMenuItem: true
|
||||
})}
|
||||
</li>
|
||||
);
|
||||
})
|
||||
? buttons.map((button, index) =>
|
||||
this.renderButton(button, index)
|
||||
)
|
||||
: null}
|
||||
</ul>
|
||||
);
|
||||
@ -248,7 +282,7 @@ export default class DropDownButton extends React.Component<
|
||||
overlay
|
||||
onHide={this.close}
|
||||
classPrefix={ns}
|
||||
className={cx('DropDown-popover')}
|
||||
className={cx('DropDown-popover', menuClassName)}
|
||||
style={{minWidth: this.target?.offsetWidth}}
|
||||
>
|
||||
{body}
|
||||
|
Loading…
Reference in New Issue
Block a user