Skip to content

Commit 8dc50d1

Browse files
committed
chore: updating code for selection controls for cleaner caption
1 parent 3777d4b commit 8dc50d1

16 files changed

Lines changed: 86 additions & 144 deletions

packages/pluggableWidgets/selection-controls-web/src/SelectionControls.editorConfig.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,10 @@ export function getProperties(
4545
...DATABASE_SOURCE_CONFIG
4646
]);
4747
if (["enumeration", "boolean"].includes(values.optionsSourceType)) {
48-
hidePropertiesIn(defaultProperties, values, [...ASSOCIATION_SOURCE_CONFIG]);
48+
hidePropertiesIn(defaultProperties, values, [
49+
"optionsSourceCustomContentType",
50+
...ASSOCIATION_SOURCE_CONFIG
51+
]);
4952
if (values.optionsSourceType === "boolean") {
5053
hidePropertiesIn(defaultProperties, values, ["attributeEnumeration"]);
5154
} else {

packages/pluggableWidgets/selection-controls-web/src/SelectionControls.editorPreview.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ export const preview = (props: SelectionControlsPreviewProps): ReactElement => {
1818
readOnlyStyle: props.readOnlyStyle,
1919
ariaRequired: dynamic(false),
2020
a11yConfig: {
21-
ariaLabels: {
22-
clearSelection: props.clearButtonAriaLabel,
23-
removeSelection: props.removeValueAriaLabel
24-
},
2521
a11yStatusMessage: {
2622
a11ySelectedValue: props.a11ySelectedValue,
2723
a11yOptionsAvailable: props.a11yOptionsAvailable,

packages/pluggableWidgets/selection-controls-web/src/SelectionControls.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ export default function SelectionControls(props: SelectionControlsContainerProps
2525
readOnlyStyle: props.readOnlyStyle,
2626
ariaRequired: props.ariaRequired,
2727
a11yConfig: {
28-
ariaLabels: {
29-
clearSelection: props.clearButtonAriaLabel?.value ?? "",
30-
removeSelection: props.removeValueAriaLabel?.value ?? ""
31-
},
3228
a11yStatusMessage: {
3329
a11ySelectedValue: props.a11ySelectedValue?.value ?? "",
3430
a11yOptionsAvailable: props.a11yOptionsAvailable?.value ?? "",

packages/pluggableWidgets/selection-controls-web/src/SelectionControls.xml

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -264,24 +264,6 @@
264264
<returnType type="Boolean" />
265265
</property>
266266
</propertyGroup>
267-
<propertyGroup caption="Aria labels">
268-
<property key="clearButtonAriaLabel" type="textTemplate" required="false">
269-
<caption>Clear selection button</caption>
270-
<description>Used to clear all selected values.</description>
271-
<translations>
272-
<translation lang="en_US">Clear selection</translation>
273-
<translation lang="nl_NL">Selectie wissen</translation>
274-
</translations>
275-
</property>
276-
<property key="removeValueAriaLabel" type="textTemplate" required="false">
277-
<caption>Remove value button</caption>
278-
<description>Used to remove individual selected values when using labels with multi-selection.</description>
279-
<translations>
280-
<translation lang="en_US">Remove value</translation>
281-
<translation lang="nl_NL">Waarde verwijderen</translation>
282-
</translations>
283-
</property>
284-
</propertyGroup>
285267
<propertyGroup caption="Accessibility status message ">
286268
<property key="a11ySelectedValue" type="textTemplate" required="false">
287269
<caption>Selected value</caption>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { createElement, PropsWithChildren, ReactElement } from "react";
2+
import { MouseEvent } from "react";
3+
4+
export interface CaptionContentProps extends PropsWithChildren {
5+
htmlFor?: string;
6+
onClick?: (e: MouseEvent) => void;
7+
}
8+
9+
export function CaptionContent(props: CaptionContentProps): ReactElement {
10+
const { htmlFor, children, onClick } = props;
11+
return createElement(htmlFor == null ? "span" : "label", {
12+
children,
13+
className: "widget-controls-caption-text",
14+
htmlFor,
15+
onClick: onClick
16+
? onClick
17+
: htmlFor
18+
? (e: MouseEvent) => {
19+
e.preventDefault();
20+
}
21+
: undefined
22+
});
23+
}

packages/pluggableWidgets/selection-controls-web/src/components/CheckboxSelection/CheckboxSelection.tsx

Lines changed: 2 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import classNames from "classnames";
22
import { ReactElement, createElement } from "react";
33
import { SelectionBaseProps, MultiSelector } from "../../helpers/types";
4+
import { CaptionContent } from "../CaptionContent";
45

56
export function CheckboxSelection({
67
selector,
@@ -42,7 +43,6 @@ export function CheckboxSelection({
4243
aria-required={ariaRequired?.value}
4344
>
4445
{options.map((optionId, index) => {
45-
const caption = selector.caption.get(optionId);
4646
const isSelected = currentIds.includes(optionId);
4747
const checkboxId = `${inputId}-checkbox-${index}`;
4848

@@ -63,38 +63,14 @@ export function CheckboxSelection({
6363
onChange={e => handleChange(optionId, e.target.checked)}
6464
aria-describedby={`${inputId}-description`}
6565
/>
66-
<label htmlFor={checkboxId} className="widget-selection-controls-checkbox-label">
67-
{selector.customContentType === "no"
68-
? caption
69-
: selector.caption.render(optionId, "options")}
70-
</label>
66+
<CaptionContent htmlFor={checkboxId}>{selector.caption.render(optionId)}</CaptionContent>
7167
</div>
7268
);
7369
})}
7470
{options.length === 0 && (
7571
<div className="widget-selection-controls-no-options">No options available</div>
7672
)}
7773
</div>
78-
79-
{/* Clear all button */}
80-
{/* {!isReadOnly && currentIds.length > 0 && (
81-
<button
82-
type="button"
83-
className="widget-selection-controls-clear-all"
84-
onClick={() => selector.setValue([])}
85-
aria-label={a11yConfig.ariaLabels.clearSelection}
86-
>
87-
Clear all selections
88-
</button>
89-
)} */}
90-
91-
{/* Accessibility status message */}
92-
{/* <div id={`${inputId}-description`} className="sr-only" aria-live="polite" aria-atomic="true">
93-
{currentIds.length > 0 &&
94-
`${a11yConfig.a11yStatusMessage.a11ySelectedValue} ${currentIds.map(id => selector.caption.get(id)).join(", ")}`}
95-
{` ${a11yConfig.a11yStatusMessage.a11yOptionsAvailable} ${options.length}`}
96-
{` ${a11yConfig.a11yStatusMessage.a11yInstructions}`}
97-
</div> */}
9874
</div>
9975
);
10076
}

packages/pluggableWidgets/selection-controls-web/src/components/RadioSelection/RadioSelection.tsx

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import classNames from "classnames";
22
import { ReactElement, createElement } from "react";
33
import { SelectionBaseProps, SingleSelector } from "../../helpers/types";
4+
import { CaptionContent } from "../CaptionContent";
45

56
export function RadioSelection({
67
selector,
@@ -41,7 +42,6 @@ export function RadioSelection({
4142
aria-required={ariaRequired?.value}
4243
>
4344
{options.map((optionId, index) => {
44-
const caption = selector.caption.get(optionId);
4545
const isSelected = currentId === optionId;
4646
const radioId = `${inputId}-radio-${index}`;
4747

@@ -63,25 +63,14 @@ export function RadioSelection({
6363
onChange={() => handleChange(optionId)}
6464
aria-describedby={`${inputId}-description`}
6565
/>
66-
<label htmlFor={radioId} className="widget-selection-controls-radio-label">
67-
{selector.customContentType === "no"
68-
? caption
69-
: selector.caption.render(optionId, "options")}
70-
</label>
66+
<CaptionContent htmlFor={radioId}>{selector.caption.render(optionId)}</CaptionContent>
7167
</div>
7268
);
7369
})}
7470
{options.length === 0 && (
7571
<div className="widget-selection-controls-no-options">No options available</div>
7672
)}
7773
</div>
78-
79-
{/* Accessibility status message */}
80-
{/* <div id={`${inputId}-description`} className="sr-only" aria-live="polite" aria-atomic="true">
81-
{currentId && `${a11yConfig.a11yStatusMessage.a11ySelectedValue} ${selector.caption.get(currentId)}`}
82-
{` ${a11yConfig.a11yStatusMessage.a11yOptionsAvailable} ${options.length}`}
83-
{` ${a11yConfig.a11yStatusMessage.a11yInstructions}`}
84-
</div> */}
8574
</div>
8675
);
8776
}

packages/pluggableWidgets/selection-controls-web/src/helpers/Association/AssociationSimpleCaptionsProvider.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DynamicValue, ListAttributeValue, ListExpressionValue, ListWidgetValue, ObjectItem } from "mendix";
2-
import { ReactNode, createElement } from "react";
2+
import { ReactNode } from "react";
33
import { OptionsSourceCustomContentTypeEnum } from "../../../typings/SelectionControlsProps";
44
import { CaptionsProvider } from "../types";
55

@@ -45,21 +45,22 @@ export class AssociationSimpleCaptionsProvider implements CaptionsProvider {
4545
return this.formatter.get(item).value || "";
4646
}
4747

48-
render(value: string | null, _placement?: "label" | "options", _htmlFor?: string): ReactNode {
48+
getCustomContent(value: string | null): ReactNode | null {
4949
if (value === null) {
50-
return <span className="widget-selection-controls-caption-text">{this.emptyCaption}</span>;
50+
return null;
5151
}
52-
5352
const item = this._objectsMap.get(value);
5453
if (!item) {
55-
return <span className="widget-selection-controls-caption-text"></span>;
54+
return null;
5655
}
5756

57+
return this.customContent?.get(item);
58+
}
59+
60+
render(value: string | null): ReactNode {
5861
if (this.customContentType === "yes" && this.customContent) {
59-
return this.customContent.get(item);
62+
return this.getCustomContent(value);
6063
}
61-
62-
const caption = this.formatter?.get(item).value || "";
63-
return <span className="widget-selection-controls-caption-text">{caption}</span>;
64+
return this.get(value);
6465
}
6566
}

packages/pluggableWidgets/selection-controls-web/src/helpers/Database/DatabaseCaptionsProvider.tsx

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { DynamicValue, ListAttributeValue, ListExpressionValue, ListWidgetValue, ObjectItem } from "mendix";
2-
import { ReactNode, createElement } from "react";
31
import { Big } from "big.js";
2+
import { DynamicValue, ListAttributeValue, ListExpressionValue, ListWidgetValue, ObjectItem } from "mendix";
3+
import { ReactNode } from "react";
44
import { OptionsSourceCustomContentTypeEnum } from "../../../typings/SelectionControlsProps";
55
import { CaptionsProvider } from "../types";
66

@@ -48,21 +48,22 @@ export class DatabaseCaptionsProvider implements CaptionsProvider {
4848
return this.formatter.get(item).value || "";
4949
}
5050

51-
render(value: string | null, _placement?: "label" | "options", _htmlFor?: string): ReactNode {
51+
getCustomContent(value: string | null): ReactNode | null {
5252
if (value === null) {
53-
return <span className="widget-selection-controls-caption-text">{this.emptyCaption}</span>;
53+
return null;
5454
}
55-
5655
const item = this._objectsMap.get(value);
5756
if (!item) {
58-
return <span className="widget-selection-controls-caption-text"></span>;
57+
return null;
5958
}
6059

60+
return this.customContent?.get(item);
61+
}
62+
63+
render(value: string | null): ReactNode {
6164
if (this.customContentType === "yes" && this.customContent) {
62-
return this.customContent.get(item);
65+
return this.getCustomContent(value);
6366
}
64-
65-
const caption = this.formatter?.get(item).value || "";
66-
return <span className="widget-selection-controls-caption-text">{caption}</span>;
67+
return this.get(value);
6768
}
6869
}

packages/pluggableWidgets/selection-controls-web/src/helpers/EnumBool/EnumAndBooleanSimpleCaptionsProvider.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DynamicValue, EditableValue } from "mendix";
2-
import { ReactNode, createElement } from "react";
2+
import { ReactNode } from "react";
33
import { CaptionsProvider } from "../types";
44

55
interface EnumAndBooleanSimpleCaptionsProviderProps {
@@ -29,8 +29,7 @@ export class EnumAndBooleanSimpleCaptionsProvider implements CaptionsProvider {
2929
return this.attr?.formatter.format(value) ?? "";
3030
}
3131

32-
render(value: string | null, _placement?: "label" | "options", _htmlFor?: string): ReactNode {
33-
const caption = this.get(value);
34-
return <span className="widget-selection-controls-caption-text">{caption}</span>;
32+
render(value: string | null): ReactNode {
33+
return this.get(value);
3534
}
3635
}

0 commit comments

Comments
 (0)