Skip to content

Update Chevron in Select to point sideways #633

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { render, fireEvent, screen } from '@testing-library/react';
import { describe, it, expect, beforeEach, vi } from 'vitest';
import '@testing-library/jest-dom/vitest';

import Select, { SelectOption } from './Select';
import Select from './Select';
import { SelectOption } from './SelectOptionType';
import { mockHTMLDialogElement } from '../../util/test-utils';

describe('Select', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Meta, StoryFn } from '@storybook/react';
import { Select, SelectOption } from './Select';
import { Select } from './Select';
import { SelectOption } from './SelectOptionType';

const meta: Meta<typeof Select> = {
component: Select,
Expand Down Expand Up @@ -31,6 +32,13 @@ function selectedOptionChanged(selectedItem: SelectOption | undefined) {
? console.log('Selected option: ' + selectedItem.label)
: console.log('No option selected');
}
function addModal(name: string, closeFunction: () => void) {
console.log('Add modal: ' + name);
closeFunction();
}
function closeModal() {
console.log('Close modal');
}

export const Default = {
args: {
Expand All @@ -41,6 +49,8 @@ export const Default = {
options: options,
placeholder: placeholder,
onChange: selectedOptionChanged,
addModal: addModal,
removeModal: closeModal,
},
};

Expand Down Expand Up @@ -131,3 +141,50 @@ export const SelectedOption: StoryFn<typeof Select> = () => {
</>
);
};

export const RTLLanguage: StoryFn<typeof Select> = () => {
const rtlOptions: SelectOption[] = [
{ label: 'الخيار 1', value: 'opt1' },
{ label: 'الخيار 2', value: 'opt2' },
{ label: 'الخيار 3 هو خيار بنص طويل جدًا', value: 'opt3' },
{ label: 'الخيار 4', value: 'opt4' },
{ label: 'الخيار 5', value: 'opt5' },
];

const rtlPlaceholder = 'اختر خيارًا';

return (
<div style={{ width: '100%' }}>
<h1>RTL Language Support</h1>

<h2>Arabic interface:</h2>
<div dir="rtl">
<Select
label="التصنيف"
variant="inVariableBox"
languageDirection="rtl"
options={rtlOptions}
placeholder={rtlPlaceholder}
onChange={selectedOptionChanged}
addModal={addModal}
removeModal={closeModal}
/>
</div>

<h2>Selected option with RTL:</h2>
<div dir="rtl">
<Select
label="التصنيف"
variant="inVariableBox"
languageDirection="rtl"
options={rtlOptions}
placeholder={rtlPlaceholder}
selectedOption={rtlOptions[1]}
onChange={selectedOptionChanged}
addModal={addModal}
removeModal={closeModal}
/>
</div>
</div>
);
};
21 changes: 15 additions & 6 deletions packages/pxweb2-ui/src/lib/components/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,18 @@ import cl from 'clsx';
import { useState, useEffect, useRef } from 'react';

import classes from './Select.module.scss';
import { SelectOption } from './SelectOptionType';
import Label from '../Typography/Label/Label';
import BodyShort from '../Typography/BodyShort/BodyShort';
import { Icon } from '../Icon/Icon';
import Modal from '../Modal/Modal';
import Radio from '../Radio/Radio';

export type SelectOption = {
label: string;
value: string;
};
import { getIconDirection } from '../../util/util';

export type SelectProps = {
variant?: 'default' | 'inVariableBox';
label: string;
languageDirection?: 'ltr' | 'rtl';
modalHeading?: string;
modalCancelLabel?: string;
modalConfirmLabel?: string;
Expand All @@ -38,6 +36,7 @@ function openOptions(options: SelectOption[]) {
export function Select({
variant = 'default',
label,
languageDirection = 'ltr',
modalHeading = '',
modalCancelLabel = '',
modalConfirmLabel = '',
Expand Down Expand Up @@ -70,6 +69,7 @@ export function Select({
{variant === 'inVariableBox' && (
<VariableBoxSelect
label={label}
languageDirection={languageDirection}
modalHeading={modalHeading}
modalCancelLabel={modalCancelLabel}
modalConfirmLabel={modalConfirmLabel}
Expand Down Expand Up @@ -161,12 +161,14 @@ type VariableBoxSelectProps = Pick<
| 'tabIndex'
| 'className'
> & {
languageDirection: 'ltr' | 'rtl';
addModal: (id: string, onClose: () => void) => void;
removeModal: (name: string) => void;
};

function VariableBoxSelect({
label,
languageDirection,
modalHeading,
modalCancelLabel,
modalConfirmLabel,
Expand Down Expand Up @@ -253,6 +255,13 @@ function VariableBoxSelect({
}
}, [removeModal, isModalOpen, addModal]);

// handle rtl for the icon
const chevronIcon = getIconDirection(
languageDirection,
'ChevronRight',
'ChevronLeft',
);

return (
<>
<div
Expand Down Expand Up @@ -294,7 +303,7 @@ function VariableBoxSelect({
{selectedItem ? selectedItem.label : placeholder}
</BodyShort>
</div>
<Icon iconName="ChevronDown" className=""></Icon>
<Icon iconName={chevronIcon} className=""></Icon>
</div>
<div className={cl(classes.divider)}></div>
{isModalOpen && (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export type SelectOption = {
label: string;
value: string;
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from 'react';
import cl from 'clsx';

import classes from './VariableBox.module.scss';
import { SelectOption } from '../Select/Select';
import { SelectOption } from '../Select/SelectOptionType';
import { VariableBoxHeader } from './VariableBoxHeader/VariableBoxHeader';
import { VariableBoxContent } from './VariableBoxContent/VariableBoxContent';
import { Variable } from '../../shared-types/variable';
Expand All @@ -18,6 +18,7 @@ export type VariableBoxPropsBase = Omit<Variable, 'notes'>;

export type VariableBoxProps = VariableBoxPropsBase & {
tableId: string;
languageDirection: 'ltr' | 'rtl';
initialIsOpen?: boolean;
onChangeCodeList: (
selectedItem: SelectOption | undefined,
Expand All @@ -39,6 +40,7 @@ export function VariableBox({
initialIsOpen,
tableId,
label,
languageDirection,
mandatory = false,
type,
values,
Expand Down Expand Up @@ -97,6 +99,7 @@ export function VariableBox({
varId={id}
type={type}
label={capitalizedVariableName}
languageDirection={languageDirection}
values={values}
codeLists={codeLists}
selectedValues={selectedValues}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ describe('VariableBoxContent', () => {
const { baseElement } = render(
<VariableBoxContent
label="test-1"
languageDirection="ltr"
type={VartypeEnum.REGULAR_VARIABLE}
values={[{ code: 'test-1', label: 'test-1' }]}
onChangeCodeList={() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { Virtuoso, VirtuosoHandle } from 'react-virtuoso';
import classes from './VariableBoxContent.module.scss';
import { Checkbox, MixedCheckbox } from '../../Checkbox/Checkbox';
import Search from '../../Search/Search';
import { Select, SelectOption } from '../../Select/Select';
import { Select } from '../../Select/Select';
import { SelectOption } from '../../Select/SelectOptionType';
import { VariableBoxProps, SelectedVBValues } from '../VariableBox';
import { VartypeEnum } from '../../../shared-types/vartypeEnum';
import { Value } from '../../../shared-types/value';
Expand All @@ -34,6 +35,7 @@ type VariableBoxContentProps = VariableBoxPropsToContent & {
selectedValues: SelectedVBValues[];
totalValues: number;
totalChosenValues: number;
languageDirection: 'ltr' | 'rtl';
onChangeCodeList: (
selectedItem: SelectOption | undefined,
varId: string,
Expand All @@ -51,6 +53,7 @@ type VariableBoxContentProps = VariableBoxPropsToContent & {
export function VariableBoxContent({
varId,
label,
languageDirection,
type,
values,
codeLists,
Expand Down Expand Up @@ -537,6 +540,7 @@ export function VariableBoxContent({
label={t(
'presentation_page.sidemenu.selection.variablebox.content.select.label',
)}
languageDirection={languageDirection}
modalHeading={label}
modalCancelLabel={t(
'presentation_page.sidemenu.selection.variablebox.content.select.modal.cancel_button',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { describe, it, expect } from 'vitest';

import { CodeList } from '../../shared-types/codelist';
import { SelectOption } from '../Select/Select';
import { SelectOption } from '../Select/SelectOptionType';
import { sortSelectOptionsGroupingsLast, mapAndSortCodeLists } from './utils';

const vsOptions: SelectOption[] = [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { SelectOption } from '../Select/Select';
import { SelectOption } from '../Select/SelectOptionType';
import { CodeList } from '../../shared-types/codelist';
import { mapCodeListsToSelectOptions } from '../../util/util';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ import cl from 'clsx';
import styles from './VariableList.module.scss';
import { SelectedVBValues, VariableBox } from '../VariableBox/VariableBox';
import { PxTableMetadata } from '../../shared-types/pxTableMetadata';
import { SelectOption } from '../Select/Select';
import { SelectOption } from '../Select/SelectOptionType';
import { Value } from '../../shared-types/value';

export type VariableListProps = {
pxTableMetadata: PxTableMetadata | null;
isLoadingMetadata: boolean;
languageDirection: 'ltr' | 'rtl';
hasLoadedDefaultSelection: boolean;
isChangingCodeList: boolean;
selectedVBValues: SelectedVBValues[];
Expand All @@ -31,6 +32,7 @@ export type VariableListProps = {
export function VariableList({
pxTableMetadata,
isLoadingMetadata,
languageDirection,
hasLoadedDefaultSelection,
isChangingCodeList = false,
selectedVBValues,
Expand Down Expand Up @@ -59,6 +61,7 @@ export function VariableList({
initialIsOpen={index === 0}
tableId={pxTableMetadata.id}
label={variable.label}
languageDirection={languageDirection}
mandatory={variable.mandatory}
type={variable.type}
values={variable.values}
Expand Down
2 changes: 0 additions & 2 deletions packages/pxweb2-ui/src/lib/shared-types/variable.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { CodeList } from './codelist';
import { Note } from './note';
import { Value } from './value';
import { ValueDisplayType } from './valueDisplayType';
import { VartypeEnum } from './vartypeEnum';

export type Variable = {
Expand All @@ -12,5 +11,4 @@ export type Variable = {
values: Value[];
codeLists?: CodeList[];
notes?: Note[];
valueDisplayType: ValueDisplayType;
};
2 changes: 1 addition & 1 deletion packages/pxweb2-ui/src/lib/util/util.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
mapCodeListsToSelectOptions,
} from './util';
import { CodeList } from '../shared-types/codelist';
import { SelectOption } from '../components/Select/Select';
import { SelectOption } from '../components/Select/SelectOptionType';

describe('getCSSVariable', () => {
beforeEach(() => {
Expand Down
21 changes: 20 additions & 1 deletion packages/pxweb2-ui/src/lib/util/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CodeList } from '../shared-types/codelist';
import { SelectOption } from '../components/Select/Select';
import { SelectOption } from '../components/Select/SelectOptionType';
import { IconProps } from '../components/Icon/Icon';

export const getCSSVariable = (variable: string): string => {
const rootStyle = getComputedStyle(document.documentElement);
Expand All @@ -23,3 +24,21 @@ export const mapCodeListsToSelectOptions = (
value: code.id,
}));
};

/**
* Returns the icon direction based on the RTL setting.
*
* @param isRtl - A boolean indicating whether the layout is RTL (right-to-left).
* @param iconLeft - The icon to use for left-to-right layout.
* @param iconRight - The icon to use for right-to-left layout.
* @returns The icon direction as a string.
*/
export function getIconDirection(
langDir: 'ltr' | 'rtl',
iconForLtl: IconProps['iconName'],
iconForRtl: IconProps['iconName'],
): IconProps['iconName'] {
const isRtl = langDir === 'rtl';

return isRtl ? iconForRtl : iconForLtl;
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React, { forwardRef } from 'react';
import cl from 'clsx';
import styles from './NavigationDrawer.module.scss';
import { Heading, Icon, Label } from '@pxweb2/pxweb2-ui';
import { useTranslation } from 'react-i18next';

import styles from './NavigationDrawer.module.scss';
import { Heading, Icon, getIconDirection, Label } from '@pxweb2/pxweb2-ui';
import i18next from 'i18next';
import useAccessibility from '../../context/useAccessibility';
import useApp from '../../context/useApp';
Expand Down Expand Up @@ -36,8 +37,12 @@ export const NavigationDrawer = forwardRef<
};
}, [addModal, removeModal, onClose, view]);

// Handle RTL languages
const hideIcon = i18next.dir() === 'rtl' ? 'ChevronRight' : 'ChevronLeft';
// Handle RTL languages for the icon
const hideIcon = getIconDirection(
i18next.dir(),
'ChevronLeft',
'ChevronRight',
);

function handleKeyDown(event: React.KeyboardEvent<HTMLDivElement>) {
if (event.key === 'Enter' || event.key === ' ') {
Expand Down
Loading