From 635b7fa5bf839fbfc988b057e4688c402f9bf67b Mon Sep 17 00:00:00 2001 From: Jonas Carlsen Date: Fri, 11 Oct 2024 13:08:42 +0200 Subject: [PATCH] feat: add generic select abstractions to reduce boilerplate --- .../plugins/audio/AudioEmbedForm.tsx | 32 ++------- .../plugins/codeBlock/CodeBlockEditor.tsx | 31 ++------- src/components/abstractions/Select.tsx | 66 +++++++++++++++++++ .../App/components/FooterWrapper.tsx | 35 +++------- .../components/ContributorsField.tsx | 31 ++------- .../FormikForm/components/LicenseField.tsx | 34 +++------- 6 files changed, 104 insertions(+), 125 deletions(-) create mode 100644 src/components/abstractions/Select.tsx diff --git a/src/components/SlateEditor/plugins/audio/AudioEmbedForm.tsx b/src/components/SlateEditor/plugins/audio/AudioEmbedForm.tsx index 64f2199d18..b8516c0a72 100644 --- a/src/components/SlateEditor/plugins/audio/AudioEmbedForm.tsx +++ b/src/components/SlateEditor/plugins/audio/AudioEmbedForm.tsx @@ -10,28 +10,21 @@ import { Formik, useFormikContext } from "formik"; import { useCallback, useMemo } from "react"; import { useTranslation } from "react-i18next"; import { createListCollection } from "@ark-ui/react"; -import { ArrowDownShortLine } from "@ndla/icons/common"; -import { CheckLine } from "@ndla/icons/editor"; import { ModalBody, ModalHeader, ModalTitle } from "@ndla/modal"; import { Button, FieldErrorMessage, FieldRoot, SelectContent, - SelectControl, - SelectIndicator, - SelectItem, - SelectItemIndicator, - SelectItemText, SelectLabel, SelectPositioner, SelectRoot, - SelectTrigger, SelectValueText, } from "@ndla/primitives"; import { IAudioMetaInformation } from "@ndla/types-backend/audio-api"; import { AudioEmbedData } from "@ndla/types-embed"; import { AudioPlayer } from "@ndla/ui"; +import { GenericSelectItem, GenericSelectTrigger } from "../../../abstractions/Select"; import { FormField } from "../../../FormField"; import { FormActionsContainer, FormikForm } from "../../../FormikForm"; import validateFormik, { RulesType } from "../../../formikValidationSchema"; @@ -129,26 +122,15 @@ const EmbedForm = ({ onCancel, audio }: EmbedFormProps) => { collection={collection} > {t("form.audio.chooseAudioType")} - - - - - + + + {collection.items.map((item) => ( - - {item.label} - - - - + + {item.label} + ))} diff --git a/src/components/SlateEditor/plugins/codeBlock/CodeBlockEditor.tsx b/src/components/SlateEditor/plugins/codeBlock/CodeBlockEditor.tsx index da10a99657..ffa2bf68e5 100644 --- a/src/components/SlateEditor/plugins/codeBlock/CodeBlockEditor.tsx +++ b/src/components/SlateEditor/plugins/codeBlock/CodeBlockEditor.tsx @@ -11,8 +11,6 @@ import { ComponentProps, useCallback, useEffect, useMemo } from "react"; import { useTranslation } from "react-i18next"; import Editor from "react-simple-code-editor"; import { FieldContext, SelectHiddenSelect, createListCollection } from "@ark-ui/react"; -import { ArrowDownShortLine } from "@ndla/icons/common"; -import { CheckLine } from "@ndla/icons/editor"; import { Button, FieldErrorMessage, @@ -20,19 +18,14 @@ import { FieldLabel, FieldRoot, SelectContent, - SelectControl, - SelectIndicator, - SelectItem, - SelectItemIndicator, - SelectItemText, SelectLabel, SelectPositioner, SelectRoot, - SelectTrigger, SelectValueText, } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; import { languageOptions } from "./codeBlockOptions"; +import { GenericSelectItem, GenericSelectTrigger } from "../../../abstractions/Select"; import { FormField } from "../../../FormField"; import { FormActionsContainer, FormikForm } from "../../../FormikForm"; import validateFormik, { RulesType } from "../../../formikValidationSchema"; @@ -168,25 +161,15 @@ const CodeBlockEditor = ({ onSave, onAbort, highlight, content, setShowWarning } > {t("codeEditor.languageSelect")} {meta.error} - - - - - + + + {languageOptions.map((item) => ( - - {item.title} - - - - + + {item.title} + ))} diff --git a/src/components/abstractions/Select.tsx b/src/components/abstractions/Select.tsx new file mode 100644 index 0000000000..4e4a1ffdf4 --- /dev/null +++ b/src/components/abstractions/Select.tsx @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2024-present, NDLA. + * + * This source code is licensed under the GPLv3 license found in the + * LICENSE file in the root directory of this source tree. + * + */ + +import { forwardRef } from "react"; +import { + SelectIndicatorProps, + SelectItemIndicator, + SelectItemIndicatorProps, + SelectItemProps, + SelectTriggerProps, +} from "@ark-ui/react"; +import { ArrowDownShortLine } from "@ndla/icons/common"; +import { CheckLine } from "@ndla/icons/editor"; +import { + Button, + ButtonProps, + SelectControl, + SelectIndicator, + SelectItem, + SelectItemText, + SelectTrigger, +} from "@ndla/primitives"; +import { JsxStyleProps } from "@ndla/styled-system/types"; + +export const GenericSelectTrigger = forwardRef( + ({ children, variant = "secondary", ...props }, ref) => ( + + + + + + ), +); + +export const GenericSelectIndicator = forwardRef( + ({ children, ...props }, ref) => ( + + {children ?? } + + ), +); + +export const GenericSelectItem = forwardRef( + ({ children, ...props }, ref) => ( + + {children} + + + ), +); + +export const GenericSelectItemIndicator = forwardRef( + ({ children, ...props }, ref) => ( + + {children ?? } + + ), +); diff --git a/src/containers/App/components/FooterWrapper.tsx b/src/containers/App/components/FooterWrapper.tsx index 0b79646809..66d2f3de67 100644 --- a/src/containers/App/components/FooterWrapper.tsx +++ b/src/containers/App/components/FooterWrapper.tsx @@ -11,21 +11,9 @@ import { useTranslation } from "react-i18next"; import { createListCollection } from "@ark-ui/react"; import emotionStyled from "@emotion/styled"; import { spacing } from "@ndla/core"; -import { ArrowDownShortLine } from "@ndla/icons/common"; -import { CheckLine } from "@ndla/icons/editor"; -import { - Button, - SelectContent, - SelectItem, - SelectItemIndicator, - SelectItemText, - SelectLabel, - SelectPositioner, - SelectRoot, - SelectTrigger, - Text, -} from "@ndla/primitives"; +import { SelectContent, SelectLabel, SelectPositioner, SelectRoot, SelectValueText, Text } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; +import { GenericSelectItem, GenericSelectTrigger } from "../../../components/abstractions/Select"; import { supportedLanguages } from "../../../i18n2"; import { LocaleType } from "../../../interfaces"; @@ -38,7 +26,7 @@ export const FooterBlock = styled("footer", { }, }); -const LanguageSelectTrigger = styled(SelectTrigger, { +const StyledGenericSelectTrigger = styled(GenericSelectTrigger, { base: { width: "unset", }, @@ -88,20 +76,15 @@ const FooterWrapper = ({ showLocaleSelector }: Props) => { value={[i18n.language]} > {t("languages.prefixChangeLanguage")} - - - + + {t("languages.prefixChangeLanguage")} + {supportedLanguages.map((lang) => ( - - {t(`languages.${lang}`)} - - - - + + {t(`languages.${lang}`)} + ))} diff --git a/src/containers/FormikForm/components/ContributorsField.tsx b/src/containers/FormikForm/components/ContributorsField.tsx index 220a4c2b38..8a8e1d17c8 100644 --- a/src/containers/FormikForm/components/ContributorsField.tsx +++ b/src/containers/FormikForm/components/ContributorsField.tsx @@ -10,8 +10,6 @@ import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { createListCollection } from "@ark-ui/react"; import { CloseLine } from "@ndla/icons/action"; -import { ArrowDownShortLine } from "@ndla/icons/common"; -import { CheckLine } from "@ndla/icons/editor"; import { contributorGroups, contributorTypes } from "@ndla/licenses"; import { Button, @@ -22,20 +20,15 @@ import { FieldsetLegend, FieldsetRoot, SelectContent, - SelectControl, SelectHiddenSelect, - SelectIndicator, - SelectItem, - SelectItemIndicator, - SelectItemText, SelectLabel, SelectPositioner, SelectRoot, - SelectTrigger, SelectValueText, } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; import { IAuthor } from "@ndla/types-backend/draft-api"; +import { GenericSelectItem, GenericSelectTrigger } from "../../../components/abstractions/Select"; import { FormField } from "../../../components/FormField"; type ContributorType = keyof typeof contributorGroups; @@ -137,25 +130,15 @@ const Contributor = ({ type, onAddNew, onRemove }: ContributorProps) => { > {t("form.name.type")} {meta.error} - - - - - + + + {collection.items.map((item) => ( - - {item.translation} - - - - + + {item.translation} + ))} diff --git a/src/containers/FormikForm/components/LicenseField.tsx b/src/containers/FormikForm/components/LicenseField.tsx index bd64e2daff..0e0f1cd931 100644 --- a/src/containers/FormikForm/components/LicenseField.tsx +++ b/src/containers/FormikForm/components/LicenseField.tsx @@ -9,26 +9,18 @@ import { useMemo } from "react"; import { useTranslation } from "react-i18next"; import { createListCollection } from "@ark-ui/react"; -import { ArrowDownShortLine } from "@ndla/icons/common"; -import { CheckLine } from "@ndla/icons/editor"; import { - Button, FieldErrorMessage, FieldRoot, SelectContent, - SelectControl, SelectHiddenSelect, - SelectIndicator, - SelectItem, - SelectItemIndicator, - SelectItemText, SelectLabel, SelectPositioner, SelectRoot, - SelectTrigger, SelectValueText, } from "@ndla/primitives"; import { styled } from "@ndla/styled-system/jsx"; +import { GenericSelectItem, GenericSelectTrigger } from "../../../components/abstractions/Select"; import { FormField } from "../../../components/FormField"; import { useLicenses } from "../../../modules/draft/draftQueries"; import { getLicensesWithTranslations } from "../../../util/licenseHelpers"; @@ -38,7 +30,7 @@ interface Props { enableLicenseNA?: boolean; } -const StyledSelectTrigger = styled(SelectTrigger, { +const StyledGenericSelectTrigger = styled(GenericSelectTrigger, { base: { width: "100%", }, @@ -70,25 +62,15 @@ const LicenseField = ({ name = "license", enableLicenseNA }: Props) => { > {t("form.license.label")} {meta.error} - - - - - + + + {collection.items.map((item) => ( - - {item.title} - - - - + + {item.title} + ))}