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
92 changes: 48 additions & 44 deletions packages/pluggableWidgets/combobox-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,174 +6,178 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- We fixed an issue where validation was not connected to combobox, causing issues for screenreaders.

## [1.7.2] - 2025-07-31

### Fixed

- We fixed an issue where combobox does not show initial caption correctly for database source.
- We fixed an issue where combobox does not show initial caption correctly for database source.

- We fixed an issue where combobox caption expression does not load correctly.
- We fixed an issue where combobox caption expression does not load correctly.

## [1.7.1] - 2025-01-28

### Fixed

- We fixed an issue where database onchange failed to trigger, if you have set your onChange event using database source on v1.7.0 previously, it will clear again upon upgrade, but it will be seamless upgrade from 1.6.x version.
- We fixed an issue where database onchange failed to trigger, if you have set your onChange event using database source on v1.7.0 previously, it will clear again upon upgrade, but it will be seamless upgrade from 1.6.x version.

## [1.7.0] - 2024-12-17

### Fixed

- We fixed an issue where placeholder failed to shown on database source.
- We fixed an issue where placeholder failed to shown on database source.

- We fixed an issue where onchange event on database source triggered directly onload.
- We fixed an issue where onchange event on database source triggered directly onload.

- We fixed an issue where selected value sometimes shows unavailable text on lazy loaded content.
- We fixed an issue where selected value sometimes shows unavailable text on lazy loaded content.

- We fixed an issue where database optional value attribute breaks on runtime when not being set.
- We fixed an issue where database optional value attribute breaks on runtime when not being set.

- We fixed an issue where custom content not shown on design preview and runtime for database datasource.
- We fixed an issue where custom content not shown on design preview and runtime for database datasource.

- We fixed an issue where the onChange event was not being triggered when selecting an item for the first time.
- We fixed an issue where the onChange event was not being triggered when selecting an item for the first time.

- We fixed an issue where the combo box values would not refresh after toggling its read-only state.
- We fixed an issue where the combo box values would not refresh after toggling its read-only state.

- We fixed an issue with the toolbar visibility when a combobox menu overlays it.
- We fixed an issue with the toolbar visibility when a combobox menu overlays it.

- We fixed a11y issue where aria-required not applied in the widget.
- We fixed a11y issue where aria-required not applied in the widget.

### Added

- We added support for attribute with **Long** type.
- We added support for attribute with **Long** type.

### Changed

- We make **Value** no longer required if the **Target attribute** is not set for database datasource.
- We make **Value** no longer required if the **Target attribute** is not set for database datasource.

- We restructure **Attribute** group configuration and rename it as **Store value**.
- We restructure **Attribute** group configuration and rename it as **Store value**.

## [1.6.3] - 2024-08-07

### Added

- We added a new filter type, 'Contains (exact),' as an option to provide a more strict search ranking.
- We added a new filter type, 'Contains (exact),' as an option to provide a more strict search ranking.

## [1.6.2] - 2024-07-16

### Changed

- Due to technical limitation, it is not possible to use lazy load on caption type = expression. Thus, we removed lazy loading for this configuration.
- Due to technical limitation, it is not possible to use lazy load on caption type = expression. Thus, we removed lazy loading for this configuration.

## [1.6.1] - 2024-06-28

### Changed

- We changed the default value for lazy loading. From now on, lazy loading will be true by default.
- We changed the default value for lazy loading. From now on, lazy loading will be true by default.

- We fixed an issue where in some cases the clear button is rendered outside of a combobox.
- We fixed an issue where in some cases the clear button is rendered outside of a combobox.

## [1.6.0] - 2024-06-19

### Changed

- We changed how input filtering works for lazy loading. if set to true, then the filter will works by retrieving directly from datasource, otherwise it works by scanning the current loaded data.
- We changed how input filtering works for lazy loading. if set to true, then the filter will works by retrieving directly from datasource, otherwise it works by scanning the current loaded data.

### Added

- We added Spinner and Skeleton loaders in addition to lazy loading feature. The default loader is spinner, and skeleton can also be selected. This improves UX when loading more content.
- We added Spinner and Skeleton loaders in addition to lazy loading feature. The default loader is spinner, and skeleton can also be selected. This improves UX when loading more content.

- We added lazy loading feature. By default it is turned off. When turned on, the items will be loaded in batches when scrolling.
- We added lazy loading feature. By default it is turned off. When turned on, the items will be loaded in batches when scrolling.

## # Breaking

- The Combo box now uses Atlas variables for its styling. This may change how the widget looks depending on the custom variables.
- The Combo box now uses Atlas variables for its styling. This may change how the widget looks depending on the custom variables.

## [1.5.0] - 2024-05-06

### Added

- We added readonly style to the combobox configuration.
- We added readonly style to the combobox configuration.

## [1.4.0] - 2024-04-19

### Changed

- We made accessibility text as optional.
- We made accessibility text as optional.

- We are no longer retrieving full dropdown options list if the combobox is readonly.
- We are no longer retrieving full dropdown options list if the combobox is readonly.

