diff --git a/e2e/nextjs-app/src/app/components/[component]/[story]/page.tsx b/e2e/nextjs-app/src/app/components/[component]/[story]/page.tsx index 59fdf9d8f8..63f1e33172 100644 --- a/e2e/nextjs-app/src/app/components/[component]/[story]/page.tsx +++ b/e2e/nextjs-app/src/app/components/[component]/[story]/page.tsx @@ -18,6 +18,7 @@ const CSR_ONLY_COMPONENTS = new Set([ "nested-select", "nested-multi-select", "input-group", + "language-switcher", ]); export default async function Page({ diff --git a/e2e/nextjs-app/src/app/components/language-switcher/dropdown-default.e2e.tsx b/e2e/nextjs-app/src/app/components/language-switcher/dropdown-default.e2e.tsx new file mode 100644 index 0000000000..1af17bc9db --- /dev/null +++ b/e2e/nextjs-app/src/app/components/language-switcher/dropdown-default.e2e.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { + LanguageSwitcher, + type LanguageSwitcherCode, +} from "@lifesg/react-design-system/language-switcher"; +import { useState } from "react"; + +export default function Story() { + const [language, setLanguage] = useState( + undefined + ); + + return ( +
+ +
+ ); +} diff --git a/e2e/nextjs-app/src/app/components/language-switcher/dropdown-preselected.e2e.tsx b/e2e/nextjs-app/src/app/components/language-switcher/dropdown-preselected.e2e.tsx new file mode 100644 index 0000000000..697e6e1137 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/language-switcher/dropdown-preselected.e2e.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { + LanguageSwitcher, + type LanguageSwitcherCode, +} from "@lifesg/react-design-system/language-switcher"; +import { useState } from "react"; + +export default function Story() { + const [language, setLanguage] = useState("zh"); + + return ( +
+ +
+ ); +} diff --git a/e2e/nextjs-app/src/app/components/language-switcher/link-default.e2e.tsx b/e2e/nextjs-app/src/app/components/language-switcher/link-default.e2e.tsx new file mode 100644 index 0000000000..78ccba65cb --- /dev/null +++ b/e2e/nextjs-app/src/app/components/language-switcher/link-default.e2e.tsx @@ -0,0 +1,24 @@ +"use client"; + +import { + LanguageSwitcher, + type LanguageSwitcherCode, +} from "@lifesg/react-design-system/language-switcher"; +import { useState } from "react"; + +export default function Story() { + const [language, setLanguage] = useState( + undefined + ); + + return ( +
+ +
+ ); +} diff --git a/e2e/nextjs-app/src/app/components/language-switcher/link-preselected.e2e.tsx b/e2e/nextjs-app/src/app/components/language-switcher/link-preselected.e2e.tsx new file mode 100644 index 0000000000..9ac18eabe8 --- /dev/null +++ b/e2e/nextjs-app/src/app/components/language-switcher/link-preselected.e2e.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { + LanguageSwitcher, + type LanguageSwitcherCode, +} from "@lifesg/react-design-system/language-switcher"; +import { useState } from "react"; + +export default function Story() { + const [language, setLanguage] = useState("ta"); + + return ( +
+ +
+ ); +} diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--mount.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--mount.png new file mode 100644 index 0000000000..f80c03ebce Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--mount.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--open.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--open.png new file mode 100644 index 0000000000..e8c2fe0191 Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default--open.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--mount.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--mount.png new file mode 100644 index 0000000000..3cd02c40cb Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--mount.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--open.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--open.png new file mode 100644 index 0000000000..28974f37bc Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Default-Dark-Mode--open.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Preselected--mount.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Preselected--mount.png new file mode 100644 index 0000000000..256ffb270f Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Dropdown-Preselected--mount.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Default--mount.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Default--mount.png new file mode 100644 index 0000000000..2c1e589c62 Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Default--mount.png differ diff --git a/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Preselected--mount.png b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Preselected--mount.png new file mode 100644 index 0000000000..04e8ac0d48 Binary files /dev/null and b/e2e/tests/components/language-switcher/__screenshots__/chromium/LanguageSwitcher-Link-Preselected--mount.png differ diff --git a/e2e/tests/components/language-switcher/language-switcher.e2e.spec.ts b/e2e/tests/components/language-switcher/language-switcher.e2e.spec.ts new file mode 100644 index 0000000000..b24a6d60f9 --- /dev/null +++ b/e2e/tests/components/language-switcher/language-switcher.e2e.spec.ts @@ -0,0 +1,180 @@ +import { test as base, expect, Locator, Page } from "@playwright/test"; +import { AbstractStoryPage, compareScreenshot } from "../../utils"; + +class StoryPage extends AbstractStoryPage { + protected readonly component = "language-switcher"; + + public readonly locators: { + internal: { + trigger: Locator; + panel: Locator; + }; + languageSwitcher: Locator; + }; + + constructor(page: Page) { + super(page); + + this.locators = { + internal: { + trigger: page.getByTestId("language-switcher--trigger"), + panel: page.getByTestId("language-switcher--panel"), + }, + languageSwitcher: page.getByTestId("language-switcher"), + }; + } + + public getDropdownOption(name: string) { + return this.page.getByRole("option", { name }); + } + + public getLinkButton(name: string) { + return this.page.getByRole("button", { name, exact: true }); + } +} + +const test = base.extend<{ story: StoryPage }>({ + story: async ({ page }, use) => { + const story = new StoryPage(page); + await use(story); + }, +}); + +test.describe("LanguageSwitcher", () => { + test.describe("Dropdown", () => { + test.describe("", () => { + test.beforeEach(async ({ story }) => { + await story.init("dropdown-default"); + }); + + test("Default", async ({ story }) => { + await compareScreenshot(story, "mount", { + locator: story.locators.languageSwitcher, + }); + + await expect(story.locators.languageSwitcher) + .toMatchAriaSnapshot(` + - combobox "Choose language / 选择语言 / Pilih bahasa / மொழியை தேர்ந்தெடுக்கவும், English" + `); + + await story.locators.internal.trigger.click(); + await compareScreenshot(story, "open", { + fullscreen: true, + }); + + await expect(story.locators.languageSwitcher) + .toMatchAriaSnapshot(` + - combobox "Choose language / 选择语言 / Pilih bahasa / மொழியை தேர்ந்தெடுக்கவும், English" [expanded] + - listbox "Choose language / 选择语言 / Pilih bahasa / மொழியை தேர்ந்தெடுக்கவும்": + - option "English" [selected] + - option "中文" + - option "Melayu" + - option "தமிழ்" + `); + }); + + test("Keyboard Interaction", async ({ story }) => { + await story.locators.internal.trigger.focus(); + await story.page.keyboard.press("Enter"); + await expect(story.locators.internal.panel).toBeVisible(); + + await story.page.keyboard.press("ArrowDown"); + await expect(story.getDropdownOption("中文")).toBeFocused(); + + await story.page.keyboard.press("End"); + await expect(story.getDropdownOption("தமிழ்")).toBeFocused(); + + await story.page.keyboard.press("Home"); + await expect(story.getDropdownOption("English")).toBeFocused(); + + await story.page.keyboard.press("ArrowDown"); + await story.page.keyboard.press("Enter"); + await expect(story.locators.internal.panel).not.toBeVisible(); + await expect(story.locators.internal.trigger).toContainText( + "中文" + ); + + await story.page.keyboard.press("Enter"); + await expect(story.locators.internal.panel).toBeVisible(); + await story.page.keyboard.press("Escape"); + await expect(story.locators.internal.panel).not.toBeVisible(); + }); + }); + + test.describe("", () => { + test.beforeEach(async ({ story }) => { + await story.init("dropdown-default", { mode: "dark" }); + }); + + test("Default Dark Mode", async ({ story }) => { + await compareScreenshot(story, "mount", { + locator: story.locators.languageSwitcher, + }); + + await story.locators.internal.trigger.click(); + await compareScreenshot(story, "open", { + fullscreen: true, + }); + }); + }); + + test.describe("", () => { + test.beforeEach(async ({ story }) => { + await story.init("dropdown-preselected"); + }); + + test("Preselected", async ({ story }) => { + await expect(story.locators.internal.trigger).toContainText( + "中文" + ); + + await compareScreenshot(story, "mount", { + locator: story.locators.languageSwitcher, + }); + }); + }); + }); + + test.describe("Link", () => { + test.describe("", () => { + test.beforeEach(async ({ story }) => { + await story.init("link-default"); + }); + + test("Default", async ({ story }) => { + await expect(story.locators.languageSwitcher) + .toMatchAriaSnapshot(` + - group "Choose language / 选择语言 / Pilih bahasa / மொழியை தேர்ந்தெடுக்கவும்": + - listitem: + - button "English" [pressed] + - listitem: + - button "中文" + - listitem: + - button "Melayu" + - listitem: + - button "தமிழ்" + `); + + await compareScreenshot(story, "mount", { + locator: story.locators.languageSwitcher, + }); + }); + }); + + test.describe("", () => { + test.beforeEach(async ({ story }) => { + await story.init("link-preselected"); + }); + + test("Preselected", async ({ story }) => { + const tamil = story.getLinkButton("தமிழ்"); + + await expect(tamil).toHaveAttribute("aria-pressed", "true"); + + await compareScreenshot(story, "mount", { + locator: story.locators.languageSwitcher, + }); + }); + }); + }); +}); diff --git a/src/language-switcher/dropdown-panel.styles.ts b/src/language-switcher/dropdown-panel.styles.ts new file mode 100644 index 0000000000..219563139d --- /dev/null +++ b/src/language-switcher/dropdown-panel.styles.ts @@ -0,0 +1,47 @@ +import { css } from "@linaria/core"; + +import { Border, Colour, Font, Radius, Spacing } from "../theme"; + +export const tokens = { + width: "--fds-internal-languageSwitcher-dropdown-width", +} as const; + +export const dropdownPanel = css` + ${tokens.width}: initial; + + width: var(${tokens.width}); + border-radius: ${Radius["sm"]}; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + background: ${Colour["bg"]}; + overflow: hidden; +`; + +export const dropdownList = css` + list-style: none; + margin: 0; + padding: ${Spacing["spacing-8"]}; +`; + +export { + baseIndicatorStyle, + selectedIndicator, +} from "../shared/dropdown-list/dropdown-list.styles"; + +export const dropdownItem = css` + align-items: center; + ${Font["body-md-regular"]} + color: ${Colour["text"]}; + + &:hover { + background: ${Colour["bg-hover-subtle"]}; + } +`; + +export const dropdownItemSelected = css` + background: transparent; + color: ${Colour["text-selected"]}; + + &:hover { + background: ${Colour["bg-hover"]}; + } +`; diff --git a/src/language-switcher/dropdown-panel.tsx b/src/language-switcher/dropdown-panel.tsx new file mode 100644 index 0000000000..6ca7f486b6 --- /dev/null +++ b/src/language-switcher/dropdown-panel.tsx @@ -0,0 +1,109 @@ +import { TickIcon } from "@lifesg/react-icons/tick"; +import clsx from "clsx"; +import type React from "react"; +import { useRef } from "react"; + +import { + baseIndicatorStyle, + listItem, + listItemActive, + listItemActiveSelected, +} from "../shared/dropdown-list/dropdown-list.styles"; +import { useDropdownRender } from "../shared/dropdown-wrapper"; +import { useApplyStyle } from "../theme"; +import { mergeRefs } from "../util"; +import { ARIA_LABEL, LANGUAGE_CODES, LANGUAGE_DISPLAY_MAP } from "./data"; +import * as styles from "./dropdown-panel.styles"; +import type { LanguageSwitcherCode } from "./types"; + +interface DropdownPanelProps { + focusedIndex: number; + handleItemSelect: (code: LanguageSwitcherCode) => void; + handleListKeyDown: (event: React.KeyboardEvent) => void; + itemRefs: React.MutableRefObject<(HTMLLIElement | null)[]>; + listboxId: string; + selectedLanguage: LanguageSwitcherCode; + testId: string; +} + +export const DropdownPanel = ({ + focusedIndex, + handleItemSelect, + handleListKeyDown, + itemRefs, + listboxId, + selectedLanguage, + testId, +}: DropdownPanelProps) => { + const { + elementWidth, + styles: floatingStyles, + setFloatingRef, + getFloatingProps, + } = useDropdownRender(); + const panelRef = useRef(null); + + useApplyStyle(panelRef, { + [styles.tokens.width]: `${elementWidth}px`, + }); + + return ( +
+
    + {LANGUAGE_CODES.map((code, index) => { + const isSelected = code === selectedLanguage; + const isFocused = index === focusedIndex; + + return ( +
  • { + itemRefs.current[index] = element; + }} + role="option" + lang={code} + className={clsx( + styles.dropdownItem, + listItem, + isFocused && + isSelected && + listItemActiveSelected, + isFocused && !isSelected && listItemActive, + isSelected && styles.dropdownItemSelected + )} + aria-selected={isSelected} + tabIndex={isFocused ? 0 : -1} + onClick={() => handleItemSelect(code)} + data-testid={`${testId}--item-${code}`} + > + {isSelected ? ( + + ) : ( +
    + )} + {LANGUAGE_DISPLAY_MAP[code]} +
  • + ); + })} +
+
+ ); +}; diff --git a/src/language-switcher/dropdown-variant.style.tsx b/src/language-switcher/dropdown-variant.style.tsx deleted file mode 100644 index eb51afc417..0000000000 --- a/src/language-switcher/dropdown-variant.style.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import styled, { css } from "styled-components"; - -import { ExpandableElement } from "../shared/dropdown-list"; -import { - baseIndicatorStyle, - selectedIndicator, -} from "../shared/dropdown-list/dropdown-list.styles"; -import { iconContainer } from "../shared/dropdown-list/expandable-element.styles"; -import { Border, Colour, Font, Radius, Spacing } from "../theme"; - -// ============================================================================= -// TRIGGER STYLES -// ============================================================================= -export const StyledExpandableElement = styled(ExpandableElement)` - min-width: 9rem; - width: auto; - ${Font["body-md-semibold"]} - color: ${Colour["text-primary"]}; - height: 2.5rem; - padding: 0 ${Spacing["spacing-16"]}; - border-radius: ${Radius["sm"]}; - border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; - background: ${Colour["bg"]}; - - .${iconContainer} { - margin-left: auto; - - svg { - color: ${Colour["text-selected"]}; - } - } - - &:focus-visible { - outline: 2px solid ${Colour["focus-ring"]}; - outline-offset: -2px; - } -`; - -const IconWrapper = css` - display: flex; - align-items: center; - - svg { - height: 1rem; - width: 1rem; - } -`; - -export const LanguageIconWrapper = styled.span` - ${IconWrapper} - color: ${Colour["icon-primary"]}; -`; - -// ============================================================================= -// DROPDOWN STYLES -// ============================================================================= -export const DropdownPanel = styled.div` - border-radius: ${Radius["sm"]}; - border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; - background: ${Colour["bg"]}; - overflow: hidden; -`; - -export const DropdownList = styled.ul` - list-style: none; - margin: 0; - padding: ${Spacing["spacing-8"]}; -`; - -export { baseIndicatorStyle, selectedIndicator }; - -export const DropdownItem = styled.li<{ $selected: boolean }>` - align-items: center; - ${Font["body-md-regular"]} - color: ${Colour["text"]}; - - &:hover { - background: ${Colour["bg-hover-subtle"]}; - } - - ${(props) => - props.$selected && - css` - background: transparent; - color: ${Colour["text-selected"]}; - - &:hover { - background: ${Colour["bg-hover"]}; - } - `} -`; diff --git a/src/language-switcher/dropdown-variant.styles.ts b/src/language-switcher/dropdown-variant.styles.ts new file mode 100644 index 0000000000..551707ccb3 --- /dev/null +++ b/src/language-switcher/dropdown-variant.styles.ts @@ -0,0 +1,40 @@ +import { css } from "@linaria/core"; + +import { iconContainer } from "../shared/dropdown-list/expandable-element.styles"; +import { Border, Colour, Font, Radius, Spacing } from "../theme"; + +export const expandableElement = css` + min-width: 9rem; + width: auto; + ${Font["body-md-semibold"]} + color: ${Colour["text-primary"]}; + height: 2.5rem; + padding: 0 ${Spacing["spacing-16"]}; + border-radius: ${Radius["sm"]}; + border: ${Border["width-010"]} ${Border["solid"]} ${Colour["border"]}; + background: ${Colour["bg"]}; + + .${iconContainer} { + margin-left: auto; + + svg { + color: ${Colour["text-selected"]}; + } + } + + &:focus-visible { + outline: 2px solid ${Colour["focus-ring"]}; + outline-offset: -2px; + } +`; + +export const languageIconWrapper = css` + display: flex; + align-items: center; + color: ${Colour["icon-primary"]}; + + svg { + height: 1rem; + width: 1rem; + } +`; diff --git a/src/language-switcher/dropdown-variant.tsx b/src/language-switcher/dropdown-variant.tsx index 1dfa9c8610..f40e9a81da 100644 --- a/src/language-switcher/dropdown-variant.tsx +++ b/src/language-switcher/dropdown-variant.tsx @@ -1,27 +1,13 @@ 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 { - baseIndicatorStyle, - listItem, - listItemActive, - listItemActiveSelected, -} from "../shared/dropdown-list/dropdown-list.styles"; -import type { DropdownRenderProps } from "../shared/dropdown-wrapper"; +import { ExpandableElement } from "../shared/dropdown-list"; import { ElementWithDropdown } from "../shared/dropdown-wrapper"; import { useId } from "../util"; import { ARIA_LABEL, LANGUAGE_CODES, LANGUAGE_DISPLAY_MAP } from "./data"; -import { - DropdownItem, - DropdownList, - DropdownPanel, - LanguageIconWrapper, - selectedIndicator, - StyledExpandableElement, -} from "./dropdown-variant.style"; +import { DropdownPanel } from "./dropdown-panel"; +import * as styles from "./dropdown-variant.styles"; import type { VariantInternalProps } from "./internal-types"; import type { LanguageSwitcherCode } from "./types"; @@ -127,8 +113,9 @@ export const DropdownVariant = ({ // RENDER FUNCTIONS // ========================================================================= const renderElement = () => ( - - + - + {LANGUAGE_DISPLAY_MAP[selectedLanguage]} - + ); - const renderDropdown = ({ - elementWidth, - styles, - setFloatingRef, - getFloatingProps, - }: DropdownRenderProps) => ( + const renderDropdown = () => ( - - {LANGUAGE_CODES.map((code, index) => { - const isSelected = code === selectedLanguage; - const isFocused = index === focusedIndex; - return ( - { - itemRefs.current[index] = el; - }} - role="option" - lang={code} - className={clsx( - listItem, - isFocused && - isSelected && - listItemActiveSelected, - isFocused && !isSelected && listItemActive - )} - aria-selected={isSelected} - tabIndex={isFocused ? 0 : -1} - $selected={isSelected} - onClick={() => handleItemSelect(code)} - data-testid={`${testId}--item-${code}`} - > - {isSelected ? ( - - ) : ( -
- )} - {LANGUAGE_DISPLAY_MAP[code]} - - ); - })} - - + focusedIndex={focusedIndex} + handleItemSelect={handleItemSelect} + handleListKeyDown={handleListKeyDown} + itemRefs={itemRefs} + listboxId={listboxId} + selectedLanguage={selectedLanguage} + testId={testId} + /> ); // ========================================================================= diff --git a/src/language-switcher/link-container-variant.style.tsx b/src/language-switcher/link-container-variant.styles.ts similarity index 55% rename from src/language-switcher/link-container-variant.style.tsx rename to src/language-switcher/link-container-variant.styles.ts index e345bf50c0..9c7672ec05 100644 --- a/src/language-switcher/link-container-variant.style.tsx +++ b/src/language-switcher/link-container-variant.styles.ts @@ -1,18 +1,11 @@ -import styled, { css } from "styled-components"; +import { css } from "@linaria/core"; import { Border, Colour, Font, Motion, Radius, Spacing } from "../theme"; -// ============================================================================= -// STYLE INTERFACES -// ============================================================================= -interface LinkItemStyleProps { - $active?: boolean; -} - // ============================================================================= // LINK CONTAINER STYLES // ============================================================================= -export const LinkContainerWrapper = styled.div` +export const linkContainerWrapper = css` display: inline-flex; padding: ${Spacing["spacing-8"]} ${Spacing["spacing-16"]}; align-items: center; @@ -21,7 +14,7 @@ export const LinkContainerWrapper = styled.div` background: ${Colour["bg"]}; `; -export const LinkList = styled.ul` +export const linkList = css` display: flex; list-style: none; margin: 0; @@ -31,12 +24,12 @@ export const LinkList = styled.ul` flex-wrap: wrap; `; -export const LinkListItem = styled.li` +export const linkListItem = css` display: flex; align-items: center; `; -export const LinkItem = styled.button` +export const linkItem = css` display: flex; padding: 0.25rem 0.5rem; justify-content: center; @@ -48,26 +41,27 @@ export const LinkItem = styled.button` color: ${Colour["text-subtler"]}; text-align: center; transition: color ${Motion["duration-150"]} ${Motion["ease-default"]}; + background: none; + cursor: pointer; - ${({ $active }) => - $active - ? css` - background: ${Colour["bg-primary-subtler"]}; - color: ${Colour["text-selected"]}; - cursor: default; - ` - : css` - background: none; - cursor: pointer; - - &:hover { - color: ${Colour["text-hover"]}; - text-decoration: underline; - } - `} + &:hover { + color: ${Colour["text-hover"]}; + text-decoration: underline; + } &:focus-visible { outline: 2px solid ${Colour["focus-ring"]}; outline-offset: -2px; } `; + +export const linkItemActive = css` + background: ${Colour["bg-primary-subtler"]}; + color: ${Colour["text-selected"]}; + cursor: default; + + &:hover { + color: ${Colour["text-selected"]}; + text-decoration: none; + } +`; diff --git a/src/language-switcher/link-container-variant.tsx b/src/language-switcher/link-container-variant.tsx index 6c41973a63..8a7671ceb9 100644 --- a/src/language-switcher/link-container-variant.tsx +++ b/src/language-switcher/link-container-variant.tsx @@ -1,19 +1,16 @@ +import clsx from "clsx"; import type React from "react"; import { useRef } from "react"; import { ARIA_LABEL, LANGUAGE_CODES, LANGUAGE_DISPLAY_MAP } from "./data"; import type { VariantInternalProps } from "./internal-types"; -import { - LinkContainerWrapper, - LinkItem, - LinkList, - LinkListItem, -} from "./link-container-variant.style"; +import * as styles from "./link-container-variant.styles"; export const LinkContainerVariant = ({ selectedLanguage, onSelectLanguage, testId, + className, ...otherProps }: VariantInternalProps): JSX.Element => { // ========================================================================= @@ -58,19 +55,30 @@ export const LinkContainerVariant = ({ // RENDER // ========================================================================= return ( - - +
+
    {LANGUAGE_CODES.map((code, index) => { const isActive = code === selectedLanguage; return ( - - + + ); })} - - +
+
); };