From 4f6a62fa53646dd93d84ad71a09f21a848f7e489 Mon Sep 17 00:00:00 2001
From: Paul Li <82799722+wmdev0808@users.noreply.github.com>
Date: Thu, 5 Aug 2021 07:16:26 -0400
Subject: [PATCH] Icon Button Widget (#5723)
Introducing the **Floating action button / Icon button**. Now you can use this to show small actions as icons. We have added a bunch of styling customisation to this as well. You can bind an onClick action to this and easily trigger an even. The component also automatically resizes within the widget as you scale it while maintaining the right aspect ratio.
---
.../icons/control/border-radius-circle.svg | 3 +
.../icons/control/border-radius-rounded.svg | 3 +
.../icons/control/border-radius-sharp.svg | 3 +
.../assets/icons/control/box-shadow-none.svg | 3 +
.../icons/control/box-shadow-variant1.svg | 17 +
.../icons/control/box-shadow-variant2.svg | 16 +
.../icons/control/box-shadow-variant3.svg | 16 +
.../icons/control/box-shadow-variant4.svg | 15 +
.../icons/control/box-shadow-variant5.svg | 15 +
.../src/assets/icons/widget/icon-button.svg | 3 +
.../appsmith/IconButtonComponent.tsx | 255 +++++++++++++++
.../BorderRadiusOptionsControl.tsx | 88 +++++
.../BoxShadowOptionsControl.tsx | 141 ++++++++
.../propertyControls/IconSelectControl.tsx | 4 -
.../src/components/propertyControls/index.ts | 4 +
app/client/src/constants/Colors.tsx | 23 ++
app/client/src/constants/DefaultTheme.tsx | 304 ++++++++++++++++++
app/client/src/constants/HelpConstants.ts | 4 +
app/client/src/constants/WidgetConstants.tsx | 1 +
app/client/src/icons/ControlIcons.tsx | 54 ++++
app/client/src/icons/WidgetIcons.tsx | 6 +
.../mockResponses/WidgetConfigResponse.tsx | 22 ++
.../mockResponses/WidgetSidebarResponse.tsx | 5 +
.../entityReducers/widgetConfigReducer.tsx | 2 +
app/client/src/utils/WidgetRegistry.tsx | 17 +
.../utils/autocomplete/EntityDefinitions.ts | 6 +
app/client/src/widgets/IconButtonWidget.tsx | 236 ++++++++++++++
27 files changed, 1262 insertions(+), 4 deletions(-)
create mode 100755 app/client/src/assets/icons/control/border-radius-circle.svg
create mode 100755 app/client/src/assets/icons/control/border-radius-rounded.svg
create mode 100755 app/client/src/assets/icons/control/border-radius-sharp.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-none.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-variant1.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-variant2.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-variant3.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-variant4.svg
create mode 100755 app/client/src/assets/icons/control/box-shadow-variant5.svg
create mode 100755 app/client/src/assets/icons/widget/icon-button.svg
create mode 100644 app/client/src/components/designSystems/appsmith/IconButtonComponent.tsx
create mode 100644 app/client/src/components/propertyControls/BorderRadiusOptionsControl.tsx
create mode 100644 app/client/src/components/propertyControls/BoxShadowOptionsControl.tsx
create mode 100644 app/client/src/widgets/IconButtonWidget.tsx
diff --git a/app/client/src/assets/icons/control/border-radius-circle.svg b/app/client/src/assets/icons/control/border-radius-circle.svg
new file mode 100755
index 0000000000..0683922aca
--- /dev/null
+++ b/app/client/src/assets/icons/control/border-radius-circle.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/assets/icons/control/border-radius-rounded.svg b/app/client/src/assets/icons/control/border-radius-rounded.svg
new file mode 100755
index 0000000000..6457a8a822
--- /dev/null
+++ b/app/client/src/assets/icons/control/border-radius-rounded.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/assets/icons/control/border-radius-sharp.svg b/app/client/src/assets/icons/control/border-radius-sharp.svg
new file mode 100755
index 0000000000..3cbbd67cba
--- /dev/null
+++ b/app/client/src/assets/icons/control/border-radius-sharp.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-none.svg b/app/client/src/assets/icons/control/box-shadow-none.svg
new file mode 100755
index 0000000000..341d9a49c8
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-none.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-variant1.svg b/app/client/src/assets/icons/control/box-shadow-variant1.svg
new file mode 100755
index 0000000000..6aa7157246
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-variant1.svg
@@ -0,0 +1,17 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-variant2.svg b/app/client/src/assets/icons/control/box-shadow-variant2.svg
new file mode 100755
index 0000000000..8fa744e9a3
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-variant2.svg
@@ -0,0 +1,16 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-variant3.svg b/app/client/src/assets/icons/control/box-shadow-variant3.svg
new file mode 100755
index 0000000000..6db02bac83
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-variant3.svg
@@ -0,0 +1,16 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-variant4.svg b/app/client/src/assets/icons/control/box-shadow-variant4.svg
new file mode 100755
index 0000000000..de2d7f492a
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-variant4.svg
@@ -0,0 +1,15 @@
+
diff --git a/app/client/src/assets/icons/control/box-shadow-variant5.svg b/app/client/src/assets/icons/control/box-shadow-variant5.svg
new file mode 100755
index 0000000000..7f1aebca1e
--- /dev/null
+++ b/app/client/src/assets/icons/control/box-shadow-variant5.svg
@@ -0,0 +1,15 @@
+
diff --git a/app/client/src/assets/icons/widget/icon-button.svg b/app/client/src/assets/icons/widget/icon-button.svg
new file mode 100755
index 0000000000..60f87aa313
--- /dev/null
+++ b/app/client/src/assets/icons/widget/icon-button.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/components/designSystems/appsmith/IconButtonComponent.tsx b/app/client/src/components/designSystems/appsmith/IconButtonComponent.tsx
new file mode 100644
index 0000000000..47c05cef9c
--- /dev/null
+++ b/app/client/src/components/designSystems/appsmith/IconButtonComponent.tsx
@@ -0,0 +1,255 @@
+import * as React from "react";
+import { useMemo } from "react";
+import styled from "styled-components";
+import { Button } from "@blueprintjs/core";
+import { IconName } from "@blueprintjs/icons";
+
+import { ComponentProps } from "components/designSystems/appsmith/BaseComponent";
+import { ThemeProp } from "components/ads/common";
+import { WIDGET_PADDING } from "constants/WidgetConstants";
+
+const IconButtonContainer = styled.div`
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ height: 100%;
+`;
+
+export interface ButtonStyleProps {
+ borderRadius?: ButtonBorderRadius;
+ boxShadow?: ButtonBoxShadow;
+ boxShadowColor?: string;
+ buttonStyle?: ButtonStyle;
+ buttonVariant?: ButtonVariant;
+ dimension: number;
+}
+
+const StyledButton = styled(Button)`
+ background-image: none !important;
+ height: ${({ dimension }) => `${dimension}px`};
+ width: ${({ dimension }) => `${dimension}px`};
+ ${({ buttonStyle, buttonVariant, theme }) => `
+ &:enabled {
+ background: ${
+ buttonStyle === ButtonStyleTypes.WARNING
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.warning.solid.bgColor
+ : "none"
+ : buttonStyle === ButtonStyleTypes.DANGER
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.danger.solid.bgColor
+ : "none"
+ : buttonStyle === ButtonStyleTypes.INFO
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.info.solid.bgColor
+ : "none"
+ : buttonStyle === ButtonStyleTypes.SECONDARY
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.secondary.solid.bgColor
+ : "none"
+ : buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.primary.solid.bgColor
+ : "none"
+ } !important;
+ }
+
+ &:hover:enabled, &:active:enabled {
+ background: ${
+ buttonStyle === ButtonStyleTypes.WARNING
+ ? buttonVariant === ButtonVariantTypes.OUTLINE
+ ? theme.colors.button.warning.outline.hoverColor
+ : buttonVariant === ButtonVariantTypes.GHOST
+ ? theme.colors.button.warning.ghost.hoverColor
+ : theme.colors.button.warning.solid.hoverColor
+ : buttonStyle === ButtonStyleTypes.DANGER
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.danger.solid.hoverColor
+ : theme.colors.button.danger.outline.hoverColor
+ : buttonStyle === ButtonStyleTypes.INFO
+ ? buttonVariant === ButtonVariantTypes.SOLID
+ ? theme.colors.button.info.solid.hoverColor
+ : theme.colors.button.info.outline.hoverColor
+ : buttonStyle === ButtonStyleTypes.SECONDARY
+ ? buttonVariant === ButtonVariantTypes.OUTLINE
+ ? theme.colors.button.secondary.outline.hoverColor
+ : buttonVariant === ButtonVariantTypes.GHOST
+ ? theme.colors.button.secondary.ghost.hoverColor
+ : theme.colors.button.secondary.solid.hoverColor
+ : buttonVariant === ButtonVariantTypes.OUTLINE
+ ? theme.colors.button.primary.outline.hoverColor
+ : buttonVariant === ButtonVariantTypes.GHOST
+ ? theme.colors.button.primary.ghost.hoverColor
+ : theme.colors.button.primary.solid.hoverColor
+ } !important;
+ }
+
+ &:disabled {
+ background-color: ${theme.colors.button.disabled.bgColor} !important;
+ color: ${theme.colors.button.disabled.textColor} !important;
+ }
+
+ border: ${
+ buttonVariant === ButtonVariantTypes.OUTLINE
+ ? buttonStyle === ButtonStyleTypes.WARNING
+ ? `1px solid ${theme.colors.button.warning.outline.borderColor}`
+ : buttonStyle === ButtonStyleTypes.DANGER
+ ? `1px solid ${theme.colors.button.danger.outline.borderColor}`
+ : buttonStyle === ButtonStyleTypes.INFO
+ ? `1px solid ${theme.colors.button.info.outline.borderColor}`
+ : buttonStyle === ButtonStyleTypes.SECONDARY
+ ? `1px solid ${theme.colors.button.secondary.outline.borderColor}`
+ : `1px solid ${theme.colors.button.primary.outline.borderColor}`
+ : "none"
+ } !important;
+
+ & > span {
+ height: 100%;
+ width: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ color: ${
+ buttonVariant === ButtonVariantTypes.SOLID
+ ? `${theme.colors.button.primary.solid.textColor}`
+ : buttonStyle === ButtonStyleTypes.WARNING
+ ? `${theme.colors.button.warning.outline.textColor}`
+ : buttonStyle === ButtonStyleTypes.DANGER
+ ? `${theme.colors.button.danger.outline.textColor}`
+ : buttonStyle === ButtonStyleTypes.INFO
+ ? `${theme.colors.button.info.outline.textColor}`
+ : buttonStyle === ButtonStyleTypes.SECONDARY
+ ? `${theme.colors.button.secondary.outline.textColor}`
+ : `${theme.colors.button.primary.outline.textColor}`
+ } !important;
+ }
+
+ & > span > svg {
+ height: 60%;
+ width: 60%;
+ min-height: 16px;
+ min-width: 16px;
+ }
+ `}
+
+
+ border-radius: ${({ borderRadius }) =>
+ borderRadius === ButtonBorderRadiusTypes.CIRCLE
+ ? "50%"
+ : borderRadius === ButtonBorderRadiusTypes.ROUNDED
+ ? "10px"
+ : 0};
+
+ box-shadow: ${({ boxShadow, boxShadowColor, theme }) =>
+ boxShadow === ButtonBoxShadowTypes.VARIANT1
+ ? `0px 0px 4px 3px ${boxShadowColor ||
+ theme.colors.button.boxShadow.default.variant1}`
+ : boxShadow === ButtonBoxShadowTypes.VARIANT2
+ ? `3px 3px 4px ${boxShadowColor ||
+ theme.colors.button.boxShadow.default.variant2}`
+ : boxShadow === ButtonBoxShadowTypes.VARIANT3
+ ? `0px 1px 3px ${boxShadowColor ||
+ theme.colors.button.boxShadow.default.variant3}`
+ : boxShadow === ButtonBoxShadowTypes.VARIANT4
+ ? `2px 2px 0px ${boxShadowColor ||
+ theme.colors.button.boxShadow.default.variant4}`
+ : boxShadow === ButtonBoxShadowTypes.VARIANT5
+ ? `-2px -2px 0px ${boxShadowColor ||
+ theme.colors.button.boxShadow.default.variant5}`
+ : "none"} !important;
+`;
+
+export enum ButtonStyleTypes {
+ PRIMARY = "PRIMARY",
+ WARNING = "WARNING",
+ DANGER = "DANGER",
+ INFO = "INFO",
+ SECONDARY = "SECONDARY",
+}
+export type ButtonStyle = keyof typeof ButtonStyleTypes;
+
+export enum ButtonVariantTypes {
+ SOLID = "SOLID",
+ OUTLINE = "OUTLINE",
+ GHOST = "GHOST",
+}
+export type ButtonVariant = keyof typeof ButtonVariantTypes;
+
+export enum ButtonBorderRadiusTypes {
+ SHARP = "SHARP",
+ ROUNDED = "ROUNDED",
+ CIRCLE = "CIRCLE",
+}
+export type ButtonBorderRadius = keyof typeof ButtonBorderRadiusTypes;
+
+export enum ButtonBoxShadowTypes {
+ NONE = "NONE",
+ VARIANT1 = "VARIANT1",
+ VARIANT2 = "VARIANT2",
+ VARIANT3 = "VARIANT3",
+ VARIANT4 = "VARIANT4",
+ VARIANT5 = "VARIANT5",
+}
+export type ButtonBoxShadow = keyof typeof ButtonBoxShadowTypes;
+
+export interface IconButtonComponentProps extends ComponentProps {
+ iconName?: IconName;
+ buttonStyle: ButtonStyle;
+ buttonVariant: ButtonVariant;
+ borderRadius: ButtonBorderRadius;
+ boxShadow: ButtonBoxShadow;
+ boxShadowColor: string;
+ isDisabled: boolean;
+ isVisible: boolean;
+ onClick: () => void;
+ height: number;
+ width: number;
+}
+
+function IconButtonComponent(props: IconButtonComponentProps) {
+ const {
+ borderRadius,
+ boxShadow,
+ boxShadowColor,
+ buttonStyle,
+ buttonVariant,
+ height,
+ isDisabled,
+ onClick,
+ width,
+ } = props;
+
+ /**
+ * returns the dimension to be used for widget
+ * whatever is the minimum between width and height,
+ * we will use that for the dimension of the widget
+ */
+ const dimension = useMemo(() => {
+ console.log({ width, height });
+ if (width > height) {
+ return height - WIDGET_PADDING * 2;
+ }
+
+ return width - WIDGET_PADDING * 2;
+ }, [width, height]);
+
+ return (
+
+
+
+ );
+}
+
+export default IconButtonComponent;
diff --git a/app/client/src/components/propertyControls/BorderRadiusOptionsControl.tsx b/app/client/src/components/propertyControls/BorderRadiusOptionsControl.tsx
new file mode 100644
index 0000000000..9f1d369fed
--- /dev/null
+++ b/app/client/src/components/propertyControls/BorderRadiusOptionsControl.tsx
@@ -0,0 +1,88 @@
+import * as React from "react";
+import styled from "styled-components";
+import { Button, ButtonGroup, IButtonProps } from "@blueprintjs/core";
+
+import BaseControl, { ControlProps } from "./BaseControl";
+import { ControlIcons } from "icons/ControlIcons";
+import { ThemeProp } from "components/ads/common";
+import {
+ ButtonBorderRadius,
+ ButtonBorderRadiusTypes,
+} from "components/designSystems/appsmith/IconButtonComponent";
+
+const StyledButtonGroup = styled(ButtonGroup)`
+ height: 33px;
+`;
+
+const StyledButton = styled(Button)`
+ border: ${(props) =>
+ props.active ? `1px solid #6A86CE` : `1px solid #A9A7A7`};
+ border-radius: 0;
+ box-shadow: none !important;
+ background-image: none !important;
+ background-color: #ffffff !important;
+ & > div {
+ display: flex;
+ }
+ &.bp3-active {
+ box-shadow: none !important;
+ background-color: #ffffff !important;
+ }
+ &:hover {
+ background-color: #ffffff !important;
+ }
+`;
+
+export interface BorderRadiusOptionsControlProps extends ControlProps {
+ propertyValue: ButtonBorderRadius | undefined;
+ onChange: (borderRaidus: ButtonBorderRadius) => void;
+}
+
+class BorderRadiusOptionsControl extends BaseControl<
+ BorderRadiusOptionsControlProps
+> {
+ constructor(props: BorderRadiusOptionsControlProps) {
+ super(props);
+ }
+
+ static getControlType() {
+ return "BORDER_RADIUS_OPTIONS";
+ }
+
+ public render() {
+ const { propertyValue } = this.props;
+
+ return (
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBorderRadiusTypes.SHARP)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBorderRadiusTypes.ROUNDED)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBorderRadiusTypes.CIRCLE)}
+ />
+
+ );
+ }
+
+ private toggleOption = (option: ButtonBorderRadius) => {
+ this.updateProperty(this.props.propertyName, option);
+ };
+}
+
+export default BorderRadiusOptionsControl;
diff --git a/app/client/src/components/propertyControls/BoxShadowOptionsControl.tsx b/app/client/src/components/propertyControls/BoxShadowOptionsControl.tsx
new file mode 100644
index 0000000000..d86d8a8a71
--- /dev/null
+++ b/app/client/src/components/propertyControls/BoxShadowOptionsControl.tsx
@@ -0,0 +1,141 @@
+import * as React from "react";
+import styled from "styled-components";
+import { Button, ButtonGroup, IButtonProps } from "@blueprintjs/core";
+
+import BaseControl, { ControlProps } from "./BaseControl";
+import { ControlIcons } from "icons/ControlIcons";
+import { ThemeProp } from "components/ads/common";
+import {
+ ButtonBoxShadow,
+ ButtonBoxShadowTypes,
+} from "components/designSystems/appsmith/IconButtonComponent";
+
+const StyledButtonGroup = styled(ButtonGroup)`
+ display: grid !important;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 10px;
+ height: 100%;
+`;
+
+const StyledButton = styled(Button)`
+ margin-right: 0 !important;
+ border: ${(props) =>
+ props.active ? `1px solid #6A86CE` : `1px solid #E0DEDE`};
+ border-radius: 0;
+ box-shadow: none !important;
+ background-image: none;
+ background-color: #ffffff !important;
+ & > div {
+ display: flex;
+ }
+ &.bp3-active {
+ box-shadow: none !important;
+ background-color: #ffffff !important;
+ }
+ &:hover {
+ background-color: #ffffff !important;
+ }
+`;
+
+export interface BoxShadowOptionsControlProps extends ControlProps {
+ propertyValue: ButtonBoxShadow | undefined;
+}
+
+class BoxShadowOptionsControl extends BaseControl<
+ BoxShadowOptionsControlProps
+> {
+ constructor(props: BoxShadowOptionsControlProps) {
+ super(props);
+ }
+
+ static getControlType() {
+ return "BOX_SHADOW_OPTIONS";
+ }
+
+ public render() {
+ const { propertyValue } = this.props;
+
+ return (
+
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.NONE)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.VARIANT1)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.VARIANT2)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.VARIANT3)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.VARIANT4)}
+ />
+
+ }
+ large
+ onClick={() => this.toggleOption(ButtonBoxShadowTypes.VARIANT5)}
+ />
+
+ );
+ }
+
+ private toggleOption = (option: ButtonBoxShadow) => {
+ this.updateProperty(this.props.propertyName, option);
+ };
+}
+
+export default BoxShadowOptionsControl;
diff --git a/app/client/src/components/propertyControls/IconSelectControl.tsx b/app/client/src/components/propertyControls/IconSelectControl.tsx
index 9f09b45a42..286f293305 100644
--- a/app/client/src/components/propertyControls/IconSelectControl.tsx
+++ b/app/client/src/components/propertyControls/IconSelectControl.tsx
@@ -24,7 +24,6 @@ const StyledButton = styled(Button)`
border: none !important;
border-radius: 0;
background-color: #ffffff !important;
-
> span.bp3-icon-caret-down {
color: rgb(169, 167, 167);
}
@@ -38,7 +37,6 @@ const StyledMenu = styled(Menu)`
max-height: 170px !important;
padding-left: 5px !important;
padding-right: 5px !important;
-
&::-webkit-scrollbar {
width: 8px;
background-color: #eeeeee;
@@ -54,13 +52,11 @@ const StyledMenuItem = styled(MenuItem)`
flex-direction: column;
align-items: center;
padding: 13px 5px;
-
&:active,
&:hover,
&.bp3-active {
background-color: #eeeeee !important;
}
-
> span.bp3-icon {
margin-right: 0;
color: #939090 !important;
diff --git a/app/client/src/components/propertyControls/index.ts b/app/client/src/components/propertyControls/index.ts
index 0f2c0952a4..c0a034b05b 100644
--- a/app/client/src/components/propertyControls/index.ts
+++ b/app/client/src/components/propertyControls/index.ts
@@ -45,6 +45,8 @@ import MultiSwitchControl, {
import MenuItemsControl from "./MenuItemsControl";
import IconSelectControl from "./IconSelectControl";
import IconAlignControl from "./IconAlignControl";
+import BorderRadiusOptionsControl from "./BorderRadiusOptionsControl";
+import BoxShadowOptionsControl from "./BoxShadowOptionsControl";
export const PropertyControls = {
InputTextControl,
@@ -69,6 +71,8 @@ export const PropertyControls = {
MenuItemsControl,
IconSelectControl,
IconAlignControl,
+ BorderRadiusOptionsControl,
+ BoxShadowOptionsControl,
};
export type PropertyControlPropsType =
diff --git a/app/client/src/constants/Colors.tsx b/app/client/src/constants/Colors.tsx
index 7ab029adaf..2b783af53c 100644
--- a/app/client/src/constants/Colors.tsx
+++ b/app/client/src/constants/Colors.tsx
@@ -87,6 +87,29 @@ export const Colors = {
OPAQ_BLUE: "rgba(106, 134, 206, 0.1)",
RATE_ACTIVE: "#FFCB45",
RATE_INACTIVE: "#F2F2F2",
+
+ ICON_BUTTON_WARNING_SOLID: "#FEB811",
+ ICON_BUTTON_WARNING_SOLID_HOVER: "#EFA903",
+ ICON_BUTTON_WARNING_OUTLINE_HOVER: "#FFFAE9",
+ ICON_BUTTON_WARNING_GHOST_HOVER: "#FBEED0",
+
+ ICON_BUTTON_DANGER_SOLID: "#F22B2B",
+ ICON_BUTTON_DANGER_SOLID_HOVER: "#B90707",
+ ICON_BUTTON_DANGER_NO_SOLID_HOVER: "#FDE4E4",
+
+ ICON_BUTTON_INFO_SOLID: "#6698FF",
+ ICON_BUTTON_INFO_SOLID_HOVER: "#1A65FF",
+ ICON_BUTTON_INFO_NO_SOLID_HOVER: "#CEDCFF",
+
+ ICON_BUTTON_PRIMARY_SOLID_HOVER: "#00693B",
+ ICON_BUTTON_PRIMARY_OUTLINE_HOVER: "#D9FDED",
+ ICON_BUTTON_PRIMARY_GHOST_HOVER: "#CBF4E2",
+
+ BOX_SHADOW_DEFAULT_VARIANT1: "rgba(0, 0, 0, 0.25)",
+ BOX_SHADOW_DEFAULT_VARIANT2: "rgba(0, 0, 0, 0.25)",
+ BOX_SHADOW_DEFAULT_VARIANT3: "rgba(0, 0, 0, 0.5)",
+ BOX_SHADOW_DEFAULT_VARIANT4: "rgba(0, 0, 0, 0.25)",
+ BOX_SHADOW_DEFAULT_VARIANT5: "rgba(0, 0, 0, 0.25)",
SELECT_DISABLED: "#ced9e080",
};
export type Color = typeof Colors[keyof typeof Colors];
diff --git a/app/client/src/constants/DefaultTheme.tsx b/app/client/src/constants/DefaultTheme.tsx
index 735cba2e18..02fec91873 100644
--- a/app/client/src/constants/DefaultTheme.tsx
+++ b/app/client/src/constants/DefaultTheme.tsx
@@ -571,6 +571,134 @@ type ColorType = {
overlayColor: string;
button: {
disabledText: ShadeColor;
+ boxShadow: {
+ default: {
+ variant1: Color;
+ variant2: Color;
+ variant3: Color;
+ variant4: Color;
+ variant5: Color;
+ };
+ };
+ disabled: {
+ bgColor: Color;
+ textColor: Color;
+ };
+ /**
+ * PRIMARY style
+ */
+ primary: {
+ solid: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ outline: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ ghost: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor?: Color;
+ };
+ };
+ /**
+ * WARNING style
+ */
+ warning: {
+ solid: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ outline: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ ghost: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor?: Color;
+ };
+ };
+ /**
+ * DANGER style
+ */
+ danger: {
+ solid: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ outline: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ ghost: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor?: Color;
+ };
+ };
+ /**
+ * INFO style
+ */
+ info: {
+ solid: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ outline: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ ghost: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor?: Color;
+ };
+ };
+ /**
+ * SECONDARY style
+ */
+ secondary: {
+ solid: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ outline: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor: Color;
+ };
+ ghost: {
+ bgColor?: Color;
+ borderColor?: Color;
+ hoverColor: Color;
+ textColor?: Color;
+ };
+ };
};
tertiary: buttonVariant;
info: buttonVariant;
@@ -1296,6 +1424,94 @@ export const dark: ColorType = {
},
button: {
disabledText: darkShades[6],
+ boxShadow: {
+ default: {
+ variant1: Colors.BOX_SHADOW_DEFAULT_VARIANT1,
+ variant2: Colors.BOX_SHADOW_DEFAULT_VARIANT2,
+ variant3: Colors.BOX_SHADOW_DEFAULT_VARIANT3,
+ variant4: Colors.BOX_SHADOW_DEFAULT_VARIANT4,
+ variant5: Colors.BOX_SHADOW_DEFAULT_VARIANT5,
+ },
+ },
+ disabled: {
+ bgColor: Colors.DARK_GRAY,
+ textColor: Colors.WHITE,
+ },
+ primary: {
+ solid: {
+ bgColor: Colors.GREEN,
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.GREEN,
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_OUTLINE_HOVER,
+ textColor: Colors.GREEN,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_GHOST_HOVER,
+ },
+ },
+ warning: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ hoverColor: Colors.ICON_BUTTON_WARNING_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ hoverColor: Colors.ICON_BUTTON_WARNING_OUTLINE_HOVER,
+ textColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_WARNING_GHOST_HOVER,
+ },
+ },
+ danger: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ hoverColor: Colors.ICON_BUTTON_DANGER_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ hoverColor: Colors.ICON_BUTTON_DANGER_NO_SOLID_HOVER,
+ textColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_DANGER_NO_SOLID_HOVER,
+ },
+ },
+ info: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_INFO_SOLID,
+ hoverColor: Colors.ICON_BUTTON_INFO_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_INFO_SOLID,
+ hoverColor: Colors.ICON_BUTTON_INFO_NO_SOLID_HOVER,
+ textColor: Colors.ICON_BUTTON_INFO_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_INFO_NO_SOLID_HOVER,
+ },
+ },
+ secondary: {
+ solid: {
+ bgColor: Colors.GRAY,
+ hoverColor: Colors.CHARCOAL,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.GRAY,
+ hoverColor: Colors.Gallery,
+ textColor: Colors.GRAY,
+ },
+ ghost: {
+ hoverColor: Colors.MERCURY,
+ },
+ },
},
tertiary: {
main: "#D4D4D4",
@@ -1771,6 +1987,94 @@ export const light: ColorType = {
},
button: {
disabledText: lightShades[6],
+ boxShadow: {
+ default: {
+ variant1: Colors.BOX_SHADOW_DEFAULT_VARIANT1,
+ variant2: Colors.BOX_SHADOW_DEFAULT_VARIANT2,
+ variant3: Colors.BOX_SHADOW_DEFAULT_VARIANT3,
+ variant4: Colors.BOX_SHADOW_DEFAULT_VARIANT4,
+ variant5: Colors.BOX_SHADOW_DEFAULT_VARIANT5,
+ },
+ },
+ disabled: {
+ bgColor: Colors.DARK_GRAY,
+ textColor: Colors.WHITE,
+ },
+ primary: {
+ solid: {
+ bgColor: Colors.GREEN,
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.GREEN,
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_OUTLINE_HOVER,
+ textColor: Colors.GREEN,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_PRIMARY_GHOST_HOVER,
+ },
+ },
+ warning: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ hoverColor: Colors.ICON_BUTTON_WARNING_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ hoverColor: Colors.ICON_BUTTON_WARNING_OUTLINE_HOVER,
+ textColor: Colors.ICON_BUTTON_WARNING_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_WARNING_GHOST_HOVER,
+ },
+ },
+ danger: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ hoverColor: Colors.ICON_BUTTON_DANGER_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ hoverColor: Colors.ICON_BUTTON_DANGER_NO_SOLID_HOVER,
+ textColor: Colors.ICON_BUTTON_DANGER_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_DANGER_NO_SOLID_HOVER,
+ },
+ },
+ info: {
+ solid: {
+ bgColor: Colors.ICON_BUTTON_INFO_SOLID,
+ hoverColor: Colors.ICON_BUTTON_INFO_SOLID_HOVER,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.ICON_BUTTON_INFO_SOLID,
+ hoverColor: Colors.ICON_BUTTON_INFO_NO_SOLID_HOVER,
+ textColor: Colors.ICON_BUTTON_INFO_SOLID,
+ },
+ ghost: {
+ hoverColor: Colors.ICON_BUTTON_INFO_NO_SOLID_HOVER,
+ },
+ },
+ secondary: {
+ solid: {
+ bgColor: Colors.GRAY,
+ hoverColor: Colors.CHARCOAL,
+ textColor: Colors.WHITE,
+ },
+ outline: {
+ borderColor: Colors.GRAY,
+ hoverColor: Colors.Gallery,
+ textColor: Colors.GRAY,
+ },
+ ghost: {
+ hoverColor: Colors.MERCURY,
+ },
+ },
},
tertiary: {
main: "#716E6E",
diff --git a/app/client/src/constants/HelpConstants.ts b/app/client/src/constants/HelpConstants.ts
index 4c8d820754..e9bb2bed17 100644
--- a/app/client/src/constants/HelpConstants.ts
+++ b/app/client/src/constants/HelpConstants.ts
@@ -135,6 +135,10 @@ export const HelpMap = {
path: "/widget-reference/menu-button",
searchKey: "Menu Button",
},
+ ICON_BUTTON_WIDGET: {
+ path: "/widget-reference/icon-button",
+ searchKey: "Icon Button",
+ },
};
export const HelpBaseURL = "https://docs.appsmith.com";
diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx
index d4e552acc8..eadc95421c 100644
--- a/app/client/src/constants/WidgetConstants.tsx
+++ b/app/client/src/constants/WidgetConstants.tsx
@@ -32,6 +32,7 @@ export enum WidgetTypes {
IFRAME_WIDGET = "IFRAME_WIDGET",
DIVIDER_WIDGET = "DIVIDER_WIDGET",
MENU_BUTTON_WIDGET = "MENU_BUTTON_WIDGET",
+ ICON_BUTTON_WIDGET = "ICON_BUTTON_WIDGET",
}
export type WidgetType = keyof typeof WidgetTypes;
diff --git a/app/client/src/icons/ControlIcons.tsx b/app/client/src/icons/ControlIcons.tsx
index 7dd974aee9..2b4a0d01bf 100644
--- a/app/client/src/icons/ControlIcons.tsx
+++ b/app/client/src/icons/ControlIcons.tsx
@@ -50,6 +50,15 @@ import { ReactComponent as DividerCapAllIcon } from "assets/icons/control/divide
import { ReactComponent as TrendingFlat } from "assets/icons/ads/trending-flat.svg";
import { ReactComponent as AlignLeftIcon } from "assets/icons/control/align_left.svg";
import { ReactComponent as AlignRightIcon } from "assets/icons/control/align_right.svg";
+import { ReactComponent as BorderRadiusSharpIcon } from "assets/icons/control/border-radius-sharp.svg";
+import { ReactComponent as BorderRadiusRoundedIcon } from "assets/icons/control/border-radius-rounded.svg";
+import { ReactComponent as BorderRadiusCircleIcon } from "assets/icons/control/border-radius-circle.svg";
+import { ReactComponent as BoxShadowNoneIcon } from "assets/icons/control/box-shadow-none.svg";
+import { ReactComponent as BoxShadowVariant1Icon } from "assets/icons/control/box-shadow-variant1.svg";
+import { ReactComponent as BoxShadowVariant2Icon } from "assets/icons/control/box-shadow-variant2.svg";
+import { ReactComponent as BoxShadowVariant3Icon } from "assets/icons/control/box-shadow-variant3.svg";
+import { ReactComponent as BoxShadowVariant4Icon } from "assets/icons/control/box-shadow-variant4.svg";
+import { ReactComponent as BoxShadowVariant5Icon } from "assets/icons/control/box-shadow-variant5.svg";
import PlayIcon from "assets/icons/control/play-icon.png";
/* eslint-disable react/display-name */
@@ -316,6 +325,51 @@ export const ControlIcons: {
),
+ BORDER_RADIUS_SHARP: (props: IconProps) => (
+
+
+
+ ),
+ BORDER_RADIUS_ROUNDED: (props: IconProps) => (
+
+
+
+ ),
+ BORDER_RADIUS_CIRCLE: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_NONE: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_VARIANT1: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_VARIANT2: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_VARIANT3: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_VARIANT4: (props: IconProps) => (
+
+
+
+ ),
+ BOX_SHADOW_VARIANT5: (props: IconProps) => (
+
+
+
+ ),
};
export type ControlIconName = keyof typeof ControlIcons;
diff --git a/app/client/src/icons/WidgetIcons.tsx b/app/client/src/icons/WidgetIcons.tsx
index edc10b14a5..daadae1486 100644
--- a/app/client/src/icons/WidgetIcons.tsx
+++ b/app/client/src/icons/WidgetIcons.tsx
@@ -27,6 +27,7 @@ import { ReactComponent as RatingIcon } from "assets/icons/widget/rating.svg";
import { ReactComponent as EmbedIcon } from "assets/icons/widget/embed.svg";
import { ReactComponent as DividerIcon } from "assets/icons/widget/divider.svg";
import { ReactComponent as MenuButtonIcon } from "assets/icons/widget/menu-button.svg";
+import { ReactComponent as IconButtonIcon } from "assets/icons/widget/icon-button.svg";
/* eslint-disable react/display-name */
@@ -173,6 +174,11 @@ export const WidgetIcons: {
),
+ ICON_BUTTON_WIDGET: (props: IconProps) => (
+
+
+
+ ),
};
export type WidgetIcon = typeof WidgetIcons[keyof typeof WidgetIcons];
diff --git a/app/client/src/mockResponses/WidgetConfigResponse.tsx b/app/client/src/mockResponses/WidgetConfigResponse.tsx
index a0198c3b54..07ffca4c65 100644
--- a/app/client/src/mockResponses/WidgetConfigResponse.tsx
+++ b/app/client/src/mockResponses/WidgetConfigResponse.tsx
@@ -1,3 +1,5 @@
+import { IconNames } from "@blueprintjs/icons";
+
import { WidgetConfigReducerState } from "reducers/entityReducers/widgetConfigReducer";
import { WidgetProps } from "widgets/BaseWidget";
import moment from "moment-timezone";
@@ -9,6 +11,13 @@ import { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReduc
import { getDynamicBindings } from "utils/DynamicBindingUtils";
import { Colors } from "constants/Colors";
import FileDataTypes from "widgets/FileDataTypes";
+import {
+ ButtonBorderRadiusTypes,
+ ButtonBoxShadowTypes,
+ ButtonStyleTypes,
+ ButtonVariantTypes,
+} from "components/designSystems/appsmith/IconButtonComponent";
+
/*
********************************{Grid Density Migration}*********************************
*/
@@ -1244,6 +1253,19 @@ const WidgetConfigResponse: WidgetConfigReducerState = {
columns: 4 * GRID_DENSITY_MIGRATION_V1,
widgetName: "MenuButton",
},
+ [WidgetTypes.ICON_BUTTON_WIDGET]: {
+ iconName: IconNames.PLUS,
+ borderRadius: ButtonBorderRadiusTypes.CIRCLE,
+ boxShadow: ButtonBoxShadowTypes.NONE,
+ buttonStyle: ButtonStyleTypes.PRIMARY,
+ buttonVariant: ButtonVariantTypes.SOLID,
+ isDisabled: false,
+ isVisible: true,
+ rows: 1 * GRID_DENSITY_MIGRATION_V1,
+ columns: 1 * GRID_DENSITY_MIGRATION_V1,
+ widgetName: "IconButton",
+ version: 1,
+ },
},
configVersion: 1,
};
diff --git a/app/client/src/mockResponses/WidgetSidebarResponse.tsx b/app/client/src/mockResponses/WidgetSidebarResponse.tsx
index 9dd925c8d2..a4b5e0941a 100644
--- a/app/client/src/mockResponses/WidgetSidebarResponse.tsx
+++ b/app/client/src/mockResponses/WidgetSidebarResponse.tsx
@@ -130,6 +130,11 @@ const WidgetSidebarResponse: WidgetCardProps[] = [
widgetCardName: "Menu Button",
key: generateReactKey(),
},
+ {
+ type: "ICON_BUTTON_WIDGET",
+ widgetCardName: "Icon Button",
+ key: generateReactKey(),
+ },
];
export default WidgetSidebarResponse;
diff --git a/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx b/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx
index 594b26ede5..074afe53c6 100644
--- a/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx
+++ b/app/client/src/reducers/entityReducers/widgetConfigReducer.tsx
@@ -34,6 +34,7 @@ import { DividerWidgetProps } from "widgets/DividerWidget";
import { RateWidgetProps } from "widgets/RateWidget";
import { IframeWidgetProps } from "widgets/IframeWidget";
import { MenuButtonWidgetProps } from "widgets/MenuButtonWidget";
+import { IconButtonWidgetProps } from "widgets/IconButtonWidget";
const initialState: WidgetConfigReducerState = WidgetConfigResponse;
@@ -92,6 +93,7 @@ export interface WidgetConfigReducerState {
RATE_WIDGET: Partial & WidgetConfigProps;
IFRAME_WIDGET: Partial & WidgetConfigProps;
MENU_BUTTON_WIDGET: Partial & WidgetConfigProps;
+ ICON_BUTTON_WIDGET: Partial & WidgetConfigProps;
};
configVersion: number;
}
diff --git a/app/client/src/utils/WidgetRegistry.tsx b/app/client/src/utils/WidgetRegistry.tsx
index f2c56bcb88..2b5aa30836 100644
--- a/app/client/src/utils/WidgetRegistry.tsx
+++ b/app/client/src/utils/WidgetRegistry.tsx
@@ -123,6 +123,10 @@ import MenuButtonWidget, {
MenuButtonWidgetProps,
ProfiledMenuButtonWidget,
} from "widgets/MenuButtonWidget";
+import IconButtonWidget, {
+ IconButtonWidgetProps,
+ ProfiledIconButtonWidget,
+} from "widgets/IconButtonWidget";
export default class WidgetBuilderRegistry {
static registerWidgetBuilders() {
@@ -538,5 +542,18 @@ export default class WidgetBuilderRegistry {
MenuButtonWidget.getMetaPropertiesMap(),
MenuButtonWidget.getPropertyPaneConfig(),
);
+
+ WidgetFactory.registerWidgetBuilder(
+ WidgetTypes.ICON_BUTTON_WIDGET,
+ {
+ buildWidget(widgetData: IconButtonWidgetProps): JSX.Element {
+ return ;
+ },
+ },
+ IconButtonWidget.getDerivedPropertiesMap(),
+ IconButtonWidget.getDefaultPropertiesMap(),
+ IconButtonWidget.getMetaPropertiesMap(),
+ IconButtonWidget.getPropertyPaneConfig(),
+ );
}
}
diff --git a/app/client/src/utils/autocomplete/EntityDefinitions.ts b/app/client/src/utils/autocomplete/EntityDefinitions.ts
index cd15ce6bc0..c61457f913 100644
--- a/app/client/src/utils/autocomplete/EntityDefinitions.ts
+++ b/app/client/src/utils/autocomplete/EntityDefinitions.ts
@@ -287,6 +287,12 @@ export const entityDefinitions = {
isVisible: isVisible,
label: "string",
},
+ ICON_BUTTON_WIDGET: {
+ "!doc":
+ "Icon button widget is just an icon, along with all other button properties.",
+ "!url": "https://docs.appsmith.com/widget-reference/icon-button",
+ isVisible: isVisible,
+ },
};
export const GLOBAL_DEFS = {
diff --git a/app/client/src/widgets/IconButtonWidget.tsx b/app/client/src/widgets/IconButtonWidget.tsx
new file mode 100644
index 0000000000..643dbca427
--- /dev/null
+++ b/app/client/src/widgets/IconButtonWidget.tsx
@@ -0,0 +1,236 @@
+import * as React from "react";
+import * as Sentry from "@sentry/react";
+import { IconName } from "@blueprintjs/icons";
+
+import BaseWidget, { WidgetProps, WidgetState } from "./BaseWidget";
+import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
+import { ValidationTypes } from "constants/WidgetValidation";
+import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
+
+import IconButtonComponent, {
+ ButtonBorderRadius,
+ ButtonBoxShadow,
+ ButtonStyle,
+ ButtonVariant,
+} from "components/designSystems/appsmith/IconButtonComponent";
+
+export interface IconButtonWidgetProps extends WidgetProps {
+ iconName?: IconName;
+ buttonStyle: ButtonStyle;
+ buttonVariant: ButtonVariant;
+ borderRadius: ButtonBorderRadius;
+ boxShadow: ButtonBoxShadow;
+ boxShadowColor: string;
+ isDisabled: boolean;
+ isVisible: boolean;
+ onClick?: string;
+}
+
+class IconButtonWidget extends BaseWidget {
+ static getPropertyPaneConfig() {
+ return [
+ {
+ sectionName: "General",
+ children: [
+ {
+ propertyName: "iconName",
+ label: "Icon",
+ helpText: "Sets the icon to be used for the icon button",
+ controlType: "ICON_SELECT",
+ isBindProperty: false,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.TEXT },
+ },
+ {
+ propertyName: "buttonStyle",
+ label: "Button Style",
+ controlType: "DROP_DOWN",
+ helpText: "Sets the style of the icon button",
+ options: [
+ {
+ label: "Primary",
+ value: "PRIMARY",
+ },
+ {
+ label: "Warning",
+ value: "WARNING",
+ },
+ {
+ label: "Danger",
+ value: "DANGER",
+ },
+ {
+ label: "Info",
+ value: "INFO",
+ },
+ {
+ label: "Secondary",
+ value: "SECONDARY",
+ },
+ ],
+ isBindProperty: false,
+ isTriggerProperty: false,
+ },
+ {
+ propertyName: "buttonVariant",
+ label: "Button Variant",
+ controlType: "DROP_DOWN",
+ helpText: "Sets the variant of the icon button",
+ options: [
+ {
+ label: "Solid",
+ value: "SOLID",
+ },
+ {
+ label: "Outline",
+ value: "OUTLINE",
+ },
+ {
+ label: "Ghost",
+ value: "GHOST",
+ },
+ ],
+ isBindProperty: false,
+ isTriggerProperty: false,
+ },
+ {
+ propertyName: "borderRadius",
+ label: "Border Radius",
+ helpText:
+ "Rounds the corners of the icon button's outer border edge",
+ controlType: "BORDER_RADIUS_OPTIONS",
+ isBindProperty: false,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.TEXT,
+ params: {
+ allowedValues: ["CIRCLE", "SHARP", "ROUNDED"],
+ },
+ },
+ },
+ {
+ propertyName: "boxShadow",
+ label: "Box Shadow",
+ helpText:
+ "Enables you to cast a drop shadow from the frame of the widget",
+ controlType: "BOX_SHADOW_OPTIONS",
+ isBindProperty: false,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.TEXT,
+ params: {
+ allowedValues: [
+ "NONE",
+ "VARIANT1",
+ "VARIANT2",
+ "VARIANT3",
+ "VARIANT4",
+ "VARIANT5",
+ ],
+ },
+ },
+ },
+ {
+ propertyName: "boxShadowColor",
+ helpText: "Sets the shadow color of the widget",
+ label: "Shadow Color",
+ controlType: "COLOR_PICKER",
+ isBindProperty: false,
+ isTriggerProperty: false,
+ },
+ {
+ propertyName: "isDisabled",
+ helpText: "Disables input to the widget",
+ label: "Disabled",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.BOOLEAN },
+ },
+ {
+ propertyName: "isVisible",
+ helpText: "Controls the visibility of the widget",
+ label: "Visible",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.BOOLEAN },
+ },
+ ],
+ },
+ {
+ sectionName: "Actions",
+ children: [
+ {
+ helpText: "Triggers an action when the button is clicked",
+ propertyName: "onClick",
+ label: "onClick",
+ controlType: "ACTION_SELECTOR",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: true,
+ },
+ ],
+ },
+ ];
+ }
+
+ getPageView() {
+ const {
+ borderRadius,
+ boxShadow,
+ boxShadowColor,
+ buttonStyle,
+ buttonVariant,
+ iconName,
+ isDisabled,
+ isVisible,
+ widgetId,
+ } = this.props;
+
+ return (
+
+ );
+ }
+
+ getWidgetType(): WidgetType {
+ return WidgetTypes.ICON_BUTTON_WIDGET;
+ }
+
+ handleClick = () => {
+ const { onClick } = this.props;
+
+ if (onClick) {
+ super.executeAction({
+ triggerPropertyName: "onClick",
+ dynamicString: onClick,
+ event: {
+ type: EventType.ON_CLICK,
+ },
+ });
+ }
+ };
+}
+
+export default IconButtonWidget;
+export const ProfiledIconButtonWidget = Sentry.withProfiler(IconButtonWidget);