Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`<BoolButton /> > it renders ChoiceButton with default props 1`] = `
<DocumentFragment>
<div
class="MuiToggleButtonGroup-root MuiToggleButtonGroup-horizontal MuiToggleButtonGroup-fullWidth css-scf8o0-MuiToggleButtonGroup-root"
role="group"
>
<button
aria-pressed="false"
class="MuiButtonBase-root MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedHorizontal MuiToggleButton-root MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-firstButton css-6n663-MuiButtonBase-root-MuiToggleButton-root"
tabindex="0"
type="button"
value="0"
>
Item 1
</button>
<button
aria-pressed="false"
class="MuiButtonBase-root MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedHorizontal MuiToggleButton-root MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-lastButton css-6n663-MuiButtonBase-root-MuiToggleButton-root"
tabindex="0"
type="button"
value="1"
>
Item 2
</button>
</div>
</DocumentFragment>
`;

exports[`<BoolButton /> > pass props to widget 1`] = `
<DocumentFragment>
<div
class="MuiToggleButtonGroup-root MuiToggleButtonGroup-vertical MuiToggleButtonGroup-fullWidth css-wsp9w8-MuiToggleButtonGroup-root"
role="group"
>
<button
aria-pressed="true"
class="MuiButtonBase-root Mui-disabled MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedVertical Mui-disabled MuiToggleButton-root Mui-selected Mui-disabled MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-firstButton css-17lpp1x-MuiButtonBase-root-MuiToggleButton-root"
disabled=""
tabindex="-1"
type="button"
value="0"
>
Choice
</button>
<button
aria-pressed="false"
class="MuiButtonBase-root Mui-disabled MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedVertical Mui-disabled MuiToggleButton-root Mui-disabled MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-middleButton css-17lpp1x-MuiButtonBase-root-MuiToggleButton-root"
disabled=""
tabindex="-1"
type="button"
value="1"
>
Option
</button>
<button
aria-pressed="false"
class="MuiButtonBase-root Mui-disabled MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedVertical Mui-disabled MuiToggleButton-root Mui-disabled MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-middleButton css-17lpp1x-MuiButtonBase-root-MuiToggleButton-root"
disabled=""
tabindex="-1"
type="button"
value="2"
>
Setting
</button>
<button
aria-pressed="false"
class="MuiButtonBase-root Mui-disabled MuiToggleButtonGroup-grouped MuiToggleButtonGroup-groupedVertical Mui-disabled MuiToggleButton-root Mui-disabled MuiToggleButton-fullWidth MuiToggleButton-sizeMedium MuiToggleButton-standard MuiToggleButtonGroup-lastButton css-17lpp1x-MuiButtonBase-root-MuiToggleButton-root"
disabled=""
tabindex="-1"
type="button"
value="3"
>
Custom
</button>
</div>
</DocumentFragment>
`;
16 changes: 0 additions & 16 deletions src/ui/widgets/ChoiceButton/choiceButton.module.css

This file was deleted.

23 changes: 9 additions & 14 deletions src/ui/widgets/ChoiceButton/choiceButton.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ describe("<BoolButton />", (): void => {
const choiceButtonProps = {
value: null
};
const { getAllByRole } = render(ChoiceButtonRenderer(choiceButtonProps));
const { getAllByRole, asFragment } = render(
ChoiceButtonRenderer(choiceButtonProps)
);
const buttons = getAllByRole("button") as Array<HTMLButtonElement>;

expect(buttons[0].textContent).toEqual("Item 1");
expect(buttons[1].textContent).toEqual("Item 2");
expect(buttons[0].style.height).toEqual("43px");
expect(buttons[1].style.width).toEqual("46px");
expect(buttons[0].style.backgroundColor).toEqual("rgb(210, 210, 210)");
expect(buttons[1].style.fontSize).toEqual("0.875rem");
expect(asFragment()).toMatchSnapshot();
});

