diff --git a/public/rich-components/button-bar-group.svg b/public/rich-components/button-bar-group.svg
new file mode 100644
index 00000000..ebb58963
--- /dev/null
+++ b/public/rich-components/button-bar-group.svg
@@ -0,0 +1,13 @@
+
\ No newline at end of file
diff --git a/src/common/components/front-rich-components/buttonBar.tsx b/src/common/components/front-rich-components/buttonBar.tsx
new file mode 100644
index 00000000..942a9f66
--- /dev/null
+++ b/src/common/components/front-rich-components/buttonBar.tsx
@@ -0,0 +1,100 @@
+import { ShapeSizeRestrictions } from '@/core/model';
+import { forwardRef, useMemo } from 'react';
+import { Group, Rect, Text } from 'react-konva';
+import { ShapeProps } from '../front-components/shape.model';
+import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes/shape-restrictions';
+
+const horizontalMenuShapeSizeRestrictions: ShapeSizeRestrictions = {
+ minWidth: 75,
+ minHeight: 25,
+ maxWidth: -1,
+ maxHeight: 100,
+ defaultWidth: 200,
+ defaultHeight: 50,
+};
+
+export const getButtonBarShapeSizeRestrictions = (): ShapeSizeRestrictions =>
+ horizontalMenuShapeSizeRestrictions;
+
+export const ButtonBarShape = forwardRef(
+ (
+ { x, y, width, height, id, onSelected, text, otherProps, ...shapeProps },
+ ref
+ ) => {
+ const menuElements: string[] = text.split('\n');
+ const numberOfItems = menuElements.length;
+ const minItemWidth = 100;
+ const itemSpacing = 20;
+ const totalWidth = Math.max(
+ minItemWidth * numberOfItems + itemSpacing * (numberOfItems + 1),
+ width
+ );
+ const { width: restrictedWidth, height: restrictedHeight } =
+ fitSizeToShapeSizeRestrictions(
+ horizontalMenuShapeSizeRestrictions,
+ totalWidth,
+ height
+ );
+ const totalMargins = restrictedWidth - itemSpacing * (numberOfItems + 1);
+ const itemWidth = totalMargins / numberOfItems;
+
+ const textColor = useMemo(
+ () => otherProps?.textColor ?? 'black',
+ [otherProps?.textColor]
+ );
+ const backgroundColor = useMemo(
+ () => otherProps?.backgroundColor ?? 'white',
+ [otherProps?.backgroundColor]
+ );
+ const strokeColor = useMemo(
+ () => otherProps?.stroke ?? 'black',
+ [otherProps?.stroke]
+ );
+ const strokeStyle = useMemo(
+ () => otherProps?.strokeStyle ?? [],
+ [otherProps?.strokeStyle]
+ );
+
+ return (
+ onSelected(id, 'horizontal-menu')}
+ >
+
+
+ {menuElements.map((e: string, index: number) => (
+
+
+
+ ))}
+
+ );
+ }
+);
+
+export default ButtonBarShape;
diff --git a/src/common/components/front-rich-components/index.ts b/src/common/components/front-rich-components/index.ts
index 9d2360dc..2982da60 100644
--- a/src/common/components/front-rich-components/index.ts
+++ b/src/common/components/front-rich-components/index.ts
@@ -11,3 +11,4 @@ export * from './calendar/calendar';
export * from './table/table';
export * from './modal/modal';
export * from './appBar';
+export * from './buttonBar';
diff --git a/src/core/model/index.ts b/src/core/model/index.ts
index 278f6728..8d825876 100644
--- a/src/core/model/index.ts
+++ b/src/core/model/index.ts
@@ -58,7 +58,8 @@ export type ShapeType =
| 'verticalScrollBar'
| 'horizontalScrollBar'
| 'modal'
- | 'appBar';
+ | 'appBar'
+ | 'buttonBar';
export const ShapeDisplayName: Record = {
combobox: 'Combobox',
@@ -108,6 +109,7 @@ export const ShapeDisplayName: Record = {
verticalScrollBar: 'Vertical Scroll Bar',
modal: 'Modal',
appBar: 'AppBar',
+ buttonBar: 'Button Bar',
};
export type EditType = 'input' | 'textarea' | 'imageupload';
diff --git a/src/pods/canvas/canvas.model.ts b/src/pods/canvas/canvas.model.ts
index 272cb308..92bdde7f 100644
--- a/src/pods/canvas/canvas.model.ts
+++ b/src/pods/canvas/canvas.model.ts
@@ -57,6 +57,7 @@ import {
getTableSizeRestrictions,
getModalShapeSizeRestrictions,
getAppBarShapeSizeRestrictions,
+ getButtonBarShapeSizeRestrictions,
} from '@/common/components/front-rich-components';
import {
getHeading1SizeRestrictions,
@@ -169,6 +170,8 @@ export const getSizeRestrictionFromShape = (
return getModalShapeSizeRestrictions();
case 'appBar':
return getAppBarShapeSizeRestrictions();
+ case 'buttonBar':
+ return getButtonBarShapeSizeRestrictions();
default:
console.warn(
`** Shape ${shapeType} has not defined default size, check getDefaultSizeFromShape helper function`
@@ -223,6 +226,7 @@ const doesShapeAllowInlineEdition = (shapeType: ShapeType): boolean => {
case 'table':
case 'modal':
case 'appBar':
+ case 'buttonBar':
return true;
default:
return false;
@@ -252,6 +256,7 @@ const generateTypeOfTransformer = (shapeType: ShapeType): string[] => {
case 'smalltext':
case 'horizontalScrollBar':
case 'appBar':
+ case 'buttonBar':
return ['middle-left', 'middle-right'];
case 'verticalScrollBar':
return ['top-center', 'bottom-center'];
@@ -317,6 +322,8 @@ const generateDefaultTextValue = (shapeType: ShapeType): string | undefined => {
return 'Alert\nWarning: The action you are about to perform may affect existing data. Are you sure you want to proceed? Once confirmed, this action cannot be undone.\nConfirm,Cancel';
case 'appBar':
return 'AppBar';
+ case 'buttonBar':
+ return 'Button 1\nButton 2\nButton 3';
default:
return undefined;
}
@@ -337,6 +344,7 @@ const getShapeEditInlineType = (shapeType: ShapeType): EditType | undefined => {
case 'table':
case 'modal':
case 'appBar':
+ case 'buttonBar':
return 'textarea';
break;
case 'image':
@@ -366,6 +374,7 @@ export const generateDefaultOtherProps = (
case 'datepickerinput':
case 'timepickerinput':
case 'modal':
+ case 'buttonBar':
return {
stroke: BASIC_SHAPE.DEFAULT_STROKE_COLOR,
backgroundColor: BASIC_SHAPE.DEFAULT_FILL_BACKGROUND,
diff --git a/src/pods/canvas/shape-renderer/index.tsx b/src/pods/canvas/shape-renderer/index.tsx
index 605e1ed5..e400d239 100644
--- a/src/pods/canvas/shape-renderer/index.tsx
+++ b/src/pods/canvas/shape-renderer/index.tsx
@@ -36,6 +36,7 @@ import {
renderVerticalMenuShape,
renderTable,
renderModal,
+ renderButtonBar,
} from './simple-rich-components';
import {
renderDiamond,
@@ -158,6 +159,8 @@ export const renderShapeComponent = (
return renderModal(shape, shapeRenderedProps);
case 'appBar':
return renderAppBar(shape, shapeRenderedProps);
+ case 'buttonBar':
+ return renderButtonBar(shape, shapeRenderedProps);
default:
return renderNotFound(shape, shapeRenderedProps);
}
diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/button-bar.renderer.tsx b/src/pods/canvas/shape-renderer/simple-rich-components/button-bar.renderer.tsx
new file mode 100644
index 00000000..be08c6d9
--- /dev/null
+++ b/src/pods/canvas/shape-renderer/simple-rich-components/button-bar.renderer.tsx
@@ -0,0 +1,33 @@
+import { ButtonBarShape } from '@/common/components/front-rich-components/buttonBar';
+import { ShapeRendererProps } from '../model';
+import { ShapeModel } from '@/core/model';
+
+export const renderButtonBar = (
+ shape: ShapeModel,
+ shapeRenderedProps: ShapeRendererProps
+) => {
+ const { handleSelected, shapeRefs, handleDragEnd, handleTransform } =
+ shapeRenderedProps;
+
+ return (
+
+ );
+};
diff --git a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts
index f7d2b070..08bdae97 100644
--- a/src/pods/canvas/shape-renderer/simple-rich-components/index.ts
+++ b/src/pods/canvas/shape-renderer/simple-rich-components/index.ts
@@ -11,3 +11,4 @@ export * from './calendar.renderer';
export * from './table.renderer';
export * from './modal.renderer';
export * from './appBar.renderer';
+export * from './button-bar.renderer';
diff --git a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts
index 846672d2..910a4079 100644
--- a/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts
+++ b/src/pods/rich-components-gallery/rich-components-gallery-data/index.ts
@@ -20,4 +20,5 @@ export const mockRichComponentsCollection: ItemInfo[] = [
{ thumbnailSrc: '/rich-components/table.svg', type: 'table' },
{ thumbnailSrc: '/rich-components/modal.svg', type: 'modal' },
{ thumbnailSrc: '/rich-components/appBar.svg', type: 'appBar' },
+ { thumbnailSrc: '/rich-components/button-bar-group.svg', type: 'buttonBar' },
];