### Added

- We improved accessibility on combobox by removing a duplicated aria-expanded from combobox widget.
- We improved accessibility on combobox by removing a duplicated aria-expanded from combobox widget.

### Fixed

- We fixed an issue with the sorting of the displayed selected items in Multi Selection, where the sorting of selected items did not match the sorting in the menu.
- We fixed an issue with the sorting of the displayed selected items in Multi Selection, where the sorting of selected items did not match the sorting in the menu.

## [1.3.1] - 2024-04-08

### Fixed

- We fixed scrollbar click issue causing combobox to close.
- We fixed scrollbar click issue causing combobox to close.

## [1.3.0] - 2024-04-03

### Fixed

- We fixed sorting on combobox, now the sorting follows the default when the combobox opens, and follow a sorted ranking when any input is given.
- We fixed sorting on combobox, now the sorting follows the default when the combobox opens, and follow a sorted ranking when any input is given.

- We fixed focusable element not able to have focus if being placed on custom footer.
- We fixed focusable element not able to have focus if being placed on custom footer.

### Added

- We added static values feature support.
- We added static values feature support.

## [1.2.0] - 2024-02-27

### Fixed

- We fixed no options text not shown on single selection.
- We fixed no options text not shown on single selection.

### Changed

- We made a minor change on the configuration labels.
- We made a minor change on the configuration labels.

### Added

- We added database list feature support.
- We added database list feature support.

## [1.1.3] - 2024-01-22

### Fixed

- We fixed dropdown options directly closing when clicking on scrollbar if placed in popup dialog
- We fixed dropdown options directly closing when clicking on scrollbar if placed in popup dialog

## [1.1.2] - 2024-01-19

### Fixed

- We fixed selected options not showing for custom content type "yes"
- We fixed selected options not showing for custom content type "yes"

## [1.1.1] - 2024-01-15

### Changed

- We changed **Select/Unselect button** caption into **Show Select all** for easier understanding
- We changed **Select/Unselect button** caption into **Show Select all** for easier understanding

## [1.1.0] - 2024-01-14

### Added

- We added a new property named **Show footer**, enabling the Combobox widget to display a footer within its menu. When **Show footer** is set to **Yes**, developers can include custom footer content such as text, buttons, links, etc.
- We added a new property named **Show footer**, enabling the Combobox widget to display a footer within its menu. When **Show footer** is set to **Yes**, developers can include custom footer content such as text, buttons, links, etc.

- We added a new property named **Select/Unselect button**, enabling the Combobox widget to display a select/unselect all button on the top of the menu list.
- We added a new property named **Select/Unselect button**, enabling the Combobox widget to display a select/unselect all button on the top of the menu list.

### Fixed

- Sorting of the search results now follow the sort order set for Selectable objects.
- Sorting of the search results now follow the sort order set for Selectable objects.

- We removed the clear button on selected item labels in read-only state.
- We removed the clear button on selected item labels in read-only state.

- We fixed the positioning of the menu when it is flipped and collides with top of the viewport.
- We fixed the positioning of the menu when it is flipped and collides with top of the viewport.

- We fixed single selection combo box losing focus after selecting an item.
- We fixed single selection combo box losing focus after selecting an item.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ interface ComboboxWrapperProps extends PropsWithChildren {
getToggleButtonProps: (options?: UseComboboxGetToggleButtonPropsOptions | undefined) => any;
validation?: string;
isLoading: boolean;
errorId?: string;
}

