From 5fedbbc4d27f56b13e18fb504cb3f135ce0878c2 Mon Sep 17 00:00:00 2001 From: Viktor Egorov Date: Sun, 6 Jul 2025 10:18:15 +0200 Subject: [PATCH] Expandable text for inputs --- .../changelog/expandable_text_for_input.yaml | 2 + .../src/base/forms/base/ExpandableText.tsx | 57 +++++++++++++++++++ .../base/forms/input/InputField.stories.mdx | 9 +++ .../src/base/forms/input/InputField.tsx | 30 ++++++++-- scm-ui/ui-webapp/public/locales/de/users.json | 11 ---- scm-ui/ui-webapp/public/locales/en/users.json | 11 ---- scm-ui/ui-webapp/public/locales/es/users.json | 10 ---- 7 files changed, 93 insertions(+), 37 deletions(-) create mode 100644 gradle/changelog/expandable_text_for_input.yaml create mode 100644 scm-ui/ui-core/src/base/forms/base/ExpandableText.tsx diff --git a/gradle/changelog/expandable_text_for_input.yaml b/gradle/changelog/expandable_text_for_input.yaml new file mode 100644 index 0000000000..4bb6f8ae5e --- /dev/null +++ b/gradle/changelog/expandable_text_for_input.yaml @@ -0,0 +1,2 @@ +- type: added + description: New option for input field to expand the description text with an icon an displays a new text diff --git a/scm-ui/ui-core/src/base/forms/base/ExpandableText.tsx b/scm-ui/ui-core/src/base/forms/base/ExpandableText.tsx new file mode 100644 index 0000000000..3c5ae323bd --- /dev/null +++ b/scm-ui/ui-core/src/base/forms/base/ExpandableText.tsx @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2020 - present Cloudogu GmbH + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the Free + * Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more + * details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see https://www.gnu.org/licenses/. + */ + +import React, { HTMLAttributes, useState } from "react"; +import { Icon } from "../../buttons"; + +interface Props extends HTMLAttributes { + descriptionText: string; + extendedDescriptionText: string; +} + +/** + * Displays a single line of text by default and allows users to expand it to view the full content. + * + * The description text is shown initially + * with an icon to toggle the visibility of the extended text. + * + * @param desription - The text content that will always be displayed. + * @param extended - The text content that will be displayed after you toggle the icon. + * @param props - Additional props to pass to the `

` element. + * @param ref - A ref to the `