test("pass props to widget", (): void => {
Expand All @@ -36,19 +35,15 @@ describe("<BoolButton />", (): void => {
itemsFromPv: false,
enabled: false
};
const { getAllByRole } = render(ChoiceButtonRenderer(choiceButtonProps));
const { getAllByRole, asFragment } = render(
ChoiceButtonRenderer(choiceButtonProps)
);
const buttons = getAllByRole("button") as Array<HTMLButtonElement>;

expect(buttons.length).toEqual(4);
// First button is selected therefore different color and box shadow
expect(buttons[0].style.boxShadow).toEqual(
"inset 0px 23px 35px 0px rgba(0,0,0,0.3)"
);
expect(buttons[0].style.backgroundColor).toEqual("rgb(10, 60, 40)");
expect(buttons[2].textContent).toEqual("Setting");
expect(buttons[3].style.cursor).toEqual("not-allowed");
expect(buttons[3].style.height).toEqual("31px");
expect(buttons[3].style.backgroundColor).toEqual("rgb(20, 20, 200)");
expect(buttons[3]).toHaveProperty("disabled", true);
expect(asFragment()).toMatchSnapshot();
});

test("pass props to widget, using itemsFromPv", (): void => {
Expand Down
140 changes: 84 additions & 56 deletions src/ui/widgets/ChoiceButton/choiceButton.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { CSSProperties, useEffect, useState } from "react";
import React, { useEffect, useState } from "react";

import { Widget } from "../widget";
import { PVComponent, PVWidgetPropType } from "../widgetProps";
Expand All @@ -13,10 +13,14 @@ import {
StringPropOpt
} from "../propTypes";
import { DType } from "../../../types/dtypes";
import classes from "./choiceButton.module.css";
import { Color } from "../../../types/color";
import { writePv } from "../../hooks/useSubscription";
import { Font } from "../../../types/font";
import {
ToggleButton as MuiToggleButton,
styled,
ToggleButtonGroup
} from "@mui/material";
import { diamondTheme } from "../../../diamondTheme";
import { Color } from "../../../types";

const ChoiceButtonProps = {
pvName: StringPropOpt,
Expand All @@ -38,6 +42,28 @@ export type ChoiceButtonComponentProps = InferWidgetProps<
> &
PVComponent;

const ToggleButton = styled(MuiToggleButton)({
"&.MuiToggleButton-root": {
textTransform: "none",
overflow: "hidden",
display: "block",
padding: 0,
lineHeight: 1,
alignItems: "center",
justifyContent: "center",
textOverflow: "ellipsis",
wordWrap: "break-word"
},
"&.Mui-disabled": {
cursor: "not-allowed",
pointerEvents: "all !important"
},
"&.MuiToggleButtonGroup-grouped": {
border: "1px solid !important",
borderColor: "#000000"
}
});

export const ChoiceButtonComponent = (
props: ChoiceButtonComponentProps
): JSX.Element => {
Expand All @@ -50,11 +76,11 @@ export const ChoiceButtonComponent = (
pvName,
items = ["Item 1", "Item 2"],
horizontal = true,
backgroundColor = Color.fromRgba(210, 210, 210),
foregroundColor = Color.BLACK,
selectedColor = Color.fromRgba(200, 200, 200),
font = new Font(14)
foregroundColor = diamondTheme.palette.primary.contrastText,
backgroundColor = diamondTheme.palette.primary.main,
selectedColor = Color.fromRgba(200, 200, 200)
} = props;
const font = props.font?.css() ?? diamondTheme.typography;
const [selected, setSelected] = useState(value?.getDoubleValue());

// Use items from file, unless itemsFRomPv set
Expand All @@ -74,61 +100,63 @@ export const ChoiceButtonComponent = (
// Number of buttons to create
const numButtons = options.length || 1;
// Determine width and height of buttons if horizontal or vertically placed
const buttonHeight = horizontal ? height : height / numButtons - 4;
const buttonWidth = horizontal ? width / numButtons - 4 : width;

const style: CSSProperties = {
height: buttonHeight,
width: buttonWidth,
textAlignLast: "center",
cursor: enabled ? "default" : "not-allowed",
color: foregroundColor?.toString(),
...font.css()
};
const buttonHeight = horizontal ? height : height / numButtons;
const buttonWidth = horizontal ? width / numButtons : width;

function handleClick(index: number) {
const handleChange = (
event: React.MouseEvent<HTMLElement>,
newSelect: number
) => {
// Write to PV
if (pvName) {
writePv(pvName, new DType({ doubleValue: index }));
writePv(pvName, new DType({ doubleValue: newSelect }));
}
}

// Iterate over items to create buttons
const elements: Array<JSX.Element> = [];
options.forEach((item: string | null | undefined, idx: number) => {
if (typeof item === "string") {
elements.push(
<button
className={classes.ChoiceButton}
disabled={enabled ? false : true}
onClick={() => handleClick(idx)}
style={{
...style,
backgroundColor:
selected === idx
? selectedColor.toString()
: backgroundColor.toString(),
boxShadow:
selected === idx
? `inset 0px ${Math.round(height / 6)}px ${Math.round(
height / 4
)}px 0px rgba(0,0,0,0.3)`
: "none"
}}
key={item}
>
{item}
</button>
);
}
});
setSelected(newSelect);
};

return (
<div
style={{ display: "flex", flexDirection: horizontal ? "row" : "column" }}
<ToggleButtonGroup
exclusive
fullWidth={true}
disabled={!enabled}
value={selected}
onChange={handleChange}
orientation={horizontal ? "horizontal" : "vertical"}
sx={{
display: "flex",
height: "100%",
width: "100%"
}}
>
{elements}
</div>
{options
.filter(item => typeof item === "string")
.map((item, idx) => (
<ToggleButton
key={item}
value={idx}
sx={{
width: buttonWidth,
height: buttonHeight,
fontFamily: font,
color: foregroundColor.toString(),
backgroundColor: backgroundColor.toString(),
"&.Mui-selected": {
backgroundColor: selectedColor.toString()
},
"&.Mui-selected:hover": {
backgroundColor: selectedColor.toString(),
opacity: 0.6
},
"&:hover": {
backgroundColor: backgroundColor.toString(),
opacity: 0.6
}
}}
>
{item}
</ToggleButton>
))}
</ToggleButtonGroup>
);
};

Expand Down