From 5cd7b833dce9c75253df2efd429c12f3eb6f95a6 Mon Sep 17 00:00:00 2001 From: "Ziggy Z." Date: Thu, 16 Apr 2026 14:02:49 +0700 Subject: [PATCH 1/5] [BOOKINGSG-9157][ZZ] refactor: migrate dropdowns list to linaria and v4 tokens --- .../dropdown-list/dropdown-label.styles.ts | 137 +++++++++++ .../dropdown-list/dropdown-label.styles.tsx | 154 ------------ src/shared/dropdown-list/dropdown-label.tsx | 114 +++++---- .../dropdown-list/dropdown-list.styles.ts | 210 +++++++++++++++++ .../dropdown-list/dropdown-list.styles.tsx | 222 ------------------ src/shared/dropdown-list/dropdown-list.tsx | 191 +++++++++------ .../dropdown-list/dropdown-search.styles.ts | 62 +++++ .../dropdown-list/dropdown-search.styles.tsx | 71 ------ src/shared/dropdown-list/dropdown-search.tsx | 43 ++-- .../expandable-element.styles.ts | 55 +++++ .../expandable-element.styles.tsx | 62 ----- .../dropdown-list/expandable-element.tsx | 32 ++- .../nested-dropdown-list.styles.ts | 95 ++++++++ .../nested-dropdown-list.styles.tsx | 107 --------- .../dropdown-list/nested-dropdown-list.tsx | 213 +++++++++++------ 15 files changed, 935 insertions(+), 833 deletions(-) create mode 100644 src/shared/dropdown-list/dropdown-label.styles.ts delete mode 100644 src/shared/dropdown-list/dropdown-label.styles.tsx create mode 100644 src/shared/dropdown-list/dropdown-list.styles.ts delete mode 100644 src/shared/dropdown-list/dropdown-list.styles.tsx create mode 100644 src/shared/dropdown-list/dropdown-search.styles.ts delete mode 100644 src/shared/dropdown-list/dropdown-search.styles.tsx create mode 100644 src/shared/dropdown-list/expandable-element.styles.ts delete mode 100644 src/shared/dropdown-list/expandable-element.styles.tsx create mode 100644 src/shared/dropdown-list/nested-dropdown-list.styles.ts delete mode 100644 src/shared/dropdown-list/nested-dropdown-list.styles.tsx diff --git a/src/shared/dropdown-list/dropdown-label.styles.ts b/src/shared/dropdown-list/dropdown-label.styles.ts new file mode 100644 index 0000000000..ee965b1622 --- /dev/null +++ b/src/shared/dropdown-list/dropdown-label.styles.ts @@ -0,0 +1,137 @@ +import { css } from "@linaria/core"; + +import { Colour, Font } from "../../theme"; +import { lineClampDynamicCss } from "../styles"; + +export const tokens = { + primaryText: { + maxLines: "--fds-internal-dropdownLabel-primaryText-maxLines", + }, + secondaryText: { + maxLines: "--fds-internal-dropdownLabel-secondaryText-maxLines", + }, +}; + +// ============================================================================= +// STYLING +// ============================================================================= + +// ----------------------------------------------------------------------------- +// PRIMARY TEXT +// ----------------------------------------------------------------------------- +export const primaryText = css` + ${tokens.primaryText.maxLines}: 2; + font-weight: ${Font.Spec["weight-regular"]}; + color: ${Colour["text"]}; + width: 100%; + overflow-wrap: break-word; +`; + +export const primaryTextBold = css` + font-weight: ${Font.Spec["weight-semibold"]}; +`; + +export const primaryTextSelected = css` + color: ${Colour["text-selected"]}; +`; + +export const primaryTextDisabled = css` + color: ${Colour["text-disabled"]}; +`; + +export const primaryTextTruncateEnd = css` + ${lineClampDynamicCss(tokens.primaryText.maxLines)} +`; + +// ----------------------------------------------------------------------------- +// SECONDARY TEXT +// ----------------------------------------------------------------------------- +export const secondaryText = css` + ${tokens.secondaryText.maxLines}: 2; + color: ${Colour["text-subtlest"]}; + width: 100%; + overflow-wrap: break-word; +`; + +export const secondaryTextTruncateEnd = css` + ${lineClampDynamicCss(tokens.secondaryText.maxLines)} +`; + +export const secondaryTextNextLine = css` + ${Font["body-md-semibold"]} +`; + +export const secondaryTextInline = css` + ${Font["body-baseline-regular"]} +`; + +// ----------------------------------------------------------------------------- +// MATCHED TEXT +// ----------------------------------------------------------------------------- +export const matchedText = css` + font-weight: ${Font.Spec["weight-semibold"]}; +`; + +// ----------------------------------------------------------------------------- +// LABEL +// ----------------------------------------------------------------------------- +export const label = css` + text-align: left; + width: 100%; + overflow: hidden; + overflow-wrap: break-word; +`; + +export const labelVariantDefault = css` + ${Font["body-baseline-regular"]} +`; + +export const labelVariantSmall = css` + ${Font["body-md-regular"]} +`; + +export const labelNextLine = css` + display: flex; + flex-direction: column; +`; + +export const labelInline = css` + .${primaryText} { + display: inline; + } + + .${secondaryText} { + display: inline; + margin-left: 0.5rem; + } +`; + +// ----------------------------------------------------------------------------- +// TRUNCATION +// ----------------------------------------------------------------------------- +export const truncateFirstLine = css` + display: inline-block; + width: 100%; + height: 1lh; + word-break: break-all; + overflow: hidden; +`; + +export const truncateFirstLineSingle = css` + width: 50%; +`; + +export const truncateSecondLine = css` + display: inline-block; + width: 100%; + height: 1lh; + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + direction: rtl; + text-align: right; +`; + +export const truncateSecondLineSingle = css` + width: 50%; +`; diff --git a/src/shared/dropdown-list/dropdown-label.styles.tsx b/src/shared/dropdown-list/dropdown-label.styles.tsx deleted file mode 100644 index 8aa624c46a..0000000000 --- a/src/shared/dropdown-list/dropdown-label.styles.tsx +++ /dev/null @@ -1,154 +0,0 @@ -import styled, { css } from "styled-components"; - -import { V3_Colour, V3_Font } from "../../v3_theme"; -import { lineClampDynamicCss } from "../styles"; -import type { - DropdownVariantType, - LabelDisplayType, - TruncateType, -} from "./types"; - -const tokens = { - primaryText: { - maxLines: "--fds-dropdownLabel-primaryText-maxLines", - }, - secondaryText: { - maxLines: "--fds-dropdownLabel-secondaryText-maxLines", - }, -}; - -// ============================================================================= -// STYLE INTERFACE -// ============================================================================= -interface LabelStyleProps { - $labelDisplayType: LabelDisplayType; - $variant: DropdownVariantType; -} - -interface LabelTextStyleProps { - $labelDisplayType?: LabelDisplayType; - $maxLines?: number; - $selected?: boolean; - $disabled?: boolean; - $truncateType?: TruncateType; - $bold?: boolean; -} - -interface MatchedTextStyleProps { - $variant: DropdownVariantType; -} - -// ============================================================================= -// STYLING -// ============================================================================= - -export const PrimaryText = styled.div` - font-weight: ${(props) => - props.$bold - ? V3_Font.Spec["weight-semibold"] - : V3_Font.Spec["weight-regular"]}; - - ${(props) => { - if (props.$disabled) { - return css` - color: ${V3_Colour["text-disabled"]}; - `; - } else if (props.$selected) { - return css` - color: ${V3_Colour["text-selected"]}; - `; - } else { - return css` - color: ${V3_Colour["text"]}; - `; - } - }} - width: 100%; - overflow-wrap: break-word; - - ${(props) => - props.$truncateType === "end" && - lineClampDynamicCss(tokens.primaryText.maxLines)} - ${tokens.primaryText.maxLines}: ${(props) => props.$maxLines || 2}; -`; - -export const SecondaryText = styled.div` - color: ${V3_Colour["text-subtlest"]}; - width: 100%; - overflow-wrap: break-word; - - ${(props) => - props.$truncateType === "end" && - lineClampDynamicCss(tokens.secondaryText.maxLines)} - ${tokens.secondaryText.maxLines}: ${(props) => props.$maxLines || 2}; - - ${(props) => { - switch (props.$labelDisplayType) { - case "next-line": - return css` - ${V3_Font["body-md-semibold"]} - `; - case "inline": - default: - return css` - ${V3_Font["body-baseline-regular"]} - `; - } - }} -`; - -export const MatchedText = styled.span` - font-weight: ${V3_Font.Spec["weight-semibold"]}; -`; - -export const Label = styled.div` - text-align: left; - width: 100%; - overflow: hidden; - overflow-wrap: break-word; - - ${(props) => - props.$variant === "small" - ? V3_Font["body-md-regular"] - : V3_Font["body-baseline-regular"]} - - ${(props) => { - switch (props.$labelDisplayType) { - case "next-line": - return css` - display: flex; - flex-direction: column; - `; - case "inline": - return css` - ${PrimaryText} { - display: inline; - } - - ${SecondaryText} { - display: inline; - margin-left: 0.5rem; - } - `; - } - }} -`; - -export const TruncateFirstLine = styled.div` - display: inline-block; - width: ${(props) => (props.$maxLines === 1 ? 50 : 100)}%; - height: 1lh; - word-break: break-all; - overflow: hidden; -`; - -export const TruncateSecondLine = styled.div` - display: inline-block; - width: ${(props) => (props.$maxLines === 1 ? 50 : 100)}%; - height: 1lh; - text-overflow: ellipsis; - white-space: nowrap; - overflow: hidden; - direction: rtl; - text-align: right; -`; diff --git a/src/shared/dropdown-list/dropdown-label.tsx b/src/shared/dropdown-list/dropdown-label.tsx index 909f307663..ce7c5bde65 100644 --- a/src/shared/dropdown-list/dropdown-label.tsx +++ b/src/shared/dropdown-list/dropdown-label.tsx @@ -1,17 +1,11 @@ -import { useCallback, useContext, useMemo } from "react"; +import clsx from "clsx"; +import { useCallback, useMemo, useRef } from "react"; import { useResizeDetector } from "react-resize-detector"; -import { ThemeContext } from "styled-components"; +import { Font } from "../../theme"; +import { useApplyStyle } from "../../theme/utils/use-apply-styles"; import { StringHelper } from "../../util/string-helper"; -import { V3_Font } from "../../v3_theme"; -import { - Label, - MatchedText, - PrimaryText, - SecondaryText, - TruncateFirstLine, - TruncateSecondLine, -} from "./dropdown-label.styles"; +import * as styles from "./dropdown-label.styles"; import type { DropdownVariantType, LabelDisplayType } from "./types"; interface DropdownLabelProps { @@ -39,15 +33,24 @@ export const DropdownLabel = ({ truncationType = "middle", variant = "default", }: DropdownLabelProps): JSX.Element => { - const theme = useContext(ThemeContext); - const fontSize = variant === "small" - ? V3_Font.Spec["body-size-md"]({ theme }) - : V3_Font.Spec["body-size-baseline"]({ theme }); - const fontFamily = V3_Font.Spec["font-family"]({ theme }); + ? Font.Spec["body-size-md"] + : Font.Spec["body-size-baseline"]; + const fontFamily = Font.Spec["font-family"]; const { ref, width } = useResizeDetector(); + const primaryTextRef = useRef(null); + const secondaryTextRef = useRef(null); + + useApplyStyle(primaryTextRef, { + [styles.tokens.primaryText.maxLines]: String(maxLines), + }); + + useApplyStyle(secondaryTextRef, { + [styles.tokens.secondaryText.maxLines]: String(maxLines), + }); + // ========================================================================= // HELPER FUNCTIONS // ========================================================================= @@ -57,16 +60,11 @@ export const DropdownLabel = ({ return false; } - // best-effort attempt to check if multi-line text will overflow, - // rendering an actual element in the DOM might be more accurate - // but might not be performant for large lists const textWidth = StringHelper.getTextWidth( displayText, `${fontSize} '${fontFamily}'` ); - // there's less space than expected due to word breaks, so an - // arbitary offset is applied return textWidth > width * maxLines - 50; }, [width, displayType, fontSize, fontFamily, maxLines] @@ -84,8 +82,6 @@ export const DropdownLabel = ({ [hasExceededContainer, sublabel] ); - // css cannot truncate inline elements so force the display to render - // them separately const itemDisplayType = shouldTruncateTitle || shouldTruncateLabel ? "next-line" : displayType; @@ -108,9 +104,9 @@ export const DropdownLabel = ({ return ( <> {label.slice(0, startIndex)} - + {label.slice(startIndex, endIndex)} - + {label.slice(endIndex)} ); @@ -119,42 +115,74 @@ export const DropdownLabel = ({ const renderTruncatedText = (displayText: string): JSX.Element => { return ( <> - +
{renderMatchInBold(displayText)} - - +
+
{renderMatchInBold(displayText)} - +
); }; return ( - + ); }; diff --git a/src/shared/dropdown-list/dropdown-list.styles.ts b/src/shared/dropdown-list/dropdown-list.styles.ts new file mode 100644 index 0000000000..ef51db2b1c --- /dev/null +++ b/src/shared/dropdown-list/dropdown-list.styles.ts @@ -0,0 +1,210 @@ +import { css } from "@linaria/core"; + +import { + Border, + Breakpoint, + Colour, + Font, + MediaQuery, + Radius, + Spacing, +} from "../../theme"; + +export const tokens = { + xSpacing: "--fds-internal-dropdown-list-container-x-spacing", + availableWidth: "--fds-internal-dropdown-list-container-available-width", + availableHeight: "--fds-internal-dropdown-list-container-available-height", +} as const; + +// ----------------------------------------------------------------------------- +// MAIN STYLES +// ----------------------------------------------------------------------------- +export const container = css` + ${tokens.availableHeight}: initial; + ${tokens.availableWidth}: initial; + ${tokens.xSpacing}: initial; + + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + border-radius: ${Radius["sm"]}; + background: ${Colour["bg"]}; + + ${tokens.xSpacing}: 0px; + ${tokens.availableWidth}: calc( + 100vw - var(${tokens.xSpacing}) * 2 + ); + + ${MediaQuery.MaxWidth.xxs} { + --fds-internal-dropdown-list-container-x-spacing: ${Breakpoint[ + "xxs-margin" + ]}; + } + + ${MediaQuery.MaxWidth.xs} { + --fds-internal-dropdown-list-container-x-spacing: ${Breakpoint[ + "xs-margin" + ]}; + } + + ${MediaQuery.MaxWidth.sm} { + --fds-internal-dropdown-list-container-x-spacing: ${Breakpoint[ + "sm-margin" + ]}; + max-height: 15rem; + } + + max-width: var(--fds-internal-dropdown-list-container-available-width); + min-width: min( + 23rem, + var(--fds-internal-dropdown-list-container-available-width) + ); + max-height: min( + 27rem, + var(--fds-internal-dropdown-list-container-available-height, 9999px) + ); + overflow: hidden; + overflow-y: auto; + + &::-webkit-scrollbar { + width: 14px; + } + + &::-webkit-scrollbar-track { + background: transparent; + } + + &::-webkit-scrollbar-thumb { + background: ${Colour["bg-inverse-subtlest"]}; + border: 5px solid transparent; + border-radius: ${Radius["full"]}; + background-clip: padding-box; + } +`; + +export const containerVariantDefault = css` + ${Font["body-baseline-regular"]} +`; + +export const containerVariantSmall = css` + ${Font["body-md-regular"]} +`; + +export const list = css` + background: transparent; + padding: ${Spacing["spacing-8"]}; +`; + +export const listbox = css` + list-style-type: none; +`; + +// ----------------------------------------------------------------------------- +// LIST ITEM STYLES +// ----------------------------------------------------------------------------- +export const listItem = css` + display: flex; + align-items: flex-start; + gap: ${Spacing["spacing-8"]}; + padding: ${Spacing["spacing-12"]} ${Spacing["spacing-8"]}; + cursor: pointer; + border: none; + border-radius: ${Radius["none"]}; + outline: none; +`; + +export const listItemActive = css` + background: ${Colour["bg-hover-subtle"]}; +`; + +export const listItemActiveSelected = css` + background: ${Colour["bg-hover"]}; +`; + +export const listItemDisabled = css` + cursor: not-allowed; +`; + +export const selectedIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1rem; + color: ${Colour["icon-selected"]}; +`; + +export const unselectedIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1rem; +`; + +export const checkboxSelectedIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1lh; + color: ${Colour["icon-selected"]}; +`; + +export const checkboxUnselectedIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1lh; + color: ${Colour["icon-primary-subtlest"]}; +`; + +export const checkboxDisabledIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1lh; + color: ${Colour["icon-disabled-subtle"]}; +`; + +// ----------------------------------------------------------------------------- +// ELEMENT STYLES +// ----------------------------------------------------------------------------- +export const selectAllContainer = css` + width: 100%; + display: flex; + justify-content: flex-end; +`; + +export const selectAllButton = css` + cursor: pointer; + overflow: hidden; + color: ${Colour["text-primary"]}; + font-size: inherit; + ${Font["body-md-semibold"]} + padding: ${Spacing["spacing-8"]}; +`; + +export const tryAgainButton = css` + cursor: pointer; + overflow: hidden; + color: ${Colour["text-primary"]}; + font-size: inherit; + ${Font["body-baseline-semibold"]} +`; + +export const resultStateContainer = css` + width: 100%; + display: flex; + padding: ${Spacing["spacing-12"]} ${Spacing["spacing-16"]}; + align-items: center; +`; + +export const labelIcon = css` + margin-right: ${Spacing["spacing-4"]}; + color: ${Colour["icon-error"]}; + height: 1em; + width: 1em; +`; + +export const spinner = css` + margin-right: ${Spacing["spacing-8"]}; + color: ${Colour["icon"]}; +`; + +export const noResultDescContainer = css` + --horizontal-padding: ${Spacing["spacing-16"]}; + color: ${Colour["text-subtle"]}; + padding: 0 var(--horizontal-padding) ${Spacing["spacing-12"]} + var(--horizontal-padding); +`; diff --git a/src/shared/dropdown-list/dropdown-list.styles.tsx b/src/shared/dropdown-list/dropdown-list.styles.tsx deleted file mode 100644 index 612b496916..0000000000 --- a/src/shared/dropdown-list/dropdown-list.styles.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { ExclamationCircleFillIcon } from "@lifesg/react-icons/exclamation-circle-fill"; -import { SquareIcon } from "@lifesg/react-icons/square"; -import { SquareFillIcon } from "@lifesg/react-icons/square-fill"; -import { SquareTickFillIcon } from "@lifesg/react-icons/square-tick-fill"; -import { TickIcon } from "@lifesg/react-icons/tick"; -import styled, { css } from "styled-components"; - -import { Markup } from "../../markup"; -import { - V3_Border, - V3_Breakpoint, - V3_Colour, - V3_Font, - V3_MediaQuery, - V3_Radius, - V3_Spacing, -} from "../../v3_theme"; -import { ComponentLoadingSpinner } from "../component-loading-spinner"; -import { BasicButton } from "../input-wrapper"; -import type { DropdownVariantType } from "./types"; - -// ============================================================================= -// STYLE INTERFACE -// ============================================================================= -interface ContainerStyleProps { - $width?: number; - $customWidth?: string; - $variant: DropdownVariantType; -} - -export interface ListItemStyleProps { - $active: boolean; - $selected: boolean; - $disabled: boolean; -} - -// ============================================================================= -// STYLING -// ============================================================================= - -// ----------------------------------------------------------------------------- -// MAIN STYLES -// ----------------------------------------------------------------------------- -export const Container = styled.div` - border: ${V3_Border["width-010"]} ${V3_Border["solid"]} - ${V3_Colour["border"]}; - border-radius: ${V3_Radius["sm"]}; - background: ${V3_Colour["bg"]}; - - --x-spacing: 0px; - --available-width: calc(100vw - var(--x-spacing) * 2); - - ${V3_MediaQuery.MaxWidth.sm} { - --x-spacing: ${V3_Breakpoint["sm-margin"]}px; - max-height: 15rem; - } - - ${V3_MediaQuery.MaxWidth.xs} { - --x-spacing: ${V3_Breakpoint["xs-margin"]}px; - } - - ${V3_MediaQuery.MaxWidth.xxs} { - --x-spacing: ${V3_Breakpoint["xxs-margin"]}px; - } - - max-width: var(--available-width); - - ${(props) => { - if (props.$customWidth) return `width: ${props.$customWidth};`; - if (props.$width) - return `width: ${props.$width}px; min-width: min(23rem, var(--available-width));`; - - return "min-width: min(23rem, var(--available-width));"; - }} - - max-height: min(27rem, var(--available-height, infinity * 1px)); - overflow: hidden; - overflow-y: auto; - ${(props) => - props.$variant === "small" - ? V3_Font["body-md-regular"] - : V3_Font["body-baseline-regular"]} - - &::-webkit-scrollbar { - width: 14px; - } - - &::-webkit-scrollbar-track { - background: transparent; - } - - &::-webkit-scrollbar-thumb { - background: ${V3_Colour["bg-inverse-subtlest"]}; - border: 5px solid transparent; - border-radius: ${V3_Radius["full"]}; - background-clip: padding-box; - } -`; -export const List = styled.div` - background: transparent; - padding: ${V3_Spacing["spacing-8"]}; -`; - -export const Listbox = styled.ul` - list-style-type: none; -`; - -// ----------------------------------------------------------------------------- -// LIST ITEM STYLES -// ----------------------------------------------------------------------------- - -export const ListItem = styled.li` - display: flex; - align-items: flex-start; - gap: ${V3_Spacing["spacing-8"]}; - padding: ${V3_Spacing["spacing-12"]} ${V3_Spacing["spacing-8"]}; - cursor: pointer; - border: none; - border-radius: ${V3_Radius["none"]}; - outline: none; - - ${(props) => { - if (props.$disabled) { - return css` - cursor: not-allowed; - `; - } else if (props.$active && props.$selected) { - return css` - background: ${V3_Colour["bg-hover"]}; - `; - } else if (props.$active) { - return css` - background: ${V3_Colour["bg-hover-subtle"]}; - `; - } - }} -`; - -export const SelectedIndicator = styled(TickIcon)` - flex-shrink: 0; - height: 1lh; - width: 1rem; - color: ${V3_Colour["icon-selected"]}; -`; - -export const UnselectedIndicator = styled.div` - flex-shrink: 0; - height: 1lh; - width: 1rem; -`; - -export const CheckboxSelectedIndicator = styled(SquareTickFillIcon)` - flex-shrink: 0; - height: 1lh; - width: 1lh; - color: ${V3_Colour["icon-selected"]}; -`; - -export const CheckboxUnselectedIndicator = styled(SquareIcon)` - flex-shrink: 0; - height: 1lh; - width: 1lh; - color: ${V3_Colour["icon-primary-subtlest"]}; -`; - -export const CheckboxDisabledIndicator = styled(SquareFillIcon)` - flex-shrink: 0; - height: 1lh; - width: 1lh; - color: ${V3_Colour["icon-disabled-subtle"]}; -`; - -// ----------------------------------------------------------------------------- -// ELEMENT STYLES -// ----------------------------------------------------------------------------- - -export const SelectAllContainer = styled.div` - width: 100%; - display: flex; - justify-content: flex-end; -`; - -export const DropdownCommonButton = styled(BasicButton)` - cursor: pointer; - overflow: hidden; - color: ${V3_Colour["text-primary"]}; - font-size: inherit; -`; - -export const TryAgainButton = styled(DropdownCommonButton)` - ${V3_Font["body-baseline-semibold"]} -`; - -export const SelectAllButton = styled(DropdownCommonButton)` - ${V3_Font["body-md-semibold"]} - padding: ${V3_Spacing["spacing-8"]} ${V3_Spacing["spacing-8"]}; -`; - -export const ResultStateContainer = styled.div` - width: 100%; - display: flex; - padding: ${V3_Spacing["spacing-12"]} ${V3_Spacing["spacing-16"]}; - align-items: center; -`; - -export const LabelIcon = styled(ExclamationCircleFillIcon)` - margin-right: ${V3_Spacing["spacing-4"]}; - color: ${V3_Colour["icon-error"]}; - height: 1em; - width: 1em; -`; - -export const Spinner = styled(ComponentLoadingSpinner)` - margin-right: ${V3_Spacing["spacing-8"]}; - color: ${V3_Colour["icon"]}; -`; - -export const NoResultDescContainer = styled(Markup)` - color: ${V3_Colour["text-subtle"]}; - padding: 0 ${V3_Spacing["spacing-16"]} ${V3_Spacing["spacing-12"]} - ${V3_Spacing["spacing-16"]}; -`; diff --git a/src/shared/dropdown-list/dropdown-list.tsx b/src/shared/dropdown-list/dropdown-list.tsx index 95f605be37..8ffc33a7a3 100644 --- a/src/shared/dropdown-list/dropdown-list.tsx +++ b/src/shared/dropdown-list/dropdown-list.tsx @@ -1,3 +1,9 @@ +import { ExclamationCircleFillIcon } from "@lifesg/react-icons/exclamation-circle-fill"; +import { SquareIcon } from "@lifesg/react-icons/square"; +import { SquareFillIcon } from "@lifesg/react-icons/square-fill"; +import { SquareTickFillIcon } from "@lifesg/react-icons/square-tick-fill"; +import { TickIcon } from "@lifesg/react-icons/tick"; +import clsx from "clsx"; import find from "lodash/find"; import isEqual from "lodash/isEqual"; import type React from "react"; @@ -13,6 +19,8 @@ import { import type { VirtuosoHandle } from "react-virtuoso"; import { Virtuoso } from "react-virtuoso"; +import { Markup } from "../../markup"; +import { useApplyStyle } from "../../theme"; import { mergeRefs, useCompare, @@ -21,26 +29,11 @@ import { useIsMounted, } from "../../util"; import { VisuallyHidden } from "../accessibility"; +import { ComponentLoadingSpinner } from "../component-loading-spinner"; import { useDropdownRender } from "../dropdown-wrapper"; +import { BasicButton } from "../input-wrapper"; import { DropdownLabel } from "./dropdown-label"; -import { - CheckboxDisabledIndicator, - CheckboxSelectedIndicator, - CheckboxUnselectedIndicator, - Container, - LabelIcon, - List, - Listbox, - ListItem, - NoResultDescContainer, - ResultStateContainer, - SelectAllButton, - SelectAllContainer, - SelectedIndicator, - Spinner, - TryAgainButton, - UnselectedIndicator, -} from "./dropdown-list.styles"; +import * as styles from "./dropdown-list.styles"; import { DropdownListStateContext } from "./dropdown-list-state"; import { DropdownSearch } from "./dropdown-search"; import type { @@ -104,8 +97,12 @@ const DropdownListInner = ( const { focusedIndex, setFocusedIndex } = useContext( DropdownListStateContext ); - const { elementWidth, setFloatingRef, getFloatingProps, styles } = - useDropdownRender(); + const { + elementWidth, + setFloatingRef, + getFloatingProps, + styles: floatingStyles, + } = useDropdownRender(); const [searchValue, setSearchValue] = useState(""); const [displayListItems, setDisplayListItems] = useState(listItems ?? []); const itemsLoadStateChanged = useCompare(itemsLoadState); @@ -122,6 +119,12 @@ const DropdownListInner = ( !!selectedItems && selectedItems?.length === maxSelectable; + const containerWidthStyle: React.CSSProperties = width + ? { width } + : matchElementWidth && elementWidth + ? { width: elementWidth } + : {}; + // ========================================================================= // HELPER FUNCTIONS // ========================================================================= @@ -131,7 +134,6 @@ const DropdownListInner = ( const getItemKey = (item: T, index: number) => { const formattedValue = valueExtractor ? valueExtractor(item) : item; - // This is needed as some items might have the same value return `item_${index}__${formattedValue}`; }; @@ -232,7 +234,6 @@ const DropdownListInner = ( switch (event.code) { case "ArrowDown": event.preventDefault(); - // Cannot go further than last element if (focusedIndex < displayListItems.length - 1) { const upcomingIndex = focusedIndex + 1; listItemRefs.current[upcomingIndex]?.focus(); @@ -241,7 +242,6 @@ const DropdownListInner = ( break; case "ArrowUp": event.preventDefault(); - // Cannot go further than first element if (focusedIndex > 0) { const upcomingIndex = focusedIndex - 1; listItemRefs.current[upcomingIndex]?.focus(); @@ -306,7 +306,6 @@ const DropdownListInner = ( virtuosoRef.current?.scrollTo({ top: 0 }); return; } - // Delay to ensure render is complete const timer = setTimeout(() => { if (!listItems) return; @@ -322,11 +321,8 @@ const DropdownListInner = ( useEffect(() => { if (disableItemFocus) return; - - // skip effect as dependency did not change if (!mounted || !itemsLoadStateChanged) return; - // Reset focus when options are loaded if (itemsLoadState === "success") { if (searchInputRef.current) { setFocusedIndex(-1); @@ -363,7 +359,6 @@ const DropdownListInner = ( useEffect(() => { if (mounted) { - // only run on mount return; } @@ -373,24 +368,20 @@ const DropdownListInner = ( checkListItemSelected(item) ); - // Focus search input if there is one if (searchInputRef.current) { setFocusedIndex(-1); - setTimeout(() => searchInputRef.current?.focus(), 200); // Wait for animation + setTimeout(() => searchInputRef.current?.focus(), 200); } else if (focusedIndex > 0) { - // Else focus on the specified element virtuosoRef.current?.scrollToIndex({ index: focusedIndex, align: "center", }); setTimeout(() => listItemRefs.current[focusedIndex]?.focus(), 200); } else if (index !== -1) { - // Else focus on the selected element virtuosoRef.current?.scrollToIndex({ index, align: "center" }); setFocusedIndex(index); setTimeout(() => listItemRefs.current[index]?.focus(), 200); } else { - // Else focus on the first list item virtuosoRef.current?.scrollToIndex({ index: 0 }); setFocusedIndex(0); setTimeout(() => listItemRefs.current[0]?.focus(), 200); @@ -404,26 +395,46 @@ const DropdownListInner = ( setFocusedIndex, ]); + // ========================================================================= + // APPLY STYLES + // ========================================================================= + + useApplyStyle(nodeRef, { + ...floatingStyles, + ...containerWidthStyle, + }); + // ========================================================================= // RENDER FUNCTIONS // ========================================================================= const renderListItemIcon = (selected: boolean) => { if (multiSelect) { if (hasSelectedMax && !selected) { - return ; + return ( + + ); } return selected ? ( - + ) : ( - + ); } return selected ? ( - + ) : ( - +
); }; @@ -448,11 +459,12 @@ const DropdownListInner = ( if (!onRetry || itemsLoadState === "success") { const selected = checkListItemSelected(item); const active = index === focusedIndex; + const disabled = !selected && hasSelectedMax; return ( - ( }} role="option" tabIndex={active ? 0 : -1} - $active={active} - $selected={selected} - $disabled={!selected && hasSelectedMax} + className={clsx( + styles.listItem, + disabled && styles.listItemDisabled, + active && selected && styles.listItemActiveSelected, + active && !selected && styles.listItemActive + )} > {renderListItem ? ( renderListItem(item, { selected }) @@ -476,7 +491,7 @@ const DropdownListInner = ( {renderDropdownLabel(item, selected)} )} - + ); } }; @@ -507,13 +522,17 @@ const DropdownListInner = ( itemsLoadState === "success" ) { return ( - - +
+ {maxSelectable || selectedItems.length !== 0 ? clearAllButtonLabel : selectAllButtonLabel} - - + +
); } }; @@ -527,14 +546,23 @@ const DropdownListInner = ( ) { return ( <> - - +
+ {noResultsLabel} - +
{noResultsDescription && ( - + {noResultsDescription} - + )} ); @@ -544,10 +572,13 @@ const DropdownListInner = ( const renderLoading = () => { if (onRetry && itemsLoadState === "loading") { return ( - - +
+ Loading... - +
); } }; @@ -555,13 +586,23 @@ const DropdownListInner = ( const renderTryAgain = () => { if (onRetry && itemsLoadState === "fail") { return ( - - +
+ Failed to load.  - + Try again. - - + +
); } }; @@ -570,35 +611,32 @@ const DropdownListInner = ( const isTestEnv = process.env.NODE_ENV === "test"; return ( - +
    renderItem(item, index)} - // disable virtualisation in tests - // https://github.com/petyosi/react-virtuoso/issues/26#issuecomment-1040316576 - // explicitly set the `key` prop to avoid React warning key={isTestEnv ? displayListItems.length : undefined} - // omit the `initialItemCount` prop to resolve NaN error {...(isTestEnv ? { initialItemCount: displayListItems.length, } : {})} /> - +
); }; const renderList = () => { return ( - {renderSearchInput()} {renderSelectAll()} @@ -606,7 +644,7 @@ const DropdownListInner = ( {renderLoading()} {renderTryAgain()} {renderVirtualisedList()} - +
); }; @@ -615,7 +653,6 @@ const DropdownListInner = ( return; } - // FIXME: implement onDismiss handling return (
{renderCustomCallToAction(onDismiss as any, displayListItems)} @@ -624,19 +661,21 @@ const DropdownListInner = ( }; return ( - {ariaLabel} {renderList()} {renderBottomCta()} - +
); }; diff --git a/src/shared/dropdown-list/dropdown-search.styles.ts b/src/shared/dropdown-list/dropdown-search.styles.ts new file mode 100644 index 0000000000..d87902b928 --- /dev/null +++ b/src/shared/dropdown-list/dropdown-search.styles.ts @@ -0,0 +1,62 @@ +import { css } from "@linaria/core"; + +import { Colour, Font, Radius, Spacing } from "../../theme"; + +// ============================================================================= +// STYLING +// ============================================================================= + +export const container = css` + background: ${Colour["bg-strong"]}; + border-radius: ${Radius["sm"]}; + display: flex; + align-items: center; +`; + +export const containerVariantDefault = css` + ${Font["body-baseline-regular"]} +`; + +export const containerVariantSmall = css` + ${Font["body-md-regular"]} +`; + +export const searchBox = css` + flex: 1; + display: flex; + align-items: center; + gap: ${Spacing["spacing-8"]}; + padding: 10px ${Spacing["spacing-8"]}; +`; + +export const searchBoxVariantSmall = css` + padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; +`; + +export const searchInput = css` + flex: 1; +`; + +export const searchIcon = css` + color: ${Colour["icon"]}; + flex-shrink: 0; + height: 1em; + width: 1em; +`; + +export const clearButton = css` + flex-shrink: 0; + align-self: stretch; + box-sizing: content-box; + padding: ${Spacing["spacing-8"]}; + margin-left: -${Spacing["spacing-8"]}; + color: ${Colour["icon"]}; + cursor: pointer; + font-size: inherit; + + svg { + flex-shrink: 0; + height: 1em; + width: 1em; + } +`; diff --git a/src/shared/dropdown-list/dropdown-search.styles.tsx b/src/shared/dropdown-list/dropdown-search.styles.tsx deleted file mode 100644 index 5a96ff3051..0000000000 --- a/src/shared/dropdown-list/dropdown-search.styles.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { MagnifierIcon } from "@lifesg/react-icons/magnifier"; -import styled, { css } from "styled-components"; - -import { V3_Colour, V3_Font, V3_Radius, V3_Spacing } from "../../v3_theme"; -import { ClickableIcon } from "../clickable-icon"; -import { BasicInput } from "../input-wrapper"; -import type { DropdownVariantType } from "./types"; - -//============================================================================= -// STYLE INTERFACE -//============================================================================= -export interface StyleProps { - $variant: DropdownVariantType | undefined; -} - -//============================================================================= -// STYLING -//============================================================================= -export const Container = styled.div` - background: ${V3_Colour["bg-strong"]}; - border-radius: ${V3_Radius["sm"]}; - display: flex; - align-items: center; - - ${(props) => - props.$variant === "small" - ? V3_Font["body-md-regular"] - : V3_Font["body-baseline-regular"]} -`; - -export const SearchBox = styled.label` - flex: 1; - display: flex; - align-items: center; - gap: ${V3_Spacing["spacing-8"]}; - padding: ${(props) => - props.$variant === "small" - ? css` - ${V3_Spacing["spacing-8"]} ${V3_Spacing["spacing-16"]} - ` - : // TODO: confirm vertical spacing - css`10px ${V3_Spacing["spacing-8"]}`}; -`; - -export const SearchInput = styled(BasicInput)` - flex: 1; -`; - -export const SearchIcon = styled(MagnifierIcon)` - color: ${V3_Colour["icon"]}; - flex-shrink: 0; - height: 1em; - width: 1em; -`; - -export const ClearButton = styled(ClickableIcon)` - flex-shrink: 0; - align-self: stretch; - box-sizing: content-box; - padding: ${V3_Spacing["spacing-8"]}; - margin-left: -${V3_Spacing["spacing-8"]}; - color: ${V3_Colour["icon"]}; - cursor: pointer; - font-size: inherit; - - svg { - flex-shrink: 0; - height: 1em; - width: 1em; - } -`; diff --git a/src/shared/dropdown-list/dropdown-search.tsx b/src/shared/dropdown-list/dropdown-search.tsx index 3b7ce516c7..95d2785f6c 100644 --- a/src/shared/dropdown-list/dropdown-search.tsx +++ b/src/shared/dropdown-list/dropdown-search.tsx @@ -1,14 +1,12 @@ import { CrossIcon } from "@lifesg/react-icons/cross"; +import { MagnifierIcon } from "@lifesg/react-icons/magnifier"; +import clsx from "clsx"; import type React from "react"; import { forwardRef } from "react"; -import { - ClearButton, - Container, - SearchBox, - SearchIcon, - SearchInput, -} from "./dropdown-search.styles"; +import { ClickableIcon } from "../clickable-icon"; +import { BasicInput } from "../input-wrapper"; +import * as styles from "./dropdown-search.styles"; import type { DropdownVariantType } from "./types"; interface Props extends React.HTMLAttributes { @@ -22,26 +20,39 @@ const Component = ( ref: React.Ref ): JSX.Element => { return ( - - - - + + {value && ( - - + )} - + ); }; diff --git a/src/shared/dropdown-list/expandable-element.styles.ts b/src/shared/dropdown-list/expandable-element.styles.ts new file mode 100644 index 0000000000..653a8973bc --- /dev/null +++ b/src/shared/dropdown-list/expandable-element.styles.ts @@ -0,0 +1,55 @@ +import { css } from "@linaria/core"; + +import { Colour, Font, Motion, Spacing } from "../../theme"; + +// ============================================================================= +// STYLING +// ============================================================================= + +export const selector = css` + display: flex; + align-items: center; + gap: ${Spacing["spacing-8"]}; + width: 100%; + + ${Font["body-baseline-regular"]} + height: calc(3rem - 2px); + + &:disabled { + cursor: not-allowed; + } + + &:focus-visible { + outline: 2px solid ${Colour["focus-ring"]}; + outline-offset: -2px; + } +`; + +export const selectorVariantSmall = css` + ${Font["body-md-regular"]} + height: calc(2.5rem - 2px); +`; + +export const selectorReadOnly = css` + padding: 0 ${Spacing["spacing-16"]}; +`; + +export const selectorEditable = css` + padding: ${Spacing["spacing-16"]}; +`; + +export const iconContainer = css` + display: flex; + align-items: center; + transition: transform ${Motion["duration-250"]} ${Motion["ease-default"]}; + + svg { + color: ${Colour["icon"]}; + height: 1em; + width: 1em; + } +`; + +export const iconContainerExpanded = css` + transform: rotate(180deg); +`; diff --git a/src/shared/dropdown-list/expandable-element.styles.tsx b/src/shared/dropdown-list/expandable-element.styles.tsx deleted file mode 100644 index 4b8fdd6ec5..0000000000 --- a/src/shared/dropdown-list/expandable-element.styles.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import styled, { css } from "styled-components"; - -import { V3_Colour, V3_Font, V3_Motion, V3_Spacing } from "../../v3_theme"; -import { BasicButton } from "../input-wrapper"; -import type { DropdownVariantType } from "./types"; - -// ============================================================================= -// STYLE INTERFACE -// ============================================================================= -interface StyleProps { - $expanded?: boolean; - $variant?: DropdownVariantType; - $readOnly?: boolean; -} - -// ============================================================================= -// STYLING -// ============================================================================= -export const Selector = styled(BasicButton)` - display: flex; - align-items: center; - gap: ${V3_Spacing["spacing-8"]}; - width: 100%; - padding: ${(props) => - props.$readOnly - ? `0 ${V3_Spacing["spacing-16"]}` - : V3_Spacing["spacing-16"]}; - - ${(props) => - props.$variant === "small" - ? css` - ${V3_Font["body-md-regular"]} - height: calc(2.5rem - 2px); // exclude top and bottom borders - ` - : css` - ${V3_Font["body-baseline-regular"]} - height: calc(3rem - 2px); - `} - - &:disabled { - cursor: not-allowed; - } - - &:focus-visible { - outline: 2px solid ${V3_Colour["focus-ring"]}; - outline-offset: -2px; - } -`; - -export const IconContainer = styled.div` - display: flex; - align-items: center; - transform: rotate(${(props) => (props.$expanded ? 180 : 0)}deg); - transition: transform ${V3_Motion["duration-250"]} - ${V3_Motion["ease-default"]}; - - svg { - color: ${V3_Colour["icon"]}; - height: 1em; - width: 1em; - } -`; diff --git a/src/shared/dropdown-list/expandable-element.tsx b/src/shared/dropdown-list/expandable-element.tsx index ecb4fd86bb..49a3d02c40 100644 --- a/src/shared/dropdown-list/expandable-element.tsx +++ b/src/shared/dropdown-list/expandable-element.tsx @@ -1,8 +1,10 @@ import { ChevronDownIcon } from "@lifesg/react-icons/chevron-down"; +import clsx from "clsx"; import type { AriaAttributes, Ref } from "react"; import { forwardRef } from "react"; -import { IconContainer, Selector } from "./expandable-element.styles"; +import { BasicButton } from "../input-wrapper"; +import * as styles from "./expandable-element.styles"; import type { DropdownVariantType } from "./types"; export interface ExpandableElementProps @@ -11,6 +13,7 @@ export interface ExpandableElementProps "aria-labelledby" | "aria-describedby" | "aria-invalid" > { children: React.ReactNode; + className?: string | undefined; disabled: boolean | undefined; expanded: boolean | undefined; listboxId: string; @@ -22,6 +25,7 @@ export interface ExpandableElementProps export const Component = ( { children, + className, disabled, expanded, listboxId, @@ -32,31 +36,37 @@ export const Component = ( }: ExpandableElementProps, ref: Ref ) => { - // ============================================================================= - // RENDER FUNCTION - // ============================================================================= return ( - {children} {!readOnly && ( - +
- +
)} -
+ ); }; diff --git a/src/shared/dropdown-list/nested-dropdown-list.styles.ts b/src/shared/dropdown-list/nested-dropdown-list.styles.ts new file mode 100644 index 0000000000..632c25e3ab --- /dev/null +++ b/src/shared/dropdown-list/nested-dropdown-list.styles.ts @@ -0,0 +1,95 @@ +import { css } from "@linaria/core"; + +import { Colour, Motion, Radius, Spacing } from "../../theme"; + +// ============================================================================= +// STYLING +// ============================================================================= + +export const tokens = { + level: "--fds-internal-nestedDropdownList-indent-level", +}; + +// ----------------------------------------------------------------------------- +// LIST ITEM STYLES +// ----------------------------------------------------------------------------- + +export const listItemContainer = css` + display: flex; +`; + +export const listItemContainerHidden = css` + display: none; +`; + +export const listItem = css` + flex: 1; + display: flex; + align-items: flex-start; + gap: ${Spacing["spacing-8"]}; + padding: ${Spacing["spacing-12"]} ${Spacing["spacing-8"]}; + cursor: pointer; + overflow: hidden; + border-radius: ${Radius["none"]}; + outline: none; +`; + +export const listItemToggleable = css` + cursor: default; +`; + +export const listItemActive = css` + background: ${Colour["bg-hover"]}; +`; + +export const indent = css` + ${tokens.level}: 0; + height: 1px; + width: calc((1lh + ${Spacing["spacing-8"]}) * var(${tokens.level})); +`; + +const expandButtonTransition = `transform ${Motion["duration-350"]} ${Motion["ease-standard"]}`; + +export const expandButton = css` + width: 1lh; + height: 1lh; + color: ${Colour["icon-primary"]}; + cursor: pointer; + + svg { + width: 1lh; + height: 1lh; + transition: ${expandButtonTransition}; + } +`; + +export const expandButtonExpanded = css` + svg { + transform: rotate(90deg); + } +`; + +export const unexpandableIndicator = css` + width: 1lh; + height: 1lh; + margin-right: ${Spacing["spacing-8"]}; +`; + +export const selectionIndicator = css` + flex-shrink: 0; + height: 1lh; + width: ${Spacing["spacing-16"]}; + display: flex; + justify-content: center; +`; + +export const selectionIndicatorNested = css` + width: 1lh; +`; + +export const checkboxMixedIndicator = css` + flex-shrink: 0; + height: 1lh; + width: 1lh; + color: ${Colour["icon-selected"]}; +`; diff --git a/src/shared/dropdown-list/nested-dropdown-list.styles.tsx b/src/shared/dropdown-list/nested-dropdown-list.styles.tsx deleted file mode 100644 index 6c1019d572..0000000000 --- a/src/shared/dropdown-list/nested-dropdown-list.styles.tsx +++ /dev/null @@ -1,107 +0,0 @@ -import { MinusSquareFillIcon } from "@lifesg/react-icons/minus-square-fill"; -import styled, { css } from "styled-components"; - -import { V3_Colour, V3_Motion, V3_Radius, V3_Spacing } from "../../v3_theme"; - -// ============================================================================= -// STYLE INTERFACE -// ============================================================================= -interface ListItemStyleProps { - $active?: boolean; - $visible?: boolean; - $toggleable?: boolean; -} - -interface IndentStyleProps { - $level?: number; -} - -interface IndicatorStyleProps { - $hasNestedSiblings?: boolean; -} - -interface ExpandButtonStyleProps { - $expanded?: boolean; -} - -// ============================================================================= -// STYLING -// ============================================================================= - -// ----------------------------------------------------------------------------- -// LIST ITEM STYLES -// ----------------------------------------------------------------------------- - -export const ListItemContainer = styled.li` - display: ${(props) => (props.$visible ? "flex" : "none")}; -`; - -export const ListItem = styled.div` - flex: 1; - display: flex; - align-items: flex-start; - gap: ${V3_Spacing["spacing-8"]}; - padding: ${V3_Spacing["spacing-12"]} ${V3_Spacing["spacing-8"]}; - cursor: ${(props) => (props.$toggleable ? "default" : "pointer")}; - overflow: hidden; // required for label to truncate properly - border-radius: ${V3_Radius["none"]}; - outline: none; - - ${(props) => - props.$active && - css` - background: ${V3_Colour["bg-hover"]}; - `} -`; - -export const Indent = styled.div` - height: 1px; - width: calc( - (1lh + ${V3_Spacing["spacing-8"]}) * ${(props) => props.$level} - ); -`; - -export const ExpandButton = styled.div` - width: 1lh; - height: 1lh; - color: ${V3_Colour["icon-primary"]}; - cursor: pointer; - - svg { - width: 1lh; - height: 1lh; - transition: transform ${V3_Motion["duration-350"]} - ${V3_Motion["ease-standard"]}; - - ${(props) => { - if (props.$expanded) { - return css` - transform: rotate(90deg); - `; - } - }} - } -`; - -export const UnexpandableIndicator = styled.div` - width: 1lh; - height: 1lh; - margin-right: ${V3_Spacing["spacing-8"]}; -`; - -export const SelectionIndicator = styled.div` - flex-shrink: 0; - height: 1lh; - width: ${(props) => - props.$hasNestedSiblings ? "1lh" : V3_Spacing["spacing-16"]}; - - display: flex; - justify-content: center; -`; - -export const CheckboxMixedIndicator = styled(MinusSquareFillIcon)` - flex-shrink: 0; - height: 1lh; - width: lh; - r: ${V3_Colour["icon-selected"]}; -`; diff --git a/src/shared/dropdown-list/nested-dropdown-list.tsx b/src/shared/dropdown-list/nested-dropdown-list.tsx index 9a5d684a41..8f2af0f4bf 100644 --- a/src/shared/dropdown-list/nested-dropdown-list.tsx +++ b/src/shared/dropdown-list/nested-dropdown-list.tsx @@ -1,39 +1,28 @@ import { CaretRightIcon } from "@lifesg/react-icons/caret-right"; +import { ExclamationCircleFillIcon } from "@lifesg/react-icons/exclamation-circle-fill"; +import { MinusSquareFillIcon } from "@lifesg/react-icons/minus-square-fill"; +import { SquareIcon } from "@lifesg/react-icons/square"; +import { SquareTickFillIcon } from "@lifesg/react-icons/square-tick-fill"; +import { TickIcon } from "@lifesg/react-icons/tick"; +import clsx from "clsx"; +import type React from "react"; import { useEffect, useMemo, useRef, useState } from "react"; import { Virtuoso } from "react-virtuoso"; +import { Markup } from "../../markup"; import { mergeRefs, useEvent, useEventListener, useIsMounted, } from "../../util"; +import { ComponentLoadingSpinner } from "../component-loading-spinner"; import { useDropdownRender } from "../dropdown-wrapper"; +import { BasicButton } from "../input-wrapper"; import { DropdownLabel } from "./dropdown-label"; -import { - CheckboxSelectedIndicator, - CheckboxUnselectedIndicator, - Container, - LabelIcon, - List, - NoResultDescContainer, - ResultStateContainer, - SelectAllButton, - SelectAllContainer, - SelectedIndicator, - Spinner, - TryAgainButton, -} from "./dropdown-list.styles"; +import * as styles from "./dropdown-list.styles"; import { DropdownSearch } from "./dropdown-search"; -import { - CheckboxMixedIndicator, - ExpandButton, - Indent, - ListItem, - ListItemContainer, - SelectionIndicator, - UnexpandableIndicator, -} from "./nested-dropdown-list.styles"; +import * as nestedStyles from "./nested-dropdown-list.styles"; import { expandFirstSubtree, expandMatchedSubtrees, @@ -88,8 +77,12 @@ export const NestedDropdownList = ({ customLabels?.noResultsDescription || _noResultsDescription; const selectableCategory = multiSelect || _selectableCategory; - const { elementWidth, setFloatingRef, getFloatingProps, styles } = - useDropdownRender(); + const { + elementWidth, + setFloatingRef, + getFloatingProps, + styles: floatingStyles, + } = useDropdownRender(); const [searchValue, setSearchValue] = useState(""); const searchTerm = searchValue.toLowerCase().trim(); const [searchActive, setSearchActive] = useState(false); @@ -438,13 +431,17 @@ export const NestedDropdownList = ({ itemsLoadState === "success" ) { return ( - - +
+ {selectedKeyPaths.size === 0 ? selectAllButtonLabel : clearAllButtonLabel} - - + +
); } }; @@ -458,14 +455,23 @@ export const NestedDropdownList = ({ ) { return ( <> - - +
+ {noResultsLabel} - +
{noResultsDescription && ( - + {noResultsDescription} - + )} ); @@ -475,10 +481,13 @@ export const NestedDropdownList = ({ const renderLoading = () => { if (onRetry && itemsLoadState === "loading") { return ( - - +
+ Loading... - +
); } }; @@ -486,13 +495,23 @@ export const NestedDropdownList = ({ const renderTryAgain = () => { if (onRetry && itemsLoadState === "fail") { return ( - - +
+ Failed to load.  - + Try again. - - + +
); } }; @@ -500,11 +519,26 @@ export const NestedDropdownList = ({ if (multiSelect) { switch (listItem.checked) { case "mixed": - return ; + return ( + + ); case true: - return ; + return ( + + ); default: - return ; + return ( + + ); } } @@ -514,13 +548,20 @@ export const NestedDropdownList = ({ } return ( - - {listItem.checked && } - + {listItem.checked && ( + + )} + ); }; @@ -543,15 +584,30 @@ export const NestedDropdownList = ({ const toggleable = hasSubItems && !selectableCategory; return ( - - {maxLevel > 0 && } + {maxLevel > 0 && ( +
{ + if (node) { + node.style.setProperty( + nestedStyles.tokens.level, + String(level) + ); + } + }} + /> + )} {maxLevel > 0 && !hasSubItems && multiSelect && ( - +
)} - ({ } role="treeitem" tabIndex={active ? 0 : -1} - $active={active} - $toggleable={toggleable} + className={clsx( + nestedStyles.listItem, + active && nestedStyles.listItemActive, + toggleable && nestedStyles.listItemToggleable + )} > {hasSubItems && ( // not an actual button, only required for visual display - { e.stopPropagation(); toggleCategory(itemIndex, !expanded, vIndex); }} - $expanded={expanded} + className={clsx( + nestedStyles.expandButton, + expanded && nestedStyles.expandButtonExpanded + )} > - +
)} {renderSelectionIcon(listItem)} ({ truncationType={itemTruncationType} maxLines={itemMaxLines} /> - - +
+ ); }; @@ -635,28 +697,37 @@ export const NestedDropdownList = ({ const renderList = () => { return ( - +
{renderSearchInput()} {renderSelectAll()} {renderNoResults()} {renderLoading()} {renderTryAgain()} {renderVirtualisedList()} - +
); }; + const containerWidthStyle: React.CSSProperties = width + ? { width } + : matchElementWidth && elementWidth + ? { width: elementWidth } + : {}; + return ( - {renderList()} - + ); }; From fe854ce1f598a8627aee86948927115748162466 Mon Sep 17 00:00:00 2001 From: "Ziggy Z." Date: Thu, 16 Apr 2026 15:14:15 +0700 Subject: [PATCH 2/5] [BOOKINGSG-9157][ZZ] refactor: move inline style to useApplyStyle --- .../dropdown-list/nested-dropdown-list.tsx | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/shared/dropdown-list/nested-dropdown-list.tsx b/src/shared/dropdown-list/nested-dropdown-list.tsx index 8f2af0f4bf..de1ed535b2 100644 --- a/src/shared/dropdown-list/nested-dropdown-list.tsx +++ b/src/shared/dropdown-list/nested-dropdown-list.tsx @@ -10,6 +10,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { Virtuoso } from "react-virtuoso"; import { Markup } from "../../markup"; +import { useApplyStyle } from "../../theme"; import { mergeRefs, useEvent, @@ -253,6 +254,12 @@ export const NestedDropdownList = ({ } }; + const containerWidthStyle: React.CSSProperties = width + ? { width } + : matchElementWidth && elementWidth + ? { width: elementWidth } + : {}; + // ========================================================================= // HELPER FUNCTIONS // ========================================================================= @@ -403,6 +410,15 @@ export const NestedDropdownList = ({ } }, [focusedIndex, virtuosoIndex, mounted]); + // ========================================================================= + // APPLY STYLE + // ========================================================================= + + useApplyStyle(nodeRef, { + ...floatingStyles, + ...containerWidthStyle, + }); + // ========================================================================= // RENDER FUNCTIONS // ========================================================================= @@ -708,17 +724,10 @@ export const NestedDropdownList = ({ ); }; - const containerWidthStyle: React.CSSProperties = width - ? { width } - : matchElementWidth && elementWidth - ? { width: elementWidth } - : {}; - return (
Date: Thu, 16 Apr 2026 17:20:54 +0700 Subject: [PATCH 3/5] [BOOKINGSG-9157][ZZ] test: adding e2e test for dropdown-list --- .../dropdown-list/base-variants.e2e.tsx | 37 ++ .../dropdown-list/custom-cta.e2e.tsx | 33 ++ .../dropdown-list/keyboard-nav.e2e.tsx | 33 ++ .../dropdown-list/load-states.e2e.tsx | 43 ++ .../dropdown-list/multi-selection.e2e.tsx | 43 ++ .../components/dropdown-list/search.e2e.tsx | 25 ++ .../dropdown-list/single-selection.e2e.tsx | 33 ++ ...m-selects-it-single-selection-selected.png | Bin 0 -> 8301 bytes ...Custom-CTA---dark-mode-custom-cta-dark.png | Bin 0 -> 7383 bytes ...variant---dark-mode-base-variants-dark.png | Bin 0 -> 13566 bytes ...efault-and-small-variant-base-variants.png | Bin 0 -> 13501 bytes ...over-state-base-variants-hover-default.png | Bin 0 -> 6891 bytes ...-hover-state-base-variants-hover-small.png | Bin 0 -> 6414 bytes ...t-Loading---dark-mode-load-states-dark.png | Bin 0 -> 4112 bytes ...il-and-retry-callback-load-states-fail.png | Bin 0 -> 4829 bytes ...ng-fail-and-retry-callback-load-states.png | Bin 0 -> 2574 bytes ...s-at-the-bottom-of-the-list-custom-cta.png | Bin 0 -> 7276 bytes ...t-all---dark-mode-multi-selection-dark.png | Bin 0 -> 10169 bytes ...ng-and-no-results-flow-search-filtered.png | Bin 0 -> 3056 bytes ...-and-no-results-flow-search-no-results.png | Bin 0 -> 4945 bytes ...heir-selection-multi-selection-partial.png | Bin 0 -> 10385 bytes ...clear-all-multi-selection-all-selected.png | Bin 0 -> 10819 bytes .../dropdown-list/dropdown-list.e2e.spec.ts | 407 ++++++++++++++++++ 23 files changed, 654 insertions(+) create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/base-variants.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/custom-cta.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/keyboard-nav.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/load-states.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/multi-selection.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/search.e2e.tsx create mode 100644 e2e/nextjs-app/src/app/components/dropdown-list/single-selection.e2e.tsx create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Clicking-an-item-selects-it-single-selection-selected.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Custom-CTA---dark-mode-custom-cta-dark.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant---dark-mode-base-variants-dark.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant-base-variants.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Item-hover-activates-hover-state-base-variants-hover-default.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Item-hover-activates-hover-state-base-variants-hover-small.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading---dark-mode-load-states-dark.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading-fail-and-retry-callback-load-states-fail.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading-fail-and-retry-callback-load-states.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Renders-at-the-bottom-of-the-list-custom-cta.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Select-all---dark-mode-multi-selection-dark.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-filtered.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-no-results.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-clicking-items-toggles-their-selection-multi-selection-partial.png create mode 100644 e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-select-all-then-clear-all-multi-selection-all-selected.png create mode 100644 e2e/tests/components/dropdown-list/dropdown-list.e2e.spec.ts diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/base-variants.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/base-variants.e2e.tsx new file mode 100644 index 0000000000..e39104da36 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/base-variants.e2e.tsx @@ -0,0 +1,37 @@ +"use client"; + +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Option A", "Option B", "Option C", "Option D"]; + +export default function Story() { + return ( +
+
+ + + +
+
+ + + +
+
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/custom-cta.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/custom-cta.e2e.tsx new file mode 100644 index 0000000000..51df46cf90 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/custom-cta.e2e.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Option A", "Option B", "Option C"]; + +export default function Story() { + return ( +
+ + ( + + )} + /> + +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/keyboard-nav.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/keyboard-nav.e2e.tsx new file mode 100644 index 0000000000..50226d9b3c --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/keyboard-nav.e2e.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Option A", "Option B", "Option C", "Option D"]; + +export default function Story() { + const [selected, setSelected] = useState([]); + + const handleSelectItem = (item: unknown) => { + setSelected((prev) => (prev.includes(item) ? [] : [item])); + }; + + return ( +
+ + + +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/load-states.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/load-states.e2e.tsx new file mode 100644 index 0000000000..18e725c5b1 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/load-states.e2e.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useState } from "react"; +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +export default function Story() { + const [failRetried, setFailRetried] = useState(false); + + return ( +
+
+ + {}} + /> + +
+
+ + setFailRetried(true)} + /> + +
+ {failRetried && ( +
Retry triggered
+ )} +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/multi-selection.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/multi-selection.e2e.tsx new file mode 100644 index 0000000000..7e6367ce5c --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/multi-selection.e2e.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { useState } from "react"; +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Option A", "Option B", "Option C", "Option D"]; + +export default function Story() { + const [selected, setSelected] = useState([]); + + const handleSelectItem = (item: unknown) => { + setSelected((prev) => + prev.includes(item) + ? prev.filter((i) => i !== item) + : [...prev, item] + ); + }; + + const handleSelectAll = () => { + setSelected((prev) => (prev.length === ITEMS.length ? [] : [...ITEMS])); + }; + + return ( +
+ + + +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/search.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/search.e2e.tsx new file mode 100644 index 0000000000..0c24badb26 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/search.e2e.tsx @@ -0,0 +1,25 @@ +"use client"; + +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]; + +export default function Story() { + return ( +
+ + + +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/nextjs-app/src/app/components/dropdown-list/single-selection.e2e.tsx b/e2e/nextjs-app/src/app/components/dropdown-list/single-selection.e2e.tsx new file mode 100644 index 0000000000..8626da6b24 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/dropdown-list/single-selection.e2e.tsx @@ -0,0 +1,33 @@ +"use client"; + +import { useState } from "react"; +import { + DropdownList, + DropdownListState, +} from "@lifesg/react-design-system/shared/dropdown-list"; + +const ITEMS = ["Option A", "Option B", "Option C", "Option D"]; + +export default function Story() { + const [selected, setSelected] = useState([]); + + const handleSelectItem = (item: unknown) => { + setSelected((prev) => (prev.includes(item) ? [] : [item])); + }; + + return ( +
+ + + +
+ ); +} + +export const story = { init: Story }; diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Clicking-an-item-selects-it-single-selection-selected.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Clicking-an-item-selects-it-single-selection-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..d662a41da0497b3a0f68e985ecc484b0ec9a314d GIT binary patch literal 8301 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Custom-CTA---dark-mode-custom-cta-dark.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Custom-CTA---dark-mode-custom-cta-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..dcc5dd3dabd90583657ef0b072176d757feec304 GIT binary patch literal 7383 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 BxVHcR literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant---dark-mode-base-variants-dark.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant---dark-mode-base-variants-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3231a87f0ecb45e99297035c0dc9dadb0641b0c9 GIT binary patch literal 13566 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant-base-variants.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Default-and-small-variant-base-variants.png new file mode 100644 index 0000000000000000000000000000000000000000..c6c02d71800b553fb4cfa59795ec27bbef4c8ced GIT binary patch literal 13501 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Item-hover-activates-hover-state-base-variants-hover-small.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Item-hover-activates-hover-state-base-variants-hover-small.png new file mode 100644 index 0000000000000000000000000000000000000000..79851b41e068c617b4984b9c4a902091921d95d1 GIT binary patch literal 6414 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading---dark-mode-load-states-dark.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading---dark-mode-load-states-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..4a04bc9b5745e34d4d5e08df41f41ade44b963db GIT binary patch literal 4112 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading-fail-and-retry-callback-load-states.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Loading-fail-and-retry-callback-load-states.png new file mode 100644 index 0000000000000000000000000000000000000000..b8a808b1685070af51e49cb4c2d1e1213a280caa GIT binary patch literal 2574 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 B+p+)v literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Renders-at-the-bottom-of-the-list-custom-cta.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Renders-at-the-bottom-of-the-list-custom-cta.png new file mode 100644 index 0000000000000000000000000000000000000000..d349ffff4e20c6ca7c2945948d02215d9a074512 GIT binary patch literal 7276 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 Cm0c77 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Select-all---dark-mode-multi-selection-dark.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Select-all---dark-mode-multi-selection-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..07d61875c5e35482830643bbc627b9c0ef44dace GIT binary patch literal 10169 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-filtered.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-filtered.png new file mode 100644 index 0000000000000000000000000000000000000000..0a95992b77674ce06a33f037870dedb886b7918c GIT binary patch literal 3056 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 literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-no-results.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-Typing-clearing-and-no-results-flow-search-no-results.png new file mode 100644 index 0000000000000000000000000000000000000000..662c086a0fc7e6a124ff501fa3a92d41df5fdc5f GIT binary patch literal 4945 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 W`G@)IP2h@%^*Ot<)xZ7z$G-yxA+84i literal 0 HcmV?d00001 diff --git a/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-select-all-then-clear-all-multi-selection-all-selected.png b/e2e/tests/components/dropdown-list/__screenshots__/chromium/DropdownList-select-all-then-clear-all-multi-selection-all-selected.png new file mode 100644 index 0000000000000000000000000000000000000000..ad2b3368d5f3f880e9a733ca1c0565dc1da8129b GIT binary patch literal 10819 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 + story: async ({ page }, use) => { + const story = new StoryPage(page); + await use(story); + }, +}); + +test.describe("DropdownList", () => { + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("base-variants"); + }); + + test("Default and small variant", async ({ story }) => { + await expect( + story.locators.variantDefaultDropdownContainer + ).toBeVisible(); + await expect( + story.locators.variantSmallDropdownContainer + ).toBeVisible(); + + await expect(story.locators.variantDefaultDropdownList) + .toMatchAriaSnapshot(` + - group "Default variant": + - listbox: + - option "Option A" + - option "Option B" + - option "Option C" + - option "Option D" + `); + + await expect(story.locators.variantSmallDropdownList) + .toMatchAriaSnapshot(` + - group "Small variant": + - listbox: + - option "Option A" + - option "Option B" + - option "Option C" + - option "Option D" + `); + + await compareScreenshot(story, "base-variants"); + }); + + test("Item hover activates hover state", async ({ story }) => { + const defaultItems = story.getListItemsIn( + story.locators.variantDefault + ); + const smallItems = story.getListItemsIn( + story.locators.variantSmall + ); + + await defaultItems.first().hover(); + await compareScreenshot(story, "base-variants-hover-default", { + locator: story.locators.variantDefault, + }); + + await smallItems.first().hover(); + await compareScreenshot(story, "base-variants-hover-small", { + locator: story.locators.variantSmall, + }); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("base-variants", { mode: "dark" }); + }); + + test("Default and small variant - dark mode", async ({ story }) => { + await compareScreenshot(story, "base-variants-dark"); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("single-selection"); + }); + + test("Clicking an item selects it", async ({ story }) => { + const container = story.locators.singleSelectContainer; + const items = story.getListItemsIn(container); + + await expect(items.first()).toHaveAttribute( + "aria-selected", + "false" + ); + await items.first().click(); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "true" + ); + + await compareScreenshot(story, "single-selection-selected", { + locator: container, + }); + }); + + test("Clicking a selected item deselects it", async ({ story }) => { + const container = story.locators.singleSelectContainer; + const items = story.getListItemsIn(container); + + await items.first().click(); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "true" + ); + + await items.first().click(); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "false" + ); + }); + + test("Selecting a new item deselects the previous", async ({ + story, + }) => { + const container = story.locators.singleSelectContainer; + const items = story.getListItemsIn(container); + + await items.first().click(); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "true" + ); + + await items.nth(1).click(); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "false" + ); + await expect(items.nth(1)).toHaveAttribute("aria-selected", "true"); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("multi-selection"); + }); + + test("clicking items toggles their selection", async ({ story }) => { + const container = story.locators.multiSelectContainer; + const items = story.getListItemsIn(container); + + await items.first().click(); + await items.nth(1).click(); + + await expect(items.first()).toHaveAttribute( + "aria-selected", + "true" + ); + await expect(items.nth(1)).toHaveAttribute("aria-selected", "true"); + await expect(items.nth(2)).toHaveAttribute( + "aria-selected", + "false" + ); + + await compareScreenshot(story, "multi-selection-partial", { + locator: container, + }); + }); + + test("select all then clear all", async ({ story }) => { + const container = story.locators.multiSelectContainer; + const items = story.getListItemsIn(container); + + await container.getByRole("button", { name: "Select all" }).click(); + const count = await items.count(); + for (let i = 0; i < count; i++) { + await expect(items.nth(i)).toHaveAttribute( + "aria-selected", + "true" + ); + } + + await compareScreenshot(story, "multi-selection-all-selected", { + locator: container, + }); + + await container.getByRole("button", { name: "Clear all" }).click(); + for (let i = 0; i < count; i++) { + await expect(items.nth(i)).toHaveAttribute( + "aria-selected", + "false" + ); + } + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("multi-selection", { mode: "dark" }); + }); + + test("Select all - dark mode", async ({ story }) => { + await compareScreenshot(story, "multi-selection-dark"); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("search"); + }); + + test("Typing, clearing, and no-results flow", async ({ story }) => { + await story.locators.searchInput.fill("an"); + + const items = story.getListItemsIn(story.locators.searchContainer); + await expect(items).toHaveCount(1); + await expect(items.first()).toContainText("Banana"); + + await compareScreenshot(story, "search-filtered", { + locator: story.locators.searchContainer, + }); + + await story.locators.searchContainer + .getByRole("button", { name: "Clear" }) + .click(); + await expect(items).toHaveCount(5); + + await story.locators.searchInput.fill("zzz"); + await expect(story.locators.searchNoResults).toBeVisible(); + + await compareScreenshot(story, "search-no-results", { + locator: story.locators.searchContainer, + }); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("keyboard-nav"); + }); + + test("Arrow keys, enter, and space", async ({ story }) => { + const items = story.getListItemsIn( + story.locators.keyboardNavContainer + ); + + await items.first().focus(); + await story.page.keyboard.press("ArrowDown"); + await expect(items.nth(1)).toBeFocused(); + + await story.page.keyboard.press("ArrowUp"); + await expect(items.first()).toBeFocused(); + + await story.page.keyboard.press("Enter"); + await expect(items.first()).toHaveAttribute( + "aria-selected", + "true" + ); + + await story.page.keyboard.press("ArrowDown"); + await expect(items.nth(1)).toBeFocused(); + await story.page.keyboard.press("Space"); + await expect(items.nth(1)).toHaveAttribute("aria-selected", "true"); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("load-states"); + }); + + test("Loading, fail, and retry callback", async ({ story }) => { + await expect(story.locators.loadingState).toBeVisible(); + + await compareScreenshot(story, "load-states", { + locator: story.locators.loadingContainer, + }); + + await expect(story.locators.failState).toBeVisible(); + await expect( + story.locators.failContainer.getByRole("button", { + name: "Try again.", + }) + ).toBeVisible(); + + await compareScreenshot(story, "load-states-fail", { + locator: story.locators.failContainer, + }); + + await story.locators.failContainer + .getByRole("button", { name: "Try again." }) + .click(); + + await expect(story.locators.retryTriggered).toBeVisible(); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("load-states", { mode: "dark" }); + }); + + test("Loading - dark mode", async ({ story }) => { + await compareScreenshot(story, "load-states-dark"); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("custom-cta"); + }); + + test("Renders at the bottom of the list", async ({ story }) => { + await expect(story.locators.customCta).toBeVisible(); + await expect(story.locators.ctaButton).toBeVisible(); + + await compareScreenshot(story, "custom-cta", { + locator: story.locators.customCtaContainer, + }); + }); + }); + + test.describe(() => { + test.beforeEach(async ({ story }) => { + await story.init("custom-cta", { mode: "dark" }); + }); + + test("Custom CTA - dark mode", async ({ story }) => { + await compareScreenshot(story, "custom-cta-dark"); + }); + }); +}); From b07edcc7eae5a6bff619d7a1eb3c4a00a70e1349 Mon Sep 17 00:00:00 2001 From: "Ziggy Z." Date: Fri, 17 Apr 2026 10:40:59 +0700 Subject: [PATCH 4/5] [BOOKINGSG-9157][ZZ] test: unit test for dropdown-list --- .../dropdown-list/dropdown-list.spec.tsx | 309 ++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 tests/shared/dropdown-list/dropdown-list.spec.tsx diff --git a/tests/shared/dropdown-list/dropdown-list.spec.tsx b/tests/shared/dropdown-list/dropdown-list.spec.tsx new file mode 100644 index 0000000000..270cdb5217 --- /dev/null +++ b/tests/shared/dropdown-list/dropdown-list.spec.tsx @@ -0,0 +1,309 @@ +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { DropdownList } from "src/shared/dropdown-list/dropdown-list"; +import { DropdownListState } from "src/shared/dropdown-list/dropdown-list-state"; + +const ITEMS = ["Option A", "Option B", "Option C", "Option D"]; + +const renderList = ( + props: Partial> = {} +) => + render( + + + + ); + +describe("DropdownList", () => { + beforeEach(() => { + jest.clearAllMocks(); + + global.ResizeObserver = jest.fn().mockImplementation(() => ({ + observe: jest.fn(), + unobserve: jest.fn(), + disconnect: jest.fn(), + })); + }); + + // ========================================================================= + // Single selection + // ========================================================================= + describe("single selection", () => { + it("should call onSelectItem with the item when clicked", async () => { + const user = userEvent.setup(); + const onSelectItem = jest.fn(); + renderList({ onSelectItem }); + + await user.click(screen.getByRole("option", { name: "Option A" })); + + expect(onSelectItem).toHaveBeenCalledWith("Option A", "Option A"); + }); + + it("should mark item as selected when it is in selectedItems", () => { + renderList({ selectedItems: ["Option B"] }); + + expect( + screen.getByRole("option", { name: "Option B" }) + ).toHaveAttribute("aria-selected", "true"); + expect( + screen.getByRole("option", { name: "Option A" }) + ).toHaveAttribute("aria-selected", "false"); + }); + + it("should not mark item as selected when selectedItems is empty", () => { + renderList({ selectedItems: [] }); + + screen.getAllByRole("option").forEach((option) => { + expect(option).toHaveAttribute("aria-selected", "false"); + }); + }); + }); + + // ========================================================================= + // Multi-selection + // ========================================================================= + describe("multi-selection", () => { + it("should call onSelectItem for each item clicked", async () => { + const user = userEvent.setup(); + const onSelectItem = jest.fn(); + renderList({ multiSelect: true, selectedItems: [], onSelectItem }); + + await user.click(screen.getByRole("option", { name: "Option A" })); + await user.click(screen.getByRole("option", { name: "Option C" })); + + expect(onSelectItem).toHaveBeenCalledTimes(2); + expect(onSelectItem).toHaveBeenNthCalledWith( + 1, + "Option A", + "Option A" + ); + expect(onSelectItem).toHaveBeenNthCalledWith( + 2, + "Option C", + "Option C" + ); + }); + + it("should call onSelectAll when select all button is clicked", async () => { + const user = userEvent.setup(); + const onSelectAll = jest.fn(); + renderList({ + multiSelect: true, + selectedItems: [], + onSelectAll, + }); + + await user.click( + screen.getByRole("button", { name: "Select all" }) + ); + + expect(onSelectAll).toHaveBeenCalledTimes(1); + }); + + it("should show clear all button when items are selected", () => { + renderList({ + multiSelect: true, + selectedItems: ["Option A"], + onSelectAll: jest.fn(), + }); + + expect( + screen.getByRole("button", { name: "Clear all" }) + ).toBeInTheDocument(); + }); + + it("should not allow selecting beyond maxSelectable", async () => { + const user = userEvent.setup(); + const onSelectItem = jest.fn(); + renderList({ + multiSelect: true, + maxSelectable: 2, + selectedItems: ["Option A", "Option B"], + onSelectItem, + }); + + await user.click(screen.getByRole("option", { name: "Option C" })); + + expect(onSelectItem).not.toHaveBeenCalled(); + }); + }); + + // ========================================================================= + // Search + // ========================================================================= + describe("search", () => { + const SEARCH_ITEMS = [ + "Apple", + "Banana", + "Cherry", + "Date", + "Elderberry", + ]; + + it("should filter items matching the search term", async () => { + const user = userEvent.setup(); + renderList({ listItems: SEARCH_ITEMS, enableSearch: true }); + + await user.type( + screen.getByRole("textbox", { name: "Enter text to search" }), + "an" + ); + + expect(screen.getAllByRole("option")).toHaveLength(1); + expect( + screen.getByRole("option", { name: "Banana" }) + ).toBeInTheDocument(); + }); + + it("should show no-results element when nothing matches", async () => { + const user = userEvent.setup(); + renderList({ listItems: SEARCH_ITEMS, enableSearch: true }); + + await user.type( + screen.getByRole("textbox", { name: "Enter text to search" }), + "zzz" + ); + + expect(screen.getByTestId("list-no-results")).toBeInTheDocument(); + }); + + it("should restore all items after clearing the search", async () => { + const user = userEvent.setup(); + renderList({ listItems: SEARCH_ITEMS, enableSearch: true }); + + const input = screen.getByRole("textbox", { + name: "Enter text to search", + }); + await user.type(input, "Apple"); + expect(screen.getAllByRole("option")).toHaveLength(1); + + await user.clear(input); + expect(screen.getAllByRole("option")).toHaveLength( + SEARCH_ITEMS.length + ); + }); + }); + + // ========================================================================= + // Keyboard navigation + // ========================================================================= + describe("keyboard navigation", () => { + it("should move focus down on ArrowDown", async () => { + const user = userEvent.setup(); + renderList(); + + const options = screen.getAllByRole("option"); + options[0].focus(); + + await user.keyboard("{ArrowDown}"); + + expect(options[1]).toHaveFocus(); + }); + + it("should move focus up on ArrowUp", async () => { + const user = userEvent.setup(); + renderList(); + + const options = screen.getAllByRole("option"); + options[0].focus(); + + await user.keyboard("{ArrowDown}"); + await user.keyboard("{ArrowDown}"); + await user.keyboard("{ArrowUp}"); + + expect(options[1]).toHaveFocus(); + }); + + it("should call onSelectItem on Enter", async () => { + const user = userEvent.setup(); + const onSelectItem = jest.fn(); + renderList({ selectedItems: [], onSelectItem }); + + const options = screen.getAllByRole("option"); + options[0].focus(); + + await user.keyboard("{Enter}"); + + expect(onSelectItem).toHaveBeenCalledWith("Option A", "Option A"); + }); + + it("should call onSelectItem on Space", async () => { + const user = userEvent.setup(); + const onSelectItem = jest.fn(); + renderList({ selectedItems: [], onSelectItem }); + + const options = screen.getAllByRole("option"); + options[0].focus(); + + await user.keyboard("{ArrowDown}"); + await user.keyboard(" "); + + expect(onSelectItem).toHaveBeenCalledWith("Option B", "Option B"); + }); + }); + + // ========================================================================= + // Load states + // ========================================================================= + describe("load states", () => { + it("should show loading spinner when itemsLoadState is loading", () => { + renderList({ itemsLoadState: "loading", onRetry: jest.fn() }); + + expect(screen.getByTestId("list-loading")).toBeInTheDocument(); + }); + + it("should show fail state when itemsLoadState is fail", () => { + renderList({ itemsLoadState: "fail", onRetry: jest.fn() }); + + expect(screen.getByTestId("list-fail")).toBeInTheDocument(); + expect( + screen.getByRole("button", { name: "Try again." }) + ).toBeInTheDocument(); + }); + + it("should call onRetry when try again is clicked", async () => { + const user = userEvent.setup(); + const onRetry = jest.fn(); + renderList({ itemsLoadState: "fail", onRetry }); + + await user.click( + screen.getByRole("button", { name: "Try again." }) + ); + + expect(onRetry).toHaveBeenCalledTimes(1); + }); + }); + + // ========================================================================= + // Custom CTA + // ========================================================================= + describe("custom CTA", () => { + it("should render the custom call-to-action at the bottom", () => { + renderList({ + renderCustomCallToAction: () => ( + + ), + }); + + expect(screen.getByTestId("custom-cta")).toBeInTheDocument(); + expect( + screen.getByRole("button", { name: "Apply" }) + ).toBeInTheDocument(); + }); + + it("should pass the current display items to the custom CTA render function", () => { + const renderCustomCallToAction = jest.fn(() =>

CTA
); + renderList({ renderCustomCallToAction }); + + expect(renderCustomCallToAction).toHaveBeenCalledWith( + undefined, + ITEMS + ); + }); + }); +}); From 09e941dd0feb3117c683451b9bebbca1a994bc3c Mon Sep 17 00:00:00 2001 From: "Ziggy Z." Date: Fri, 17 Apr 2026 14:13:05 +0700 Subject: [PATCH 5/5] [BOOKINGSG-9157][ZZ] fix: change usage for dropdown variant in language-switcher --- .../dropdown-variant.style.tsx | 13 +++++---- src/language-switcher/dropdown-variant.tsx | 27 ++++++++++++++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/language-switcher/dropdown-variant.style.tsx b/src/language-switcher/dropdown-variant.style.tsx index 63601358e2..a9e4edacf0 100644 --- a/src/language-switcher/dropdown-variant.style.tsx +++ b/src/language-switcher/dropdown-variant.style.tsx @@ -2,11 +2,10 @@ import styled, { css } from "styled-components"; import { ExpandableElement } from "../shared/dropdown-list"; import { - ListItem, - SelectedIndicator, - UnselectedIndicator, + selectedIndicator, + unselectedIndicator, } from "../shared/dropdown-list/dropdown-list.styles"; -import { IconContainer } from "../shared/dropdown-list/expandable-element.styles"; +import { iconContainer } from "../shared/dropdown-list/expandable-element.styles"; import { Border, Colour, Font, Radius, Spacing } from "../theme"; // ============================================================================= @@ -23,7 +22,7 @@ export const StyledExpandableElement = styled(ExpandableElement)` border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; background: ${Colour["bg"]}; - ${IconContainer} { + .${iconContainer} { margin-left: auto; svg { @@ -68,9 +67,9 @@ export const DropdownList = styled.ul` padding: ${Spacing["spacing-8"]}; `; -export { SelectedIndicator, UnselectedIndicator }; +export { selectedIndicator, unselectedIndicator }; -export const DropdownItem = styled(ListItem)` +export const DropdownItem = styled.li<{ $selected: boolean }>` align-items: center; ${Font["body-md-regular"]} color: ${Colour["text"]}; diff --git a/src/language-switcher/dropdown-variant.tsx b/src/language-switcher/dropdown-variant.tsx index 1cd326bfe4..8746def838 100644 --- a/src/language-switcher/dropdown-variant.tsx +++ b/src/language-switcher/dropdown-variant.tsx @@ -1,7 +1,14 @@ import { LanguageIcon } from "@lifesg/react-icons/language"; +import { TickIcon } from "@lifesg/react-icons/tick"; +import clsx from "clsx"; import type React from "react"; import { useEffect, useRef, useState } from "react"; +import { + listItem, + listItemActive, + listItemActiveSelected, +} from "../shared/dropdown-list/dropdown-list.styles"; import type { DropdownRenderProps } from "../shared/dropdown-wrapper"; import { ElementWithDropdown } from "../shared/dropdown-wrapper"; import { SimpleIdGenerator } from "../util"; @@ -11,9 +18,9 @@ import { DropdownList, DropdownPanel, LanguageIconWrapper, - SelectedIndicator, + selectedIndicator, StyledExpandableElement, - UnselectedIndicator, + unselectedIndicator, } from "./dropdown-variant.style"; import type { VariantInternalProps } from "./internal-types"; import type { LanguageSwitcherCode } from "./types"; @@ -166,18 +173,26 @@ export const DropdownVariant = ({ }} role="option" lang={code} + className={clsx( + listItem, + isFocused && + isSelected && + listItemActiveSelected, + isFocused && !isSelected && listItemActive + )} aria-selected={isSelected} tabIndex={isFocused ? 0 : -1} - $active={isFocused} $selected={isSelected} - $disabled={false} onClick={() => handleItemSelect(code)} data-testid={`${testId}--item-${code}`} > {isSelected ? ( - + ) : ( - +
)} {LANGUAGE_DISPLAY_MAP[code]}