diff --git a/app/client/src/components/wds/constants.ts b/app/client/src/components/wds/constants.ts
index c2b66497b0..9093278fee 100644
--- a/app/client/src/components/wds/constants.ts
+++ b/app/client/src/components/wds/constants.ts
@@ -6,4 +6,5 @@ export const WDS_V2_WIDGET_MAP = {
TEXT_WIDGET: "WDS_TEXT_WIDGET",
TABLE_WIDGET_V2: "WDS_TABLE_WIDGET",
BUTTON_GROUP_WIDGET: "WDS_BUTTON_GROUP_WIDGET",
+ CHECKBOX_GROUP_WIDGET: "WDS_CHECKBOX_GROUP_WIDGET",
};
diff --git a/app/client/src/widgets/index.ts b/app/client/src/widgets/index.ts
index e5c98808d7..71aa13d2de 100644
--- a/app/client/src/widgets/index.ts
+++ b/app/client/src/widgets/index.ts
@@ -65,6 +65,7 @@ import { WDSTextWidget } from "./wds/WDSTextWidget";
import type BaseWidget from "./BaseWidget";
import { WDSTableWidget } from "./wds/WDSTableWidget";
import { WDSButtonGroupWidget } from "./wds/WDSButtonGroupWidget";
+import { WDSCheckboxGroupWidget } from "./wds/WDSCheckboxGroupWidget";
const Widgets = [
CanvasWidget,
@@ -123,6 +124,7 @@ const Widgets = [
WDSTextWidget,
WDSTableWidget,
WDSButtonGroupWidget,
+ WDSCheckboxGroupWidget,
//Deprecated Widgets
InputWidget,
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/index.tsx b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/index.tsx
new file mode 100644
index 0000000000..300a2973d0
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/index.tsx
@@ -0,0 +1,30 @@
+import React from "react";
+import { CheckboxGroup, Checkbox } from "@design-system/widgets";
+import type { CheckboxGroupComponentProps } from "./types";
+import type { OptionProps } from "../widget/types";
+
+export const CheckboxGroupComponent = (props: CheckboxGroupComponentProps) => {
+ return (
+
+ {props.options.map((option: OptionProps, index: number) => {
+ return (
+
+ {option.label}
+
+ );
+ })}
+
+ );
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/types.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/types.ts
new file mode 100644
index 0000000000..f38db10c6d
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/component/types.ts
@@ -0,0 +1,19 @@
+import type { CheckboxGroupWidgetProps, OptionProps } from "../widget/types";
+
+export interface CheckboxGroupComponentProps
+ extends Pick<
+ CheckboxGroupWidgetProps,
+ | "defaultSelectedValues"
+ | "isDisabled"
+ | "isRequired"
+ | "isValid"
+ | "labelPosition"
+ | "labelText"
+ | "onCheckChange"
+ | "options"
+ | "orientation"
+ | "widgetId"
+ > {
+ onChange: (value: string[]) => void;
+ selectedValues: OptionProps["value"][];
+}
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/anvilConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/anvilConfig.ts
new file mode 100644
index 0000000000..3e259eae1a
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/anvilConfig.ts
@@ -0,0 +1,10 @@
+import type { AnvilConfig } from "WidgetProvider/constants";
+
+export const anvilConfig: AnvilConfig = {
+ widgetSize: {
+ maxHeight: {},
+ maxWidth: {},
+ minHeight: { base: "42px" },
+ minWidth: { base: "130px" },
+ },
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/autocompleteConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/autocompleteConfig.ts
new file mode 100644
index 0000000000..5836c4c3d4
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/autocompleteConfig.ts
@@ -0,0 +1,12 @@
+import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils";
+
+export const autocompleteConfig = {
+ "!doc":
+ "Checkbox group widget allows users to easily configure multiple checkboxes together.",
+ "!url": "https://docs.appsmith.com/widget-reference/checkbox-group",
+ isVisible: DefaultAutocompleteDefinitions.isVisible,
+ isDisabled: "bool",
+ isValid: "bool",
+ options: "[$__dropdownOption__$]",
+ selectedValues: "[string]",
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/defaultsConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/defaultsConfig.ts
new file mode 100644
index 0000000000..f6b52854c3
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/defaultsConfig.ts
@@ -0,0 +1,19 @@
+export const defaultsConfig = {
+ rows: 10,
+ columns: 20,
+ animateLoading: true,
+ options: [
+ { label: "Blue", value: "BLUE" },
+ { label: "Green", value: "GREEN" },
+ { label: "Red", value: "RED" },
+ ],
+ defaultSelectedValues: ["BLUE"],
+ isDisabled: false,
+ isRequired: false,
+ isVisible: true,
+ labelPosition: "left",
+ labelText: "Label",
+ orientation: "vertical",
+ version: 1,
+ widgetName: "CheckboxGroup",
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/featuresConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/featuresConfig.ts
new file mode 100644
index 0000000000..60a677c66c
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/featuresConfig.ts
@@ -0,0 +1,6 @@
+export const featuresConfig = {
+ dynamicHeight: {
+ sectionIndex: 3,
+ active: true,
+ },
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/index.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/index.ts
new file mode 100644
index 0000000000..47a4551c1e
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/index.ts
@@ -0,0 +1,7 @@
+export * from "./propertyPaneConfig";
+export { metaConfig } from "./metaConfig";
+export { settersConfig } from "./settersConfig";
+export { defaultsConfig } from "./defaultsConfig";
+export { featuresConfig } from "./featuresConfig";
+export { autocompleteConfig } from "./autocompleteConfig";
+export { anvilConfig } from "./anvilConfig";
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/metaConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/metaConfig.ts
new file mode 100644
index 0000000000..6bbcaf024e
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/metaConfig.ts
@@ -0,0 +1,9 @@
+import IconSVG from "../icon.svg";
+import { WIDGET_TAGS } from "constants/WidgetConstants";
+
+export const metaConfig = {
+ name: "Checkbox Group",
+ iconSVG: IconSVG,
+ tags: [WIDGET_TAGS.TOGGLES],
+ needsMeta: true,
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/contentConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/contentConfig.ts
new file mode 100644
index 0000000000..34cdb7bc3e
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/contentConfig.ts
@@ -0,0 +1,172 @@
+import { ValidationTypes } from "constants/WidgetValidation";
+import { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
+import { defaultSelectedValuesValidation } from "./validations";
+import { AutocompleteDataType } from "utils/autocomplete/AutocompleteDataType";
+
+export const propertyPaneContentConfig = [
+ {
+ sectionName: "Data",
+ children: [
+ {
+ helpText: "Displays a list of unique checkbox options",
+ propertyName: "options",
+ label: "Options",
+ controlType: "OPTION_INPUT",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.ARRAY,
+ params: {
+ default: [],
+ unique: ["value"],
+ children: {
+ type: ValidationTypes.OBJECT,
+ params: {
+ required: true,
+ allowedKeys: [
+ {
+ name: "label",
+ type: ValidationTypes.TEXT,
+ params: {
+ default: "",
+ required: true,
+ },
+ },
+ {
+ name: "value",
+ type: ValidationTypes.TEXT,
+ params: {
+ default: "",
+ },
+ },
+ ],
+ },
+ },
+ },
+ },
+ evaluationSubstitutionType: EvaluationSubstitutionType.SMART_SUBSTITUTE,
+ },
+ {
+ helpText: "Sets the values of the options checked by default",
+ propertyName: "defaultSelectedValues",
+ label: "Default selected values",
+ placeholderText: '["apple", "orange"]',
+ controlType: "INPUT_TEXT",
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.FUNCTION,
+ params: {
+ fn: defaultSelectedValuesValidation,
+ expected: {
+ type: "String or Array",
+ example: `apple | ["apple", "orange"]`,
+ autocompleteDataType: AutocompleteDataType.STRING,
+ },
+ },
+ },
+ },
+ ],
+ },
+ {
+ sectionName: "Label",
+ children: [
+ {
+ helpText: "Sets the label text of the widget",
+ propertyName: "labelText",
+ label: "Text",
+ controlType: "INPUT_TEXT",
+ placeholderText: "Enter label text",
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.TEXT },
+ },
+ {
+ helpText: "Sets the label position of the widget",
+ propertyName: "labelPosition",
+ label: "Position",
+ controlType: "ICON_TABS",
+ fullWidth: true,
+ options: [
+ { label: "Left", value: "left" },
+ { label: "Right", value: "right" },
+ ],
+ isBindProperty: false,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.TEXT },
+ },
+ ],
+ },
+ {
+ sectionName: "Validations",
+ children: [
+ {
+ propertyName: "isRequired",
+ label: "Required",
+ helpText: "Makes input to the widget mandatory",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.BOOLEAN,
+ },
+ },
+ ],
+ },
+ {
+ sectionName: "General",
+ children: [
+ {
+ propertyName: "isVisible",
+ label: "Visible",
+ helpText: "Controls the visibility of the widget",
+ controlType: "SWITCH",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: {
+ type: ValidationTypes.BOOLEAN,
+ },
+ },
+ {
+ propertyName: "isDisabled",
+ label: "Disabled",
+ controlType: "SWITCH",
+ helpText: "Disables input to this widget",
+ 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 },
+ },
+ ],
+ },
+ {
+ sectionName: "Events",
+ children: [
+ {
+ helpText: "When the check state is changed",
+ propertyName: "onCheckChange",
+ label: "onCheckChange",
+ controlType: "ACTION_SELECTOR",
+ isJSConvertible: true,
+ isBindProperty: true,
+ isTriggerProperty: true,
+ },
+ ],
+ },
+];
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/index.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/index.ts
new file mode 100644
index 0000000000..4273f74125
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/index.ts
@@ -0,0 +1,2 @@
+export { propertyPaneContentConfig } from "./contentConfig";
+export { propertyPaneStyleConfig } from "./styleConfig";
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/styleConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/styleConfig.ts
new file mode 100644
index 0000000000..37a70b3aa2
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/styleConfig.ts
@@ -0,0 +1,30 @@
+import { ValidationTypes } from "constants/WidgetValidation";
+
+export const propertyPaneStyleConfig = [
+ {
+ sectionName: "General",
+ children: [
+ {
+ helpText: "Controls widget orientation",
+ propertyName: "orientation",
+ label: "Orientation",
+ controlType: "ICON_TABS",
+ fullWidth: true,
+ options: [
+ {
+ label: "Horizontal",
+ value: "horizontal",
+ },
+ {
+ label: "Vertical",
+ value: "vertical",
+ },
+ ],
+ defaultValue: "vertical",
+ isBindProperty: true,
+ isTriggerProperty: false,
+ validation: { type: ValidationTypes.TEXT },
+ },
+ ],
+ },
+];
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/defaultSelectedValuesValidation.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/defaultSelectedValuesValidation.ts
new file mode 100644
index 0000000000..d10dc9dda0
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/defaultSelectedValuesValidation.ts
@@ -0,0 +1,30 @@
+import type { ValidationResponse } from "constants/WidgetValidation";
+
+export function defaultSelectedValuesValidation(
+ value: unknown,
+): ValidationResponse {
+ let values: string[] = [];
+
+ if (typeof value === "string") {
+ try {
+ values = JSON.parse(value);
+ if (!Array.isArray(values)) {
+ throw new Error();
+ }
+ } catch {
+ values = value.length ? value.split(",") : [];
+ if (values.length > 0) {
+ values = values.map((_v: string) => _v.trim());
+ }
+ }
+ }
+
+ if (Array.isArray(value)) {
+ values = Array.from(new Set(value));
+ }
+
+ return {
+ isValid: true,
+ parsed: values,
+ };
+}
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/index.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/index.ts
new file mode 100644
index 0000000000..f1b59d04b6
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/propertyPaneConfig/validations/index.ts
@@ -0,0 +1 @@
+export * from "./defaultSelectedValuesValidation";
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/settersConfig.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/settersConfig.ts
new file mode 100644
index 0000000000..2a036bc6b0
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/config/settersConfig.ts
@@ -0,0 +1,21 @@
+export const settersConfig = {
+ __setters: {
+ setVisibility: {
+ path: "isVisible",
+ type: "boolean",
+ },
+ setDisabled: {
+ path: "isDisabled",
+ type: "boolean",
+ },
+ setRequired: {
+ path: "isRequired",
+ type: "boolean",
+ },
+ setSelectedOptions: {
+ path: "defaultSelectedValues",
+ type: "array",
+ accessor: "selectedValues",
+ },
+ },
+};
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/icon.svg b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/icon.svg
new file mode 100644
index 0000000000..a0a3a45d85
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/icon.svg
@@ -0,0 +1,7 @@
+
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/index.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/index.ts
new file mode 100644
index 0000000000..8a6bcdb377
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/index.ts
@@ -0,0 +1,3 @@
+import { WDSCheckboxGroupWidget } from "./widget";
+
+export { WDSCheckboxGroupWidget };
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/index.tsx b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/index.tsx
new file mode 100644
index 0000000000..ac4b064a3c
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/index.tsx
@@ -0,0 +1,127 @@
+import React from "react";
+import type { SetterConfig } from "entities/AppTheming";
+import type { DerivedPropertiesMap } from "WidgetProvider/factory";
+import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
+import { xor } from "lodash";
+import BaseWidget from "widgets/BaseWidget";
+import type { CheckboxGroupWidgetProps, OptionProps } from "./types";
+import type { WidgetState } from "widgets/BaseWidget";
+import type { AnvilConfig } from "WidgetProvider/constants";
+import { CheckboxGroupComponent } from "../component";
+import {
+ anvilConfig,
+ autocompleteConfig,
+ defaultsConfig,
+ featuresConfig,
+ metaConfig,
+ propertyPaneContentConfig,
+ propertyPaneStyleConfig,
+ settersConfig,
+} from "./../config";
+
+class WDSCheckboxGroupWidget extends BaseWidget<
+ CheckboxGroupWidgetProps,
+ WidgetState
+> {
+ static type = "WDS_CHECKBOX_GROUP_WIDGET";
+
+ static getConfig() {
+ return metaConfig;
+ }
+
+ static getFeatures() {
+ return featuresConfig;
+ }
+
+ static getDefaults() {
+ return defaultsConfig;
+ }
+
+ static getAutoLayoutConfig() {
+ return {};
+ }
+
+ static getAnvilConfig(): AnvilConfig | null {
+ return anvilConfig;
+ }
+
+ static getAutocompleteDefinitions() {
+ return autocompleteConfig;
+ }
+
+ static getSetterConfig(): SetterConfig {
+ return settersConfig;
+ }
+
+ static getPropertyPaneContentConfig() {
+ return propertyPaneContentConfig;
+ }
+
+ static getPropertyPaneStyleConfig() {
+ return propertyPaneStyleConfig;
+ }
+
+ static getDefaultPropertiesMap(): Record {
+ return {
+ selectedValues: "defaultSelectedValues",
+ };
+ }
+
+ static getDerivedPropertiesMap(): DerivedPropertiesMap {
+ return {
+ value: `{{this.selectedValues}}`,
+ isValid: `{{ this.isRequired ? !!this.selectedValues.length : true }}`,
+ };
+ }
+
+ static getMetaPropertiesMap(): Record {
+ return {
+ selectedValues: undefined,
+ isDirty: false,
+ };
+ }
+
+ componentDidUpdate(prevProps: CheckboxGroupWidgetProps) {
+ if (
+ xor(this.props.defaultSelectedValues, prevProps.defaultSelectedValues)
+ .length > 0 &&
+ this.props.isDirty
+ ) {
+ this.props.updateWidgetMetaProperty("isDirty", false);
+ }
+ }
+
+ handleChange = (selectedValues: OptionProps["value"][]) => {
+ if (!this.props.isDirty) {
+ this.props.updateWidgetMetaProperty("isDirty", true);
+ }
+
+ this.props.updateWidgetMetaProperty("selectedValues", selectedValues, {
+ triggerPropertyName: "onCheckChange",
+ dynamicString: this.props.onCheckChange,
+ event: {
+ type: EventType.ON_CHECKBOX_GROUP_SELECTION_CHANGE,
+ },
+ });
+ };
+
+ getWidgetView() {
+ return (
+
+ );
+ }
+}
+
+export { WDSCheckboxGroupWidget };
diff --git a/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/types.ts b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/types.ts
new file mode 100644
index 0000000000..7731d91772
--- /dev/null
+++ b/app/client/src/widgets/wds/WDSCheckboxGroupWidget/widget/types.ts
@@ -0,0 +1,19 @@
+import type { WidgetProps } from "widgets/BaseWidget";
+
+export interface OptionProps {
+ label?: string;
+ value: string;
+}
+
+export interface CheckboxGroupWidgetProps extends WidgetProps {
+ defaultSelectedValues?: OptionProps["value"][];
+ isDisabled: boolean;
+ isRequired?: boolean;
+ isValid?: boolean;
+ isVisible: boolean;
+ labelPosition: "left" | "right";
+ labelText?: string;
+ onCheckChange?: string;
+ options: OptionProps[];
+ orientation: "vertical" | "horizontal";
+}