diff --git a/README.md b/README.md index 5de5ac64..fe4d0aa3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # @folio/linked-data -© 2024 EBSCO Information Services. +Copyright (C) 2024 The Open Library Foundation This software is distributed under the terms of the Apache License, Version 2.0. See the file "[LICENSE](LICENSE)" for more information. diff --git a/src/components/ComplexLookupField/ComplexLookupField.tsx b/src/components/ComplexLookupField/ComplexLookupField.tsx index c63a06c4..bbfd6c4e 100644 --- a/src/components/ComplexLookupField/ComplexLookupField.tsx +++ b/src/components/ComplexLookupField/ComplexLookupField.tsx @@ -20,7 +20,7 @@ interface Props { } export const ComplexLookupField: FC = ({ value = undefined, id, entry, onChange }) => { - const { layout } = entry; + const { layout, htmlId } = entry; const lookupConfig = COMPLEX_LOOKUPS_CONFIG[layout?.api as string]; const buttonConfigLabel = lookupConfig?.labels?.button; @@ -86,6 +86,7 @@ export const ComplexLookupField: FC = ({ value = undefined, id, entry, on value={localValue?.map(({ label }) => label).join(VALUE_DIVIDER) ?? ''} disabled={true} data-testid="complex-lookup-input" + ariaLabelledBy={htmlId} /> )} diff --git a/src/components/ComplexLookupField/MarcPreviewComplexLookup.tsx b/src/components/ComplexLookupField/MarcPreviewComplexLookup.tsx index 57ef62d0..14116675 100644 --- a/src/components/ComplexLookupField/MarcPreviewComplexLookup.tsx +++ b/src/components/ComplexLookupField/MarcPreviewComplexLookup.tsx @@ -1,5 +1,5 @@ import { FC } from 'react'; -import { FormattedDate, FormattedMessage } from 'react-intl'; +import { FormattedDate, FormattedMessage, useIntl } from 'react-intl'; import { useSearchContext } from '@common/hooks/useSearchContext'; import { useMarcPreviewState, useUIState } from '@src/store'; import { SearchControlPane } from '@components/SearchControlPane'; @@ -14,6 +14,7 @@ type MarcPreviewComplexLookupProps = { export const MarcPreviewComplexLookup: FC = ({ onClose }) => { const { onAssignRecord } = useSearchContext(); + const { formatMessage } = useIntl(); const { isMarcPreviewOpen } = useUIState(); const { complexValue: marcPreviewData, metadata: marcPreviewMetadata } = useMarcPreviewState(); @@ -50,7 +51,11 @@ export const MarcPreviewComplexLookup: FC = ({ on renderCloseButton={renderCloseButton} >
-
diff --git a/src/components/DropdownField/DropdownField.tsx b/src/components/DropdownField/DropdownField.tsx index 172daa1b..bb3ced90 100644 --- a/src/components/DropdownField/DropdownField.tsx +++ b/src/components/DropdownField/DropdownField.tsx @@ -7,6 +7,7 @@ interface IDropdownField { onChange: (value: ReactSelectOption, fieldId: string, isDynamicField?: boolean) => void; value?: ReactSelectOption; isDisabled?: boolean; + htmlId?: string; id?: string; 'data-testid'?: string; } @@ -15,6 +16,7 @@ export const DropdownField: FC = ({ options, uuid, id, + htmlId, onChange, value, isDisabled = false, @@ -40,6 +42,7 @@ export const DropdownField: FC = ({ disabled={isDisabled} className="edit-section-field-input dropdown-field" data-testid={testId} + ariaLabelledby={htmlId} /> ); }; diff --git a/src/components/DuplicateGroup/DuplicateGroup.tsx b/src/components/DuplicateGroup/DuplicateGroup.tsx index da2c8af8..05012155 100644 --- a/src/components/DuplicateGroup/DuplicateGroup.tsx +++ b/src/components/DuplicateGroup/DuplicateGroup.tsx @@ -6,6 +6,7 @@ import Trash16 from '@src/assets/trash-16.svg?react'; import { getHtmlIdForSchemaControl } from '@common/helpers/schema.helper'; import { SchemaControlType } from '@common/constants/uiControls.constants'; import './DuplicateGroup.scss'; +import { useIntl } from 'react-intl'; interface Props { onClickDuplicate?: VoidFunction; @@ -17,25 +18,31 @@ interface Props { } export const DuplicateGroup: FC = memo( - ({ onClickDuplicate, onClickDelete, hasDeleteButton = true, className, htmlId, deleteDisabled = true }) => ( -
- - {hasDeleteButton && ( + ({ onClickDuplicate, onClickDelete, hasDeleteButton = true, className, htmlId, deleteDisabled = true }) => { + const { formatMessage } = useIntl(); + + return ( +
- )} -
- ), + {hasDeleteButton && ( + + )} +
+ ); + }, ); diff --git a/src/components/EditControlPane/EditControlPane.tsx b/src/components/EditControlPane/EditControlPane.tsx index 93d362a8..456d11b3 100644 --- a/src/components/EditControlPane/EditControlPane.tsx +++ b/src/components/EditControlPane/EditControlPane.tsx @@ -1,5 +1,5 @@ import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, useIntl } from 'react-intl'; import { Dropdown } from '@components/Dropdown'; import { DropdownItemType } from '@common/constants/uiElements.constants'; import { RESOURCE_CREATE_URLS } from '@common/constants/routes.constants'; @@ -31,6 +31,7 @@ export const EditControlPane = () => { const { navigateAsDuplicate } = useNavigateToEditPage(); const [queryParams] = useSearchParams(); const { fetchMarcData } = useMarcData(setBasicValue); + const { formatMessage } = useIntl(); const handleFetchMarcData = async () => fetchMarcData(resourceId); @@ -85,6 +86,7 @@ export const EditControlPane = () => { navigate(searchResultsUri); }} className="nav-close" + ariaLabel={formatMessage({ id: 'ld.aria.edit.close' })} > diff --git a/src/components/EditSection/DrawComponent.tsx b/src/components/EditSection/DrawComponent.tsx index 62212c22..d3703b5a 100644 --- a/src/components/EditSection/DrawComponent.tsx +++ b/src/components/EditSection/DrawComponent.tsx @@ -35,7 +35,7 @@ export const DrawComponent: FC = ({ onChange, handleGroupsCollapseExpand, }) => { - const { uuid, displayName = '', type, children, constraints } = entry; + const { uuid, displayName = '', type, children, constraints, htmlId } = entry; const isDisabled = !!disabledFields?.get(uuid); const displayNameWithAltValue = EDIT_ALT_DISPLAY_LABELS[displayName] || displayName; const selectedUserValue = userValues[uuid]; @@ -77,6 +77,7 @@ export const DrawComponent: FC = ({ = ({ = ({ = memo( }) => { return ( <> - {displayName && showLabel &&
{displayName}
} + {displayName && showLabel && ( +
+ {displayName} +
+ )}
{children}
diff --git a/src/components/FieldWithMetadataAndControls/ExtendedLayout.tsx b/src/components/FieldWithMetadataAndControls/ExtendedLayout.tsx index cdea3915..c6374ce5 100644 --- a/src/components/FieldWithMetadataAndControls/ExtendedLayout.tsx +++ b/src/components/FieldWithMetadataAndControls/ExtendedLayout.tsx @@ -32,7 +32,7 @@ export const ExtendedLayout: FC = memo( }) => { return ( <> -
+
{displayName && showLabel && (
{displayName}
)} diff --git a/src/components/Input/Input.tsx b/src/components/Input/Input.tsx index 7916159f..8f7411f1 100644 --- a/src/components/Input/Input.tsx +++ b/src/components/Input/Input.tsx @@ -12,6 +12,7 @@ type InputProps = { onPressEnter?: VoidFunction; type?: HTMLInputTypeAttribute; ariaLabel?: string; + ariaLabelledBy?: string; role?: string; [x: string]: any; }; @@ -26,6 +27,7 @@ export const Input: FC = ({ onPressEnter, type = 'text', ariaLabel, + ariaLabelledBy, role = 'textbox', ...restProps }) => { @@ -46,6 +48,7 @@ export const Input: FC = ({ }} type={type} aria-label={ariaLabel} + aria-labelledby={ariaLabelledBy} role={role} {...restProps} /> diff --git a/src/components/LiteralField/LiteralField.tsx b/src/components/LiteralField/LiteralField.tsx index f98301d6..6383095e 100644 --- a/src/components/LiteralField/LiteralField.tsx +++ b/src/components/LiteralField/LiteralField.tsx @@ -3,6 +3,7 @@ import { Input } from '@components/Input'; interface ILiteralField { uuid: string; + htmlId?: string; value?: string; isDisabled?: boolean; id?: string; @@ -12,6 +13,7 @@ interface ILiteralField { export const LiteralField: FC = ({ uuid, + htmlId, value = '', id, isDisabled = false, @@ -34,6 +36,7 @@ export const LiteralField: FC = ({ onChange={handleOnChange} value={localValue} disabled={isDisabled} + ariaLabelledBy={htmlId} /> ); }; diff --git a/src/components/Preview/TitledPreview.tsx b/src/components/Preview/TitledPreview.tsx index e4cbc0d6..087b46e9 100644 --- a/src/components/Preview/TitledPreview.tsx +++ b/src/components/Preview/TitledPreview.tsx @@ -2,7 +2,7 @@ import { Button, ButtonType } from '@components/Button'; import { Preview } from './Preview'; import { PreviewActionsDropdown } from '@components/PreviewActionsDropdown'; import Times16 from '@src/assets/times-16.svg?react'; -import { FormattedMessage } from 'react-intl'; +import { FormattedMessage, useIntl } from 'react-intl'; import { ResourceType } from '@common/constants/record.constants'; import { useNavigateToEditPage } from '@common/hooks/useNavigateToEditPage'; import { generateEditResourceUrl } from '@common/helpers/navigation.helper'; @@ -25,21 +25,25 @@ export const TitledPreview = ({ previewContent, onClickClose, }: ITitledPreview) => { + const { formatMessage } = useIntl(); const { navigateToEditPage } = useNavigateToEditPage(); const { title, id, base, initKey, userValues } = previewContent ?? {}; const selectedOwnId = id ?? ownId; const withPreviewContent = ( <> {showCloseCtl ? ( - ) : ( )} -
- {title &&
{title}
} -
+
{title &&
{title}
}
); diff --git a/src/components/PreviewExternalResourcePane/PreviewExternalResourcePane.tsx b/src/components/PreviewExternalResourcePane/PreviewExternalResourcePane.tsx index 48e460ae..cddca195 100644 --- a/src/components/PreviewExternalResourcePane/PreviewExternalResourcePane.tsx +++ b/src/components/PreviewExternalResourcePane/PreviewExternalResourcePane.tsx @@ -1,3 +1,4 @@ +import { useIntl } from 'react-intl'; import { Button, ButtonType } from '@components/Button'; import Times16 from '@src/assets/times-16.svg?react'; import { getRecordTitle } from '@common/helpers/record.helper'; @@ -7,6 +8,7 @@ import { useInputsState } from '@src/store'; export const PreviewExternalResourcePane = () => { const { record } = useInputsState(); const { dispatchNavigateToOriginEventWithFallback } = useContainerEvents(); + const { formatMessage } = useIntl(); return (
@@ -16,6 +18,7 @@ export const PreviewExternalResourcePane = () => { type={ButtonType.Icon} onClick={dispatchNavigateToOriginEventWithFallback} className="nav-close" + ariaLabel={formatMessage({ id: 'ld.aria.externalResourcePreview.close' })} > diff --git a/src/components/SimpleLookupField/SimpleLookupField.tsx b/src/components/SimpleLookupField/SimpleLookupField.tsx index b461db19..2f4b8e0c 100644 --- a/src/components/SimpleLookupField/SimpleLookupField.tsx +++ b/src/components/SimpleLookupField/SimpleLookupField.tsx @@ -19,6 +19,7 @@ interface Props { uri: string; uuid: string; value?: UserValueContents[]; + htmlId?: string; parentUri?: string; isDisabled?: boolean; id?: string; @@ -34,6 +35,7 @@ export const SimpleLookupField: FC = ({ uuid, id, value, + htmlId, onChange, parentUri, isDisabled = false, @@ -92,6 +94,7 @@ export const SimpleLookupField: FC = ({ return ( { type={ButtonType.Icon} onClick={resetMarcPreviewData} className="nav-close" + ariaLabel={formatMessage({ id: 'ld.aria.marcPreview.close' })} > diff --git a/translations/ui-linked-data/en.json b/translations/ui-linked-data/en.json index f4b85b7d..4b824f9d 100644 --- a/translations/ui-linked-data/en.json +++ b/translations/ui-linked-data/en.json @@ -194,6 +194,13 @@ "ld.aria.filters.select": "Select search identifiers", "ld.aria.listEntry.open": "Open collapsible list entry", "ld.aria.listEntry.close": "Close collapsible list entry", + "ld.aria.edit.close": "Close edit page", + "ld.aria.edit.deleteComponent": "Delete component", + "ld.aria.edit.duplicateComponent": "Duplicate component", + "ld.aria.resourcePreview.close": "Close resource preview pane", + "ld.aria.externalResourcePreview.close": "Close external resource preview page", + "ld.aria.marcAuthorityPreview.close": "Close MARC authority preview", + "ld.aria.marcPreview.close": "Close MARC preview modal", "ld.aria.filters.textbox": "Search query textbox", "ld.aria.table.selectRow": "Select table row", "ld.aria.sections.openResourcePreview": "Open resource preview section",