diff --git a/app/client/src/components/wds/constants.ts b/app/client/src/components/wds/constants.ts
index c89ff8b026..ec7a5a8afb 100644
--- a/app/client/src/components/wds/constants.ts
+++ b/app/client/src/components/wds/constants.ts
@@ -2,6 +2,7 @@ export const WDS_V2_WIDGET_MAP = {
BUTTON_WIDGET: "WDS_BUTTON_WIDGET",
INPUT_WIDGET_V2: "WDS_INPUT_WIDGET",
CHECKBOX_WIDGET: "WDS_CHECKBOX_WIDGET",
+ ICON_BUTTON_WIDGET: "WDS_ICON_BUTTON_WIDGET",
TEXT_WIDGET: "WDS_TEXT_WIDGET",
TABLE_WIDGET_V2: "WDS_TABLE_WIDGET",
};
diff --git a/app/client/src/widgets/index.ts b/app/client/src/widgets/index.ts
index d022c05e2d..caf4172148 100644
--- a/app/client/src/widgets/index.ts
+++ b/app/client/src/widgets/index.ts
@@ -60,6 +60,7 @@ import ListWidgetV2 from "./ListWidgetV2";
import { WDSButtonWidget } from "./wds/WDSButtonWidget";
import { WDSInputWidget } from "./wds/WDSInputWidget";
import { WDSCheckboxWidget } from "./wds/WDSCheckboxWidget";
+import { WDSIconButtonWidget } from "./wds/WDSIconButtonWidget";
import { WDSTextWidget } from "./wds/WDSTextWidget";
import type BaseWidget from "./BaseWidget";
import { WDSTableWidget } from "./wds/WDSTableWidget";
@@ -117,6 +118,7 @@ const Widgets = [
WDSButtonWidget,
WDSInputWidget,
WDSCheckboxWidget,
+ WDSIconButtonWidget,
WDSTextWidget,
WDSTableWidget,
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/component/index.tsx b/app/client/src/widgets/wds/WDSIconButtonWidget/component/index.tsx
new file mode 100644
index 0000000000..e0def84118
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/component/index.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import { Icon as BIcon } from "@blueprintjs/core";
+import { IconButton, Tooltip } from "@design-system/widgets";
+import type { IconButtonComponentProps } from "./types";
+
+export const IconButtonComponent = (props: IconButtonComponentProps) => {
+ const { iconName, tooltip, ...rest } = props;
+ const icon =
+ iconName &&
+ (() => {
+ return ;
+ });
+
+ return (
+
+
+
+ );
+};
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/component/types.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/component/types.ts
new file mode 100644
index 0000000000..3af971afb3
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/component/types.ts
@@ -0,0 +1,16 @@
+import type { IconName } from "@blueprintjs/icons";
+import type { IconButtonProps } from "@design-system/widgets";
+
+export interface IconButtonComponentProps {
+ tooltip?: string;
+ visuallyDisabled?: boolean;
+ isLoading: boolean;
+ iconName?: IconName;
+ isDisabled?: boolean;
+ variant?: IconButtonProps["variant"];
+ color?: IconButtonProps["color"];
+ onPress?: IconButtonProps["onPress"];
+ minWidth?: number;
+ maxWidth?: number;
+ minHeight?: number;
+}
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/autocompleteConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/autocompleteConfig.ts
new file mode 100644
index 0000000000..c003ee9072
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/autocompleteConfig.ts
@@ -0,0 +1,8 @@
+import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
+
+export const autocompleteConfig = {
+ "!doc":
+ "Icon button widget is just an icon, along with all other button properties.",
+ "!url": "https://docs.appsmith.com/widget-reference/icon-button",
+ isVisible: DefaultAutocompleteDefinitions.isVisible,
+};
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/defaultsConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/defaultsConfig.ts
new file mode 100644
index 0000000000..1dee7795aa
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/defaultsConfig.ts
@@ -0,0 +1,19 @@
+import { BUTTON_VARIANTS, COLORS } from "@design-system/widgets";
+import { IconNames } from "@blueprintjs/icons";
+import { ResponsiveBehavior } from "layoutSystems/common/utils/constants";
+import { ICON_BUTTON_MIN_WIDTH } from "constants/minWidthConstants";
+
+export const defaultsConfig = {
+ iconName: IconNames.PLUS,
+ buttonVariant: BUTTON_VARIANTS.filled,
+ buttonColor: COLORS.accent,
+ isDisabled: false,
+ isVisible: true,
+ rows: 4,
+ columns: 4,
+ widgetName: "IconButton",
+ version: 1,
+ animateLoading: true,
+ responsiveBehavior: ResponsiveBehavior.Hug,
+ minWidth: ICON_BUTTON_MIN_WIDTH,
+};
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/index.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/index.ts
new file mode 100644
index 0000000000..3233e112d9
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/index.ts
@@ -0,0 +1,5 @@
+export * from "./propertyPaneConfig";
+export { autocompleteConfig } from "./autocompleteConfig";
+export { defaultsConfig } from "./defaultsConfig";
+export { metaConfig } from "./metaConfig";
+export { settersConfig } from "./settersConfig";
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/metaConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/metaConfig.ts
new file mode 100644
index 0000000000..fb74fc53cd
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/metaConfig.ts
@@ -0,0 +1,9 @@
+import IconSVG from "../icon.svg";
+import { WIDGET_TAGS } from "constants/WidgetConstants";
+
+export const metaConfig = {
+ name: "Icon button",
+ iconSVG: IconSVG,
+ tags: [WIDGET_TAGS.BUTTONS],
+ searchTags: ["click", "submit"],
+};
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/contentConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/contentConfig.ts
new file mode 100644
index 0000000000..32b563110a
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/contentConfig.ts
@@ -0,0 +1,87 @@
+import { ValidationTypes } from "constants/WidgetValidation";
+import { IconNames } from "@blueprintjs/icons";
+
+const ICON_NAMES = Object.keys(IconNames).map(
+ (name: string) => IconNames[name as keyof typeof IconNames],
+);
+
+export const propertyPaneContentConfig = [
+ {
+ sectionName: "Basic",
+ children: [
+ {
+ propertyName: "iconName",
+ label: "Icon",
+ helpText: "Sets the icon to be used for the icon button",
+ controlType: "ICON_SELECT",
+ defaultIconName: "plus",
+ hideNoneIcon: true,
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.TEXT,
+ params: {
+ allowedValues: ICON_NAMES,
+ default: IconNames.PLUS,
+ },
+ },
+ },
+ {
+ helpText: "when the button is clicked",
+ propertyName: "onClick",
+ label: "onClick",
+ controlType: "ACTION_SELECTOR",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: true,
+ },
+ ],
+ },
+ {
+ sectionName: "General",
+ children: [
+ {
+ helpText: "Show helper text with button on hover",
+ propertyName: "tooltip",
+ label: "Tooltip",
+ controlType: "INPUT_TEXT",
+ placeholderText: "Add Input Field",
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.TEXT },
+ },
+ {
+ propertyName: "isVisible",
+ helpText: "Controls the visibility of the widget",
+ label: "Visible",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.BOOLEAN },
+ },
+ {
+ propertyName: "isDisabled",
+ helpText: "Disables input to the widget",
+ label: "Disabled",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.BOOLEAN },
+ },
+ {
+ propertyName: "animateLoading",
+ label: "Animate loading",
+ controlType: "SWITCH",
+ helpText: "Controls the loading of the widget",
+ defaultValue: true,
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.BOOLEAN },
+ },
+ ],
+ },
+];
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/index.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/index.ts
new file mode 100644
index 0000000000..4273f74125
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/index.ts
@@ -0,0 +1,2 @@
+export { propertyPaneContentConfig } from "./contentConfig";
+export { propertyPaneStyleConfig } from "./styleConfig";
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/styleConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/styleConfig.ts
new file mode 100644
index 0000000000..34c2dd186f
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/propertyPaneConfig/styleConfig.ts
@@ -0,0 +1,53 @@
+import { capitalize } from "lodash";
+import { BUTTON_VARIANTS, COLORS } from "@design-system/widgets";
+import { ValidationTypes } from "constants/WidgetValidation";
+
+export const propertyPaneStyleConfig = [
+ {
+ sectionName: "General",
+ children: [
+ {
+ propertyName: "buttonVariant",
+ label: "Button variant",
+ controlType: "ICON_TABS",
+ fullWidth: true,
+ helpText: "Sets the variant of the button",
+ options: Object.values(BUTTON_VARIANTS).map((variant) => ({
+ label: capitalize(variant),
+ value: variant,
+ })),
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.TEXT,
+ params: {
+ allowedValues: Object.values(BUTTON_VARIANTS),
+ default: BUTTON_VARIANTS.filled,
+ },
+ },
+ },
+ {
+ propertyName: "buttonColor",
+ label: "Button color",
+ controlType: "DROP_DOWN",
+ fullWidth: true,
+ helpText: "Sets the semantic color of the button",
+ options: Object.values(COLORS).map((semantic) => ({
+ label: capitalize(semantic),
+ value: semantic,
+ })),
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.TEXT,
+ params: {
+ allowedValues: Object.values(COLORS),
+ default: COLORS.accent,
+ },
+ },
+ },
+ ],
+ },
+];
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/config/settersConfig.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/config/settersConfig.ts
new file mode 100644
index 0000000000..888f2f9bcb
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/config/settersConfig.ts
@@ -0,0 +1,12 @@
+export const settersConfig = {
+ __setters: {
+ setVisibility: {
+ path: "isVisible",
+ type: "boolean",
+ },
+ setDisabled: {
+ path: "isDisabled",
+ type: "boolean",
+ },
+ },
+};
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/icon.svg b/app/client/src/widgets/wds/WDSIconButtonWidget/icon.svg
new file mode 100644
index 0000000000..5a7a953e1a
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/icon.svg
@@ -0,0 +1,3 @@
+
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/index.tsx b/app/client/src/widgets/wds/WDSIconButtonWidget/index.tsx
new file mode 100644
index 0000000000..58186d0659
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/index.tsx
@@ -0,0 +1,3 @@
+import { WDSIconButtonWidget } from "./widget";
+
+export { WDSIconButtonWidget };
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/widget/index.tsx b/app/client/src/widgets/wds/WDSIconButtonWidget/widget/index.tsx
new file mode 100644
index 0000000000..cb14bfee36
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/widget/index.tsx
@@ -0,0 +1,113 @@
+import React from "react";
+import type { SetterConfig } from "entities/AppTheming";
+import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
+import BaseWidget from "widgets/BaseWidget";
+import {
+ metaConfig,
+ defaultsConfig,
+ autocompleteConfig,
+ propertyPaneContentConfig,
+ propertyPaneStyleConfig,
+ settersConfig,
+} from "./../config";
+import type { IconButtonWidgetProps, IconButtonWidgetState } from "./types";
+import { IconButtonComponent } from "../component";
+
+class WDSIconButtonWidget extends BaseWidget<
+ IconButtonWidgetProps,
+ IconButtonWidgetState
+> {
+ constructor(props: IconButtonWidgetProps) {
+ super(props);
+
+ this.state = {
+ isLoading: false,
+ };
+ }
+
+ static type = "WDS_ICON_BUTTON_WIDGET";
+
+ static getConfig() {
+ return metaConfig;
+ }
+
+ static getDefaults() {
+ return defaultsConfig;
+ }
+
+ static getAutoLayoutConfig() {
+ return {};
+ }
+
+ static getAutocompleteDefinitions() {
+ return autocompleteConfig;
+ }
+
+ static getPropertyPaneContentConfig() {
+ return propertyPaneContentConfig;
+ }
+
+ static getPropertyPaneStyleConfig() {
+ return propertyPaneStyleConfig;
+ }
+
+ static getSetterConfig(): SetterConfig {
+ return settersConfig;
+ }
+
+ hasOnClickAction = () => {
+ const { isDisabled, onClick } = this.props;
+
+ return Boolean(onClick && !isDisabled);
+ };
+
+ handleActionComplete = () => {
+ this.setState({
+ isLoading: false,
+ });
+ };
+
+ onButtonClick = () => {
+ const { onClick } = this.props;
+
+ if (onClick) {
+ this.setState({ isLoading: true });
+
+ super.executeAction({
+ triggerPropertyName: "onClick",
+ dynamicString: onClick,
+ event: {
+ type: EventType.ON_CLICK,
+ callback: this.handleActionComplete,
+ },
+ });
+
+ return;
+ }
+ };
+
+ getWidgetView() {
+ const onPress = (() => {
+ if (this.hasOnClickAction()) {
+ return this.onButtonClick;
+ }
+
+ return undefined;
+ })();
+
+ return (
+
+ );
+ }
+}
+
+export { WDSIconButtonWidget };
diff --git a/app/client/src/widgets/wds/WDSIconButtonWidget/widget/types.ts b/app/client/src/widgets/wds/WDSIconButtonWidget/widget/types.ts
new file mode 100644
index 0000000000..1bdd35bef7
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSIconButtonWidget/widget/types.ts
@@ -0,0 +1,16 @@
+import type { IconButtonProps } from "@design-system/widgets";
+import type { WidgetProps, WidgetState } from "widgets/BaseWidget";
+import type { IconName } from "@blueprintjs/icons";
+
+export interface IconButtonWidgetProps extends WidgetProps {
+ iconName: IconName;
+ buttonColor: IconButtonProps["color"];
+ buttonVariant: IconButtonProps["variant"];
+ isDisabled: boolean;
+ isVisible: boolean;
+ onClick?: string;
+}
+
+export interface IconButtonWidgetState extends WidgetState {
+ isLoading: boolean;
+}