export const ComboboxWrapper = forwardRef(
(props: ComboboxWrapperProps, ref: RefObject<HTMLDivElement>): ReactElement => {
const { isOpen, readOnly, readOnlyStyle, getToggleButtonProps, validation, children, isLoading } = props;
const { isOpen, readOnly, readOnlyStyle, getToggleButtonProps, validation, children, isLoading, errorId } =
props;
const { id, onClick } = getToggleButtonProps();

return (
Expand Down Expand Up @@ -45,7 +47,7 @@ export const ComboboxWrapper = forwardRef(
</div>
)}
</div>
{validation && <ValidationAlert>{validation}</ValidationAlert>}
{validation && <ValidationAlert id={errorId}>{validation}</ValidationAlert>}
</Fragment>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import classNames from "classnames";
import { Fragment, KeyboardEvent, ReactElement, createElement, useMemo, useRef } from "react";
import { ClearButton } from "../../assets/icons";
import { MultiSelector, SelectionBaseProps } from "../../helpers/types";
import { getSelectedCaptionsPlaceholder } from "../../helpers/utils";
import { getSelectedCaptionsPlaceholder, getValidationErrorId } from "../../helpers/utils";
import { useDownshiftMultiSelectProps } from "../../hooks/useDownshiftMultiSelectProps";
import { useLazyLoading } from "../../hooks/useLazyLoading";
import { ComboboxWrapper } from "../ComboboxWrapper";
Expand Down Expand Up @@ -37,6 +37,7 @@ export function MultiSelection({
const inputRef = useRef<HTMLInputElement>(null);
const isSelectedItemsBoxStyle = selector.selectedItemsStyle === "boxes";
const isOptionsSelected = selector.isOptionsSelected();
const errorId = getValidationErrorId(options.inputId);

const memoizedselectedCaptions = useMemo(
() => getSelectedCaptionsPlaceholder(selector, selectedItems),
Expand Down Expand Up @@ -65,6 +66,7 @@ export function MultiSelection({
getToggleButtonProps={getToggleButtonProps}
validation={selector.validation}
isLoading={lazyLoading && selector.options.isLoading}
errorId={errorId}
>
<div
className={classNames(
Expand Down Expand Up @@ -135,6 +137,8 @@ export function MultiSelection({
readOnly: selector.options.filterType === "none",
"aria-required": ariaRequired
})}
aria-describedby={selector.validation ? errorId : undefined}
aria-invalid={selector.validation ? true : undefined}
/>
<InputPlaceholder isEmpty={selectedItems.length <= 0}>{memoizedselectedCaptions}</InputPlaceholder>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import classNames from "classnames";
import { Fragment, ReactElement, createElement, useMemo, useRef } from "react";
import { ClearButton } from "../../assets/icons";
import { SelectionBaseProps, SingleSelector } from "../../helpers/types";
import { getValidationErrorId } from "../../helpers/utils";
import { useDownshiftSingleSelectProps } from "../../hooks/useDownshiftSingleSelectProps";
import { useLazyLoading } from "../../hooks/useLazyLoading";
import { ComboboxWrapper } from "../ComboboxWrapper";
Expand Down Expand Up @@ -54,6 +55,8 @@ export function SingleSelection({
]
);

const errorId = getValidationErrorId(options.inputId);

return (
<Fragment>
<ComboboxWrapper
Expand All @@ -63,6 +66,7 @@ export function SingleSelection({
getToggleButtonProps={getToggleButtonProps}
validation={selector.validation}
isLoading={lazyLoading && selector.options.isLoading}
errorId={errorId}
>
<div
className={classNames("widget-combobox-selected-items", {
Expand All @@ -84,6 +88,8 @@ export function SingleSelection({
{ suppressRefError: true }
)}
placeholder=" "
aria-describedby={selector.validation ? errorId : undefined}
aria-invalid={selector.validation ? true : undefined}
/>
<InputPlaceholder
isEmpty={!selector.currentId || !selector.caption.render(selectedItem, "label")}
Expand Down
12 changes: 8 additions & 4 deletions packages/pluggableWidgets/combobox-web/src/helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ export function CaptionContent(props: CaptionContentProps): ReactElement {
onClick: onClick
? onClick
: htmlFor
? (e: MouseEvent) => {
e.preventDefault();
}
: undefined
? (e: MouseEvent) => {
e.preventDefault();
}
: undefined
});
}

Expand Down Expand Up @@ -114,3 +114,7 @@ export function _valuesIsEqual(valueA: ValueType, valueB: ValueType): boolean {
}
return valueA === valueB;
}

export function getValidationErrorId(inputId?: string): string | undefined {
return inputId ? inputId + "-validation-message" : undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,8 @@ export interface ComboboxContainerProps {

export interface ComboboxPreviewProps {
readOnly: boolean;
renderMode?: "design" | "xray" | "structure";
renderMode: "design" | "xray" | "structure";
translate: (text: string) => string;
source: SourceEnum;
optionsSourceType: OptionsSourceTypeEnum;
attributeEnumeration: string;
Expand Down
10 changes: 6 additions & 4 deletions packages/shared/widget-plugin-component-kit/src/Alert.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@ export interface AlertProps {
children?: ReactNode;
className?: string;
bootstrapStyle: "default" | "primary" | "success" | "info" | "warning" | "danger";
id?: string;
role?: string;
}

export interface ValidationAlertProps {
children?: ReactNode;
className?: string;
id?: string;
}

// cloning from https://gitlab.rnd.mendix.com/appdev/appdev/-/blob/master/client/src/widgets/web/helpers/Alert.tsx
export const ValidationAlert = ({ className, children }: ValidationAlertProps): JSX.Element | null => (
<Alert className={classNames("mx-validation-message", className)} bootstrapStyle="danger" role="alert">
export const ValidationAlert = ({ className, children, id }: ValidationAlertProps): JSX.Element | null => (
<Alert className={classNames("mx-validation-message", className)} bootstrapStyle="danger" role="alert" id={id}>
{children}
</Alert>
);

export const Alert = ({ className, bootstrapStyle, children, role }: AlertProps): JSX.Element | null =>
export const Alert = ({ className, bootstrapStyle, children, role, id }: AlertProps): JSX.Element | null =>
Children.count(children) > 0 ? (
<div className={classNames(`alert alert-${bootstrapStyle}`, className)} role={role}>
<div className={classNames(`alert alert-${bootstrapStyle}`, className)} role={role} id={id}>
{children}
</div>
) : null;
Expand Down