diff --git a/libs/sdk-ui-dashboard/src/presentation/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialog.tsx b/libs/sdk-ui-dashboard/src/presentation/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialog.tsx index bdd7f06a487..7a8ba099c60 100644 --- a/libs/sdk-ui-dashboard/src/presentation/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialog.tsx +++ b/libs/sdk-ui-dashboard/src/presentation/scheduledEmail/DefaultScheduledEmailManagementDialog/DefaultScheduledEmailManagementDialog.tsx @@ -2,7 +2,7 @@ import React, { useCallback, useState } from "react"; import { FormattedMessage, useIntl } from "react-intl"; -import { Button, Dialog, Hyperlink, Typography } from "@gooddata/sdk-ui-kit"; +import { AddButton, Button, Dialog, Hyperlink, Typography } from "@gooddata/sdk-ui-kit"; import { IAutomationMetadataObject } from "@gooddata/sdk-model"; import { ScheduledEmails } from "./components/ScheduledEmailsList.js"; @@ -15,7 +15,6 @@ import { useDashboardSelector, } from "../../../model/index.js"; import { messages } from "../../../locales.js"; -import { CreateButton } from "./components/CreateButton.js"; /** * @alpha @@ -72,10 +71,10 @@ export const ScheduledEmailManagementDialog: React.FC - = maxAutomations} - titleId={messages.scheduleManagementCreate.id!} + title={} /> void; -} - -// TODO: this can be fully moved to sdk-ui-kit (inspired by add grantee button and generalized a bit) -export const CreateButton: React.FC = (props) => { - const { isDisabled, onClick, titleId, tooltipId } = props; - - const buttonClassNames = cx( - { - disabled: isDisabled, - }, - "gd-button-link", - "gd-icon-plus", - "s-create-item", - ); - - const handleClick = useCallback( - (e: React.MouseEvent) => { - e.preventDefault(); - if (isDisabled) { - return; - } - onClick?.(); - }, - [isDisabled, onClick], - ); - - if (!tooltipId) { - return ( - - ); - } - - return ( - - - - - - - ); -}; diff --git a/libs/sdk-ui-dashboard/styles/scss/scheduled_mail.scss b/libs/sdk-ui-dashboard/styles/scss/scheduled_mail.scss index 87c4bbcd651..59d12439fa2 100644 --- a/libs/sdk-ui-dashboard/styles/scss/scheduled_mail.scss +++ b/libs/sdk-ui-dashboard/styles/scss/scheduled_mail.scss @@ -152,7 +152,6 @@ $dialog-padding: 20px; > .gd-label { height: 30px; line-height: 30px; - margin-bottom: 5px; } .gd-attachment-config-button { @@ -369,7 +368,7 @@ $dialog-padding: 20px; @media #{kit-variables.$small-only} { width: calc(100vw - 20px); - height: 100vh; + height: 90vh; max-height: none; } @@ -377,6 +376,10 @@ $dialog-padding: 20px; display: flex; margin-bottom: 10px; + .gd-dialog-header { + margin: 0; + } + > h3 { color: var(--gd-modal-title-color, kit-variables.$gd-color-dark); } @@ -848,6 +851,7 @@ $dialog-padding: 20px; } .gd-divider-with-margin { + margin-top: 0; margin-bottom: $vertical-space; } diff --git a/libs/sdk-ui-kit/api/sdk-ui-kit.api.md b/libs/sdk-ui-kit/api/sdk-ui-kit.api.md index a61f950f00d..25c42d59cd6 100644 --- a/libs/sdk-ui-kit/api/sdk-ui-kit.api.md +++ b/libs/sdk-ui-kit/api/sdk-ui-kit.api.md @@ -49,6 +49,9 @@ export type ActionType = "LinkButton" | "Button" | "Switcher"; // @internal (undocumented) export function activateHeaderMenuItems(items: IHeaderMenuItem[][], ids: Array): IHeaderMenuItem[][]; +// @internal (undocumented) +export const AddButton: React_2.FC; + // @internal (undocumented) export const AddGranteeBase: React_2.FC; @@ -739,6 +742,22 @@ export const HubspotConversionTouchPointDialog: React_2.FC; +// @internal (undocumented) +export interface IAddButtonProps { + // (undocumented) + className?: string; + // (undocumented) + isDisabled?: boolean; + // (undocumented) + onClick?: () => void; + // (undocumented) + title: JSX.Element; + // (undocumented) + tooltip?: JSX.Element; + // (undocumented) + tooltipAlignPoints?: IAlignPoint[]; +} + // @internal (undocumented) export interface IAddGranteeBaseProps { // (undocumented) diff --git a/libs/sdk-ui-kit/src/AddButton/AddButton.tsx b/libs/sdk-ui-kit/src/AddButton/AddButton.tsx new file mode 100644 index 00000000000..3dc8d036553 --- /dev/null +++ b/libs/sdk-ui-kit/src/AddButton/AddButton.tsx @@ -0,0 +1,76 @@ +// (C) 2024 GoodData Corporation + +import React, { useCallback } from "react"; +import cx from "classnames"; +import { BubbleHoverTrigger } from "../Bubble/BubbleHoverTrigger.js"; +import { Button } from "../Button/Button.js"; +import { Bubble } from "../Bubble/Bubble.js"; +import { IAlignPoint } from "../typings/positioning.js"; + +const defaultTooltipAlignPoints = [{ align: "cr cl" }, { align: "cl cr" }]; + +/** + * @internal + */ +export interface IAddButtonProps { + title: JSX.Element; + isDisabled?: boolean; + onClick?: () => void; + tooltip?: JSX.Element; + tooltipAlignPoints?: IAlignPoint[]; + className?: string; +} + +/** + * @internal + */ +export const AddButton: React.FC = (props) => { + const { + title, + isDisabled, + onClick, + tooltip, + tooltipAlignPoints = defaultTooltipAlignPoints, + className, + } = props; + + const buttonClassNames = cx( + { + disabled: isDisabled, + }, + "gd-button-link", + "gd-icon-plus", + "s-add-button", + className, + ); + + const handleClick = useCallback( + (e: React.MouseEvent) => { + e.preventDefault(); + if (isDisabled) { + return; + } + onClick?.(); + }, + [isDisabled, onClick], + ); + + if (!tooltip) { + return ( + + ); + } + + return ( + + + + {tooltip} + + + ); +}; diff --git a/libs/sdk-ui-kit/src/AddButton/index.ts b/libs/sdk-ui-kit/src/AddButton/index.ts new file mode 100644 index 00000000000..8aab22976a4 --- /dev/null +++ b/libs/sdk-ui-kit/src/AddButton/index.ts @@ -0,0 +1,3 @@ +// (C) 2024 GoodData Corporation + +export { AddButton, IAddButtonProps } from "./AddButton.js"; diff --git a/libs/sdk-ui-kit/src/index.ts b/libs/sdk-ui-kit/src/index.ts index eaac9c5bc8c..906e9067f34 100644 --- a/libs/sdk-ui-kit/src/index.ts +++ b/libs/sdk-ui-kit/src/index.ts @@ -60,3 +60,4 @@ export * from "./TextAreaWithSubmit/index.js"; export * from "./SeparatorLine/index.js"; export * from "./RichText/index.js"; export * from "./RecurrenceForm/index.js"; +export * from "./AddButton/index.js"; diff --git a/libs/sdk-ui-tests/stories/visual-regression/kit/AddButton/AddButton.tsx b/libs/sdk-ui-tests/stories/visual-regression/kit/AddButton/AddButton.tsx new file mode 100644 index 00000000000..c71353b4b88 --- /dev/null +++ b/libs/sdk-ui-tests/stories/visual-regression/kit/AddButton/AddButton.tsx @@ -0,0 +1,31 @@ +// (C) 2024 GoodData Corporation + +import React from "react"; +import { storiesOf } from "../../../_infra/storyRepository.js"; +import { UiKit } from "../../../_infra/storyGroups.js"; +import { wrapWithTheme } from "../../themeWrapper.js"; +import { AddButton } from "@gooddata/sdk-ui-kit"; +import { action } from "@storybook/addon-actions"; + +const onClick = () => { + action("onClick"); +}; + +const AddButtonTest = () => { + return ( +
+

Default

+ Create} onClick={onClick} /> + +

Disabled

+ Can't touch this} isDisabled={true} onClick={onClick} /> + +

With tooltip

+ Hover} tooltip={<>Some information here!} onClick={onClick} /> +
+ ); +}; + +storiesOf(`${UiKit}/AddButton`) + .add("full-featured", () => , { screenshot: true }) + .add("themed", () => wrapWithTheme(), { screenshot: true });