feat: WDS icon button widget integration (#27928)
## Description Adds WDSIconButton Widget. #### PR fixes following issue(s) Fixes #27538 > if no issue exists, please create an issue and ask the maintainers about this first > > #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [ ] Manual - [ ] JUnit - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [ ] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [ ] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed --------- Co-authored-by: Pawan Kumar <pawan.stardust@gmail.com>
This commit is contained in:
parent
8b5269fef1
commit
3ea74ec78e
|
|
@ -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",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
||||
|
|
|
|||
|
|
@ -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 <BIcon icon={iconName} />;
|
||||
});
|
||||
|
||||
return (
|
||||
<Tooltip tooltip={tooltip}>
|
||||
<IconButton icon={icon} {...rest} />
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export * from "./propertyPaneConfig";
|
||||
export { autocompleteConfig } from "./autocompleteConfig";
|
||||
export { defaultsConfig } from "./defaultsConfig";
|
||||
export { metaConfig } from "./metaConfig";
|
||||
export { settersConfig } from "./settersConfig";
|
||||
|
|
@ -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"],
|
||||
};
|
||||
|
|
@ -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 },
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
export { propertyPaneContentConfig } from "./contentConfig";
|
||||
export { propertyPaneStyleConfig } from "./styleConfig";
|
||||
|
|
@ -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,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
export const settersConfig = {
|
||||
__setters: {
|
||||
setVisibility: {
|
||||
path: "isVisible",
|
||||
type: "boolean",
|
||||
},
|
||||
setDisabled: {
|
||||
path: "isDisabled",
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
};
|
||||
3
app/client/src/widgets/wds/WDSIconButtonWidget/icon.svg
Normal file
3
app/client/src/widgets/wds/WDSIconButtonWidget/icon.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 23.0001C18.0751 23.0001 23 18.0752 23 12.0001C23 5.92494 18.0751 1.00006 12 1.00006C5.92487 1.00006 1 5.92494 1 12.0001C1 18.0752 5.92487 23.0001 12 23.0001ZM13.0001 11V6.50007H11V11H6.00001V13.0001H11V18.0001H13.0001V13.0001H17.5001V11H13.0001Z" fill="#4C5664"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 420 B |
3
app/client/src/widgets/wds/WDSIconButtonWidget/index.tsx
Normal file
3
app/client/src/widgets/wds/WDSIconButtonWidget/index.tsx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import { WDSIconButtonWidget } from "./widget";
|
||||
|
||||
export { WDSIconButtonWidget };
|
||||
113
app/client/src/widgets/wds/WDSIconButtonWidget/widget/index.tsx
Normal file
113
app/client/src/widgets/wds/WDSIconButtonWidget/widget/index.tsx
Normal file
|
|
@ -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 (
|
||||
<IconButtonComponent
|
||||
color={this.props.buttonColor}
|
||||
iconName={this.props.iconName}
|
||||
isDisabled={this.props.isDisabled}
|
||||
isLoading={this.state.isLoading}
|
||||
key={this.props.widgetId}
|
||||
onPress={onPress}
|
||||
tooltip={this.props.tooltip}
|
||||
variant={this.props.buttonVariant}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export { WDSIconButtonWidget };
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user