feat: add close button to item control components

This commit is contained in:
Abhinav Kumar
2025-07-04 18:32:23 +05:30
parent 87a803b1a3
commit a808b8376f
4 changed files with 190 additions and 124 deletions

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Connector, connectorStyleOptions } from 'src/types';
import { Box, Slider, Select, MenuItem, TextField } from '@mui/material';
import { Box, Slider, Select, MenuItem, TextField, IconButton as MUIIconButton } from '@mui/material';
import { useConnector } from 'src/hooks/useConnector';
import { ColorSelector } from 'src/components/ColorSelector/ColorSelector';
import { useUiStateStore } from 'src/stores/uiStateStore';
@@ -8,6 +8,7 @@ import { useScene } from 'src/hooks/useScene';
import { ControlsContainer } from '../components/ControlsContainer';
import { Section } from '../components/Section';
import { DeleteButton } from '../components/DeleteButton';
import { Close as CloseIcon } from '@mui/icons-material';
interface Props {
id: string;
@@ -27,61 +28,77 @@ export const ConnectorControls = ({ id }: Props) => {
return (
<ControlsContainer>
<Section>
<TextField
label="Description"
value={connector.description}
onChange={(e) => {
updateConnector(connector.id, {
description: e.target.value as string
});
}}
/>
</Section>
<Section>
<ColorSelector
onChange={(color) => {
return updateConnector(connector.id, { color });
}}
activeColor={connector.color}
/>
</Section>
<Section title="Width">
<Slider
marks
step={10}
min={10}
max={30}
value={connector.width}
onChange={(e, newWidth) => {
updateConnector(connector.id, { width: newWidth as number });
}}
/>
</Section>
<Section title="Style">
<Select
value={connector.style}
onChange={(e) => {
updateConnector(connector.id, {
style: e.target.value as Connector['style']
});
<Box sx={{ position: 'relative' }}>
{/* Close button */}
<MUIIconButton
aria-label="Close"
onClick={() => uiStateActions.setItemControls(null)}
sx={{
position: 'absolute',
top: 8,
right: 8,
zIndex: 2,
}}
size="small"
>
{Object.values(connectorStyleOptions).map((style) => {
return <MenuItem value={style}>{style}</MenuItem>;
})}
</Select>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteConnector(connector.id);
<CloseIcon />
</MUIIconButton>
<Section>
<TextField
label="Description"
value={connector.description}
onChange={(e) => {
updateConnector(connector.id, {
description: e.target.value as string
});
}}
/>
</Box>
</Section>
</Section>
<Section>
<ColorSelector
onChange={(color) => {
return updateConnector(connector.id, { color });
}}
activeColor={connector.color}
/>
</Section>
<Section title="Width">
<Slider
marks
step={10}
min={10}
max={30}
value={connector.width}
onChange={(e, newWidth) => {
updateConnector(connector.id, { width: newWidth as number });
}}
/>
</Section>
<Section title="Style">
<Select
value={connector.style}
onChange={(e) => {
updateConnector(connector.id, {
style: e.target.value as Connector['style']
});
}}
>
{Object.values(connectorStyleOptions).map((style) => {
return <MenuItem value={style}>{style}</MenuItem>;
})}
</Select>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteConnector(connector.id);
}}
/>
</Box>
</Section>
</Box>
</ControlsContainer>
);
};

View File

@@ -1,8 +1,9 @@
import React, { useState, useCallback } from 'react';
import { Box, Stack, Button } from '@mui/material';
import { Box, Stack, Button, IconButton as MUIIconButton } from '@mui/material';
import {
ChevronRight as ChevronRightIcon,
ChevronLeft as ChevronLeftIcon
ChevronLeft as ChevronLeftIcon,
Close as CloseIcon
} from '@mui/icons-material';
import { useIconCategories } from 'src/hooks/useIconCategories';
import { useIcon } from 'src/hooks/useIcon';
@@ -50,11 +51,24 @@ export const NodeControls = ({ id }: Props) => {
<ControlsContainer>
<Box
sx={{
bgcolor: (theme) => {
return theme.customVars.customPalette.diagramBg;
}
bgcolor: (theme) => theme.customVars.customPalette.diagramBg,
position: 'relative',
}}
>
{/* Close button */}
<MUIIconButton
aria-label="Close"
onClick={() => uiStateActions.setItemControls(null)}
sx={{
position: 'absolute',
top: 8,
right: 8,
zIndex: 2,
}}
size="small"
>
<CloseIcon />
</MUIIconButton>
<Section sx={{ py: 2 }}>
<Stack
direction="row"
@@ -120,3 +134,4 @@ export const NodeControls = ({ id }: Props) => {
</ControlsContainer>
);
};

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Box } from '@mui/material';
import { Box, IconButton as MUIIconButton } from '@mui/material';
import { useRectangle } from 'src/hooks/useRectangle';
import { ColorSelector } from 'src/components/ColorSelector/ColorSelector';
import { useUiStateStore } from 'src/stores/uiStateStore';
@@ -7,6 +7,7 @@ import { useScene } from 'src/hooks/useScene';
import { ControlsContainer } from '../components/ControlsContainer';
import { Section } from '../components/Section';
import { DeleteButton } from '../components/DeleteButton';
import { Close as CloseIcon } from '@mui/icons-material';
interface Props {
id: string;
@@ -26,24 +27,40 @@ export const RectangleControls = ({ id }: Props) => {
return (
<ControlsContainer>
<Section>
<ColorSelector
onChange={(color) => {
updateRectangle(rectangle.id, { color });
<Box sx={{ position: 'relative' }}>
{/* Close button */}
<MUIIconButton
aria-label="Close"
onClick={() => uiStateActions.setItemControls(null)}
sx={{
position: 'absolute',
top: 8,
right: 8,
zIndex: 2,
}}
activeColor={rectangle.color}
/>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteRectangle(rectangle.id);
size="small"
>
<CloseIcon />
</MUIIconButton>
<Section>
<ColorSelector
onChange={(color) => {
updateRectangle(rectangle.id, { color });
}}
activeColor={rectangle.color}
/>
</Box>
</Section>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteRectangle(rectangle.id);
}}
/>
</Box>
</Section>
</Box>
</ControlsContainer>
);
};

View File

@@ -5,9 +5,10 @@ import {
TextField,
ToggleButton,
ToggleButtonGroup,
Slider
Slider,
IconButton as MUIIconButton
} from '@mui/material';
import { TextRotationNone as TextRotationNoneIcon } from '@mui/icons-material';
import { TextRotationNone as TextRotationNoneIcon, Close as CloseIcon } from '@mui/icons-material';
import { useTextBox } from 'src/hooks/useTextBox';
import { useUiStateStore } from 'src/stores/uiStateStore';
import { getIsoProjectionCss } from 'src/utils';
@@ -34,59 +35,75 @@ export const TextBoxControls = ({ id }: Props) => {
return (
<ControlsContainer>
<Section>
<TextField
value={textBox.content}
onChange={(e) => {
updateTextBox(textBox.id, { content: e.target.value as string });
}}
/>
</Section>
<Section title="Text size">
<Slider
marks
step={0.3}
min={0.3}
max={0.9}
value={textBox.fontSize}
onChange={(e, newSize) => {
updateTextBox(textBox.id, { fontSize: newSize as number });
}}
/>
</Section>
<Section title="Alignment">
<ToggleButtonGroup
value={textBox.orientation}
exclusive
onChange={(e, orientation) => {
if (textBox.orientation === orientation || orientation === null)
return;
updateTextBox(textBox.id, { orientation });
<Box sx={{ position: 'relative' }}>
{/* Close button */}
<MUIIconButton
aria-label="Close"
onClick={() => uiStateActions.setItemControls(null)}
sx={{
position: 'absolute',
top: 8,
right: 8,
zIndex: 2,
}}
size="small"
>
<ToggleButton value={ProjectionOrientationEnum.X}>
<TextRotationNoneIcon sx={{ transform: getIsoProjectionCss() }} />
</ToggleButton>
<ToggleButton value={ProjectionOrientationEnum.Y}>
<TextRotationNoneIcon
sx={{
transform: `scale(-1, 1) ${getIsoProjectionCss()} scale(-1, 1)`
}}
/>
</ToggleButton>
</ToggleButtonGroup>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteTextBox(textBox.id);
<CloseIcon />
</MUIIconButton>
<Section>
<TextField
value={textBox.content}
onChange={(e) => {
updateTextBox(textBox.id, { content: e.target.value as string });
}}
/>
</Box>
</Section>
</Section>
<Section title="Text size">
<Slider
marks
step={0.3}
min={0.3}
max={0.9}
value={textBox.fontSize}
onChange={(e, newSize) => {
updateTextBox(textBox.id, { fontSize: newSize as number });
}}
/>
</Section>
<Section title="Alignment">
<ToggleButtonGroup
value={textBox.orientation}
exclusive
onChange={(e, orientation) => {
if (textBox.orientation === orientation || orientation === null)
return;
updateTextBox(textBox.id, { orientation });
}}
>
<ToggleButton value={ProjectionOrientationEnum.X}>
<TextRotationNoneIcon sx={{ transform: getIsoProjectionCss() }} />
</ToggleButton>
<ToggleButton value={ProjectionOrientationEnum.Y}>
<TextRotationNoneIcon
sx={{
transform: `scale(-1, 1) ${getIsoProjectionCss()} scale(-1, 1)`
}}
/>
</ToggleButton>
</ToggleButtonGroup>
</Section>
<Section>
<Box>
<DeleteButton
onClick={() => {
uiStateActions.setItemControls(null);
deleteTextBox(textBox.id);
}}
/>
</Box>
</Section>
</Box>
</ControlsContainer>
);
};