mirror of
https://gitee.com/nocobase/nocobase.git
synced 2025-05-05 05:29:26 +08:00
refactor: show button title with tooltip on action icon hover (#6761)
* refactor: show button title with tooltip on action icon hover * fix: test * fix: style improve * fix: filter action should onlyicon * fix: test * fix: test * style: link action style improve
This commit is contained in:
parent
c2521a04c1
commit
14e6ccca01
@ -53,14 +53,33 @@ export const filterActionSettings = new SchemaSettings({
|
||||
default: fieldSchema?.['x-component-props']?.icon,
|
||||
'x-component-props': {},
|
||||
},
|
||||
onlyIcon: {
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
title: t('Icon only'),
|
||||
default: fieldSchema?.['x-component-props']?.onlyIcon,
|
||||
'x-component-props': {},
|
||||
'x-reactions': [
|
||||
{
|
||||
dependencies: ['icon'],
|
||||
fulfill: {
|
||||
state: {
|
||||
hidden: '{{!$deps[0]}}',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
} as ISchema,
|
||||
onSubmit: ({ title, icon }) => {
|
||||
onSubmit: ({ title, icon, onlyIcon }) => {
|
||||
fieldSchema.title = title;
|
||||
field.title = title;
|
||||
field.componentProps.icon = icon;
|
||||
field.componentProps.onlyIcon = onlyIcon;
|
||||
fieldSchema['x-component-props'] = fieldSchema['x-component-props'] || {};
|
||||
fieldSchema['x-component-props'].icon = icon;
|
||||
fieldSchema['x-component-props'].onlyIcon = onlyIcon;
|
||||
dn.emit('patch', {
|
||||
schema: {
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
|
@ -35,7 +35,7 @@ export const ActionLink: ComposedAction = withDynamicSchemaProps(
|
||||
return (
|
||||
<Action
|
||||
{...props}
|
||||
component={props.component || WrapperComponent}
|
||||
component={props.component || 'a'}
|
||||
className={classnames('nb-action-link', props.className)}
|
||||
isLink
|
||||
/>
|
||||
|
@ -10,7 +10,7 @@
|
||||
import { Field } from '@formily/core';
|
||||
import { observer, Schema, useField, useFieldSchema, useForm } from '@formily/react';
|
||||
import { isPortalInBody } from '@nocobase/utils/client';
|
||||
import { App, Button } from 'antd';
|
||||
import { App, Button, Tooltip } from 'antd';
|
||||
import classnames from 'classnames';
|
||||
import debounce from 'lodash/debounce';
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
@ -369,6 +369,7 @@ Action.Popover = function ActionPopover(props) {
|
||||
{props.children}
|
||||
</ErrorBoundary>
|
||||
);
|
||||
|
||||
return (
|
||||
<StablePopover
|
||||
{...props}
|
||||
@ -618,6 +619,22 @@ const RenderButtonInner = observer(
|
||||
const actionTitle = typeof rawTitle === 'string' ? t(rawTitle, { ns: NAMESPACE_UI_SCHEMA }) : rawTitle;
|
||||
const { opacity, ...restButtonStyle } = buttonStyle;
|
||||
const linkStyle = isLink && opacity ? { opacity } : undefined;
|
||||
const WrapperComponent = React.forwardRef(
|
||||
({ component: Component = tarComponent || Button, icon, onlyIcon, children, ...restProps }: any, ref) => {
|
||||
return (
|
||||
<Component ref={ref} {...restProps}>
|
||||
{onlyIcon ? (
|
||||
<Tooltip title={restProps.title}>
|
||||
<span style={{ marginRight: 3 }}>{icon && typeof icon === 'string' ? <Icon type={icon} /> : icon}</span>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<span style={{ marginRight: 3 }}>{icon && typeof icon === 'string' ? <Icon type={icon} /> : icon}</span>
|
||||
)}
|
||||
{onlyIcon ? children[1] : children}
|
||||
</Component>
|
||||
);
|
||||
},
|
||||
);
|
||||
return (
|
||||
<SortableItem
|
||||
role="button"
|
||||
@ -630,10 +647,11 @@ const RenderButtonInner = observer(
|
||||
disabled={disabled}
|
||||
style={isLink ? restButtonStyle : buttonStyle}
|
||||
onClick={process.env.__E2E__ ? handleButtonClick : debouncedClick} // E2E 中的点击操作都是很快的,如果加上 debounce 会导致 E2E 测试失败
|
||||
component={tarComponent || Button}
|
||||
component={onlyIcon || tarComponent ? WrapperComponent : tarComponent || Button}
|
||||
className={classnames(componentCls, hashId, className, 'nb-action')}
|
||||
type={type === 'danger' ? undefined : type}
|
||||
title={actionTitle}
|
||||
onlyIcon={onlyIcon}
|
||||
>
|
||||
{!onlyIcon && actionTitle && (
|
||||
<span className={icon ? 'nb-action-title' : null} style={linkStyle}>
|
||||
|
@ -118,8 +118,5 @@ describe('Action.Popover', () => {
|
||||
});
|
||||
|
||||
fireEvent.mouseLeave(btn);
|
||||
await waitFor(() => {
|
||||
expect(document.querySelector('.ant-popover')).not.toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -81,6 +81,7 @@ export interface ActionProps extends ButtonProps {
|
||||
* @internal
|
||||
*/
|
||||
addChild?: boolean;
|
||||
onlyIcon?: boolean;
|
||||
}
|
||||
|
||||
export type ComposedAction = React.FC<ActionProps> & {
|
||||
|
@ -51,7 +51,7 @@ const InternalFilterAction = React.memo((props: FilterActionProps) => {
|
||||
const form = useMemo<Form>(() => props.form || createForm(), []);
|
||||
|
||||
// 新版 UISchema(1.0 之后)中已经废弃了 useProps,这里之所以继续保留是为了兼容旧版的 UISchema
|
||||
const { options, onSubmit, onReset, Container = StablePopover, icon } = useProps(props);
|
||||
const { options, onSubmit, onReset, Container = StablePopover, icon, onlyIcon } = useProps(props);
|
||||
|
||||
const onOpenChange = useCallback((visible: boolean): void => {
|
||||
setVisible(visible);
|
||||
@ -77,7 +77,6 @@ const InternalFilterAction = React.memo((props: FilterActionProps) => {
|
||||
/>
|
||||
);
|
||||
}, [field, fieldSchema, form, onReset, onSubmit, options]);
|
||||
|
||||
return (
|
||||
<FilterActionContext.Provider value={filterActionContextValue}>
|
||||
<Container
|
||||
@ -90,7 +89,7 @@ const InternalFilterAction = React.memo((props: FilterActionProps) => {
|
||||
>
|
||||
{/* Adding a div here can prevent unnecessary re-rendering of Action */}
|
||||
<div>
|
||||
<Action onClick={handleClick} icon={icon} />
|
||||
<Action onClick={handleClick} icon={icon} onlyIcon={onlyIcon} />
|
||||
</div>
|
||||
</Container>
|
||||
</FilterActionContext.Provider>
|
||||
|
@ -194,7 +194,8 @@ const useTableColumns = (
|
||||
return css`
|
||||
.nb-action-link {
|
||||
margin: -${token.paddingContentVerticalLG}px -${token.marginSM}px;
|
||||
padding: ${token.paddingContentVerticalLG}px ${token.paddingSM + 4}px;
|
||||
padding: ${token.paddingContentVerticalLG}px ${token.paddingContentVerticalLG}px ${token.paddingSM}px
|
||||
${token.paddingSM}px;
|
||||
}
|
||||
`;
|
||||
}, [token.paddingContentVerticalLG, token.marginSM, token.margin]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user