` element. + * + * @beta + * @since 3.9.0 + */ +const ExpandableText = React.forwardRef( + ({ descriptionText, extendedDescriptionText, ...props }, ref) => { + const [isExpanded, setIsExpanded] = useState(false); + + return ( +

+

+ setIsExpanded(!isExpanded)} aria-expanded={isExpanded}> + {isExpanded ? "chevron-down" : "chevron-right"} + + {descriptionText} +
+ <>{isExpanded && {extendedDescriptionText}} +

+ ); + } +); + +export default ExpandableText; diff --git a/scm-ui/ui-core/src/base/forms/input/InputField.stories.mdx b/scm-ui/ui-core/src/base/forms/input/InputField.stories.mdx index 16c8cad121..b3b87eaafb 100644 --- a/scm-ui/ui-core/src/base/forms/input/InputField.stories.mdx +++ b/scm-ui/ui-core/src/base/forms/input/InputField.stories.mdx @@ -13,6 +13,15 @@ This will be our first form field molecule + + + + + + + + + diff --git a/scm-ui/ui-core/src/base/forms/input/InputField.tsx b/scm-ui/ui-core/src/base/forms/input/InputField.tsx index fe5c5b292d..670f164aff 100644 --- a/scm-ui/ui-core/src/base/forms/input/InputField.tsx +++ b/scm-ui/ui-core/src/base/forms/input/InputField.tsx @@ -19,15 +19,21 @@ import classNames from "classnames"; import Field from "../base/Field"; import Control from "../base/Control"; import Label from "../base/label/Label"; +import Help from "../base/help/Help"; import FieldMessage from "../base/field-message/FieldMessage"; import Input from "./Input"; -import Help from "../base/help/Help"; import { useAriaId } from "../../helpers"; +import ExpandableText from "../base/ExpandableText"; export type InputFieldProps = { label: string; + /** + * @deprecated This property is deprecated and will be removed in future versions. + * Use `descriptionText` instead. + */ helpText?: string; descriptionText?: string; + extendedText?: string; error?: string; icon?: string; } & React.ComponentProps; @@ -36,9 +42,11 @@ export type InputFieldProps = { * @see https://bulma.io/documentation/form/input/ */ const InputField = React.forwardRef( - ({ name, label, helpText, descriptionText, error, icon, className, id, ...props }, ref) => { + ({ name, label, helpText, descriptionText, extendedText, error, icon, className, id, ...props }, ref) => { const inputId = useAriaId(id ?? props.testId); + const helpTextId = helpText ? `input-helptext-${name}` : undefined; const descriptionId = descriptionText ? `input-description-${name}` : undefined; + const extendedDescriptionId = extendedText ? `input-extended-${name}` : undefined; const variant = error ? "danger" : undefined; return ( @@ -46,13 +54,25 @@ const InputField = React.forwardRef( {label} {helpText ? : null} - {descriptionText ? ( + {extendedText && descriptionText ? ( + + ) : (

{descriptionText}

- ) : null} + )} - + {icon ? ( diff --git a/scm-ui/ui-webapp/public/locales/de/users.json b/scm-ui/ui-webapp/public/locales/de/users.json index a55f413cf4..2479cd09ac 100644 --- a/scm-ui/ui-webapp/public/locales/de/users.json +++ b/scm-ui/ui-webapp/public/locales/de/users.json @@ -16,14 +16,6 @@ "name-invalid": "Dieser Name ist ungültig", "displayname-invalid": "Dieser Anzeigename ist ungültig" }, - "help": { - "usernameHelpText": "Einzigartiger Name des Benutzers", - "displayNameHelpText": "Anzeigename des Benutzers", - "mailHelpText": "E-Mail Adresse des Benutzers", - "adminHelpText": "Ein Administrator kann Repositories, Gruppen und Benutzer erstellen, bearbeiten und löschen.", - "activeHelpText": "Aktivierung oder Deaktivierung eines Benutzers", - "externalFlagHelpText": "Der Benutzer wird über ein Fremdsystem verwaltet." - }, "users": { "title": "Benutzer", "subtitle": "Verwaltung der Benutzer", @@ -57,21 +49,18 @@ "submit-success-notification": "Der Benutzer wurde erfolgreich aktualisiert", "name": { "label": "Benutzername", - "helpText": "Einzigartiger Name des Benutzers.", "error": { "validate": "Dieser Name ist ungültig" } }, "displayName": { "label": "Anzeigename", - "helpText": "Anzeigename des Benutzers.", "error": { "validate": "Dieser Anzeigename ist ungültig" } }, "mail": { "label": "E-Mail", - "helpText": "E-Mail Adresse des Benutzers.", "error": { "validate": "Diese E-Mail ist ungültig" } diff --git a/scm-ui/ui-webapp/public/locales/en/users.json b/scm-ui/ui-webapp/public/locales/en/users.json index acf37078ea..aca7c88653 100644 --- a/scm-ui/ui-webapp/public/locales/en/users.json +++ b/scm-ui/ui-webapp/public/locales/en/users.json @@ -16,14 +16,6 @@ "name-invalid": "This name is invalid", "displayname-invalid": "This displayname is invalid" }, - "help": { - "usernameHelpText": "Unique name of the user.", - "displayNameHelpText": "Display name of the user.", - "mailHelpText": "Email address of the user.", - "adminHelpText": "An administrator is able to create, modify and delete repositories, groups and users.", - "activeHelpText": "Activate or deactivate the user.", - "externalFlagHelpText": "This user is managed by an external system." - }, "users": { "title": "Users", "subtitle": "Create, read, update and delete users", @@ -57,21 +49,18 @@ "submit-success-notification": "The user was updated successfully", "name": { "label": "User Name", - "helpText": "Unique name of the user.", "error": { "validate": "This name is invalid" } }, "displayName": { "label": "Display Name", - "helpText": "Display name of the user.", "error": { "validate": "This display name is invalid" } }, "mail": { "label": "Email", - "helpText": "Email address of the user.", "error": { "validate": "This email address is invalid" } diff --git a/scm-ui/ui-webapp/public/locales/es/users.json b/scm-ui/ui-webapp/public/locales/es/users.json index 8895eeb024..c34ed3e5cb 100644 --- a/scm-ui/ui-webapp/public/locales/es/users.json +++ b/scm-ui/ui-webapp/public/locales/es/users.json @@ -15,13 +15,6 @@ "name-invalid": "El nombre es incorrecto", "displayname-invalid": "El nombre a mostrar es incorrecto" }, - "help": { - "usernameHelpText": "Nombre único del usuario.", - "displayNameHelpText": "Nombre de usuario a mostrar.", - "mailHelpText": "Dirección de correo electrónico del usuario.", - "adminHelpText": "Un administrador es capaz de crear, modificar y borrar repositorios, grupos y usuarios.", - "activeHelpText": "Activar o desactivar el usuario." - }, "users": { "title": "Usuarios", "subtitle": "Crear, leer, actualizar y borrar usuarios", @@ -46,21 +39,18 @@ "form": { "name": { "label": "Nombre de usuario", - "helpText": "Nombre único del usuario.", "error": { "validate": "El nombre es incorrecto" } }, "displayName": { "label": "Nombre a mostrar", - "helpText": "Nombre de usuario a mostrar.", "error": { "validate": "El nombre a mostrar es incorrecto" } }, "mail": { "label": "Correo electrónico", - "helpText": "Dirección de correo electrónico del usuario.", "error": { "validate": "El correo electrónico es incorrecto" }