El componente menú desplegable presenta a los usuarios un conjunto de opciones de entre las que deben seleccionar. Las listas desplegables revelan progresivamente las opciones, lo que evita que los usuarios vean demasiada información a la vez. También se pueden utilizar para agrupar información. Las listas desplegables siempre son compatibles con un campo, un rótulo o un título que se coloca antes del control.
Este componente tiene cuatro variantes: selección, selección múltiple, cuadro combinado, cuadro combinado múltiple.
La variante de cuadro combinado múltiple del menú desplegable permite a los usuarios filtrar listas más largas solo para las selecciones que coincidan con una consulta. El usuario puede seleccionar varias opciones de la lista.
Si la lista de opciones no tiene la complejidad que requiere un cuadro combinado, puede usar el menú desplegable de ](pathname://es/drop-downs-multiselect.mdx)selección múltiple[.
Hay una pequeña cantidad de opciones (5 o menos) entre las que los usuarios pueden elegir. Utilice casillas de verificación para los elementos de selección múltiple.
Anatomía del componente menú desplegable de la variante cuadro combinado múltiple.
Rótulo: Describe el propósito del campo de entrada.
Texto de ayuda (opcional): Proporciona contexto adicional o ayuda al usuario a elegir la selección correcta.
Entrada del menú desplegable: Muestra las opciones seleccionadas por el usuario. Los usuarios pueden escribir en el campo de entrada para encontrar una opción que coincida con su consulta.
Menú desplegable: Muestra una lista de opciones de entre las que elegir.
Jutro admite menús desplegables con campos de entrada con predicción de escritura. Los usuarios pueden ingresar texto manualmente para filtrar los elementos desplegables. Esta característica es útil para ayudar a los usuarios a seleccionar de entre una lista larga.
Los menús desplegables con la función de predicción de escritura habilitada proporcionan sugerencias a medida que los usuarios escriben. Las selecciones aparecen en función de los caracteres que los usuarios hayan ingresado. Cuantos más caracteres introduzcan los usuarios en el campo, más refinada se volverá la lista.
Cuando utilice el menú desplegable para ordenar, considere organizar las opciones en orden. Por ejemplo:
De la opción más común a la menos común.
De la operación más simple a la más compleja.
De la opción menos riesgosa a la más riesgosa.
La primera opción aparecería en la parte superior de la lista.
Evite organizar la lista de opciones alfabéticamente, a menos que tenga sentido para su caso de uso. A menudo está bien organizar alfabéticamente las listas de países y otros problemas de elementos conocidos. Sin embargo, debe asegurarse de que los usuarios conozcan inequívocamente el nombre de su selección.
En todos los aspectos del diseño de las interfaces de productos de Guidewire, utilice mayúsculas como se usan en las oraciones. No use mayúsculas en todas las palabras.
Use verbos en tiempo presente y voz activa en la mayoría de las situaciones.
Use contracciones comunes para darle al texto un tono más natural e informal (pauta correspondiente al inglés).
Use un lenguaje sencillo. Evite la jerga innecesaria y el lenguaje complejo.
Coloque el rótulo del menú desplegable fuera del campo para que siempre esté visible. Un menú desplegable sin rótulo no es accesible.
No reemplace los rótulos de campo por texto de marcador de posición en el campo. Esto perjudica la facilidad de uso y tiene muchas consecuencias negativas.
Coloque un rótulo permanente fuera del campo.
No utilice texto de marcador de posición como sustituto del rótulo de campo.
Use el texto de ayuda para mostrar el contexto y comunicar qué opción seleccionar o cómo hacerlo. Estos son algunos ejemplos de lo que podría incluir en el texto de ayuda:
Una descripción general de las opciones del menú desplegable.
Sugerencias que ayuden al usuario a elegir la selección correcta.
Más contexto de por qué un usuario deba elegir una opción.
Utilice el texto de ayuda solo para la información pertinente. No use texto de ayuda que simplemente repita la misma información que aparece en el rótulo.
En el texto de ayuda, use mayúsculas como se usan en las oraciones. Escriba 1 o 2 oraciones cortas y completas que terminen con un punto.
Utilice texto de ayuda para mostrar el contexto.
No use texto de ayuda que simplemente repita la misma información que aparece en el rótulo.
No coloque texto de marcador de posición en el campo de entrada de texto. El texto de marcador de posición sobrecarga la memoria a corto plazo de los usuarios porque desaparece una vez que se ingresa un valor. También supone una carga adicional para los usuarios con discapacidades visuales y cognitivas.
En su lugar, coloque sugerencias e instrucciones fuera del campo.
El campo de entrada para el cuadro combinado múltiple sigue las pautas de contenido para los campos de texto.
El texto del mensaje de error indica a un usuario cómo corregir el error. En el caso del menú desplegable, los errores a menudo están relacionados con algo que debe corregirse para la validación integrada. Por ejemplo, si alguien no selecciona un factor de riesgo y este es un campo obligatorio, puede usar el texto de error para guiar al usuario a una solución: “Seleccione uno o más factores de riesgo”.
En el texto de error, use mayúsculas como se usan en las oraciones. Escriba 1 o 2 oraciones cortas y completas que terminen con un punto.
Use el texto de error para guiar al usuario y mostrarle una solución.
No escriba mensajes de error ambiguos ni deje a los usuarios pensando cómo resolver un problema.
Utilice un asterisco (*) para indicar los campos obligatorios. El asterisco precede al rótulo del campo. Esto ayuda a los usuarios a identificar fácilmente qué campos son obligatorios escaneando solo el carácter más a la izquierda del rótulo.
Además de marcar los campos obligatorios con un asterisco, se recomienda incluir instrucciones claras en la parte superior del formulario, como “Todos los campos marcados con un asterisco son obligatorios”, para garantizar que los usuarios comprendan el significado del asterisco.
Utilice un asterisco para indicar que un campo es obligatorio.
No use un asterisco para indicar algo que sea opcional.
La variante cuadro combinado múltiple aparece sin valor (predeterminado), texto de marcador de posición o una entrada rellena.
Ilustración
Estado
Descripción
Sin valor (predeterminado)
Indica al usuario que no se ha seleccionado ningún valor y que no hay un marcador de posición.
Marcador de posición
Indica al usuario que no se ha seleccionado ningún valor. El marcador de posición aparece atenuado.
Entrada rellena
Indica al usuario que la entrada está completa con datos.
El cuadro combinado múltiple también tiene estados interactivos para habilitado, en foco, deshabilitado, error, solo lectura y solo visualización.
Estado
Descripción
Habilitado
Indica al usuario que el elemento está habilitado para la interacción.
En foco
Indica al usuario qué elemento de la interfaz de usuario del sistema está el foco.
Deshabilitado
Indica al usuario que el valor de entrada no se puede cambiar debido a factores locales. Por ejemplo, una casilla de verificación sobre el campo de entrada debe estar marcada para acceder a este campo de entrada. El usuario puede habilitarla interactuando con la página.
Error
Indica que el usuario cometió un error de validación. El texto del error proporciona información a los usuarios para solucionarlo.
Solo lectura
Indica al usuario que el valor de entrada no se puede cambiar debido a factores externos. Por ejemplo, la falta de acceso de escritura. El usuario puede hacer algo para habilitarlo, por ejemplo, ponerse en contacto con un administrador.
Solo visualización
El estado de solo visualización se utiliza en dos casos:
Un elemento de interfaz de usuario se utiliza en el modo de visualización.
Un elemento de la interfaz de usuario se muestra en el modo de edición, pero nunca se puede editar.
Este estado se llamaba “solo lectura” antes.
La siguiente imagen ilustra estados interactivos del cuadro combinado múltiple.
El menú desplegable se expande y se contrae usando la barra espaciadora. Los usuarios pueden navegar por las opciones utilizando las teclas de flecha y seleccionar por medio de barra espaciadora o la tecla Intro.
aria-labelledby establece una asociación programática entre el campo de entrada y su rótulo. El atributo WAI-ARIA de aria-autocomplete='list' comunica que aparecerá una lista de opciones entre las que el usuario puede elegir, pero el cuadro de edición conserva el foco. Al seleccionar la opción 'required' en Storybook, se agregan los atributos 'required' and 'aria-required="true"' al campo de entrada.
Este componente de Jutro ha sido validado para cumplir con las pautas de accesibilidad de WCAG 2.2 AA en su configuración base predeterminada. Esto incluye garantizar que se cumpla lo siguiente:
La relación de contraste de los elementos textuales con respecto a su fondo es superior a 4,5:1.
El contenido no textual que debe transmitir significado (como íconos e indicadores de foco) tiene una relación de contraste de al menos 3:1 con sus colores adyacentes.
El elemento se puede operar con teclado, así como con mouse.
Se puede acceder al contenido mediante lectores de pantalla, como JAWS y VoiceOver.
El cumplimiento de los criterios de accesibilidad depende, en última instancia, de cómo se implementa y personaliza este componente. Los cambios realizados por el autor del contenido pueden afectar la accesibilidad. Para obtener más información sobre nuestro modelo de responsabilidad compartida, revise nuestra declaración completa sobre accesibilidad de Jutro.
Al utilizar este componente en su aplicación:
Ayude a los usuarios a comprender el contenido evitando nombres de opciones muy largos.
Evite el uso de elementos que implícitamente puedan recibir el foco, como botones, casillas de verificación y enlaces, o contenido implícitamente semántico, como encabezados, dentro de los componentes menú desplegable.
Note: Hay versiones obsoletas de este componente. Consulte una versión de los documentos anterior a la 10.0.x.
Asegúrese de comprender la superficie de la API de componentes del sistema de diseño, así como sus implicaciones, ventajas y desventajas. Obtenga más información en nuestra introducción a la API de componentes.
Warning: No se admite pasar opciones secundarias al componente MultipleSelect que no sea SelectOption. Aunque podría funcionar, quizás dé lugar a comportamientos inesperados o se vea afectado por cambios introducidos en futuras versiones.
If set to true, adds an icon button that appears when at least one option is selected, or any text is typed. It allows the user to unselect all selected options and delete the typed text at once.
If set to true, the tags are displayed permanently in expanded view. This overrides the default behavior where excess tags collapse into a tag containing aggregated options.
Value of the component, in the form of an array of currently selected options. Takes precedence over initialValue. If this prop is passed, component works in controlled mode and its value will change only if this prop changes.
El gancho useFilteredOptions proporciona los mecanismos para manejar las opciones que se muestran en función de la entrada del usuario.
Parámetros recibidos:
initialOptions: TValue[]. Lista inicial de opciones en el componente sin ningún filtro aplicado.
Fase de salida:
Un objeto con:
filteredOptions: TValue[]. Matriz con las opciones resultantes tras aplicar el filtro.
onSearch: function. Función que toma el evento de entrada onSearch y filtra las opciones en función de él. Esto se puede asignar al evento onSearch del componente.
resetFilter: function. Se utiliza para restablecer el filtrado de opciones, ya que establece la matriz filteredOptions a su valor inicial.
Cuando las etiquetas de las opciones seleccionadas exceden el espacio del componente, algunas de ellas se contraen en una sola etiqueta que indica la cantidad de opciones seleccionadas que no se muestran. Al hacer clic en esta etiqueta, el componente se expande verticalmente para mostrar todas las etiquetas de las opciones seleccionadas. Una vez expandidas, las etiquetas de opción no se pueden contraer.
Para anular este comportamiento y mostrar todas las etiquetas de opción de forma permanente en una vista expandida, establezca la propiedad tagsAlwaysExpanded en true. Para comparar los dos comportamientos, consulte los ejemplos.
Todos los componentes relacionados con el menú desplegable definen la lista de opciones disponibles a través de la propiedad children de tipo ReactNode. Solo puede utilizar los siguientes subcomponentes como secundarios:
SelectOption utilizado por Select y MultipleSelect
ComboboxOption utilizado por Combobox y MultipleCombobox
Warning:
SelectOption y ComboboxOption solo deben utilizarse en el contexto de su respectivo componente "principal". Aunque pueden funcionar de forma aislada, esta no es una función compatible.
Los componentes Select y MultipleSelect solo están pensados para aceptar componentes SelectOption como secundarios. Aunque es posible que puedan mostrar o manejar otros tipos o elementos HTML, esta no es una función compatible.
Los componentes Combobox y MultipleCombobox solo están pensados para aceptar componentes ComboboxOption como secundarios. Aunque es posible que puedan mostrar o manejar otros tipos o elementos HTML, esta no es una función compatible.
Cualquier uso de estos componentes fuera de su ámbito de compatibilidad queda fuera del compromiso de cambios sin interrupciones, ya que dicho uso no se considera parte del contrato de componentes. Estos usos pueden dar lugar a comportamientos inesperados o verse afectados por cambios introducidos en futuras versiones.
Las entradas de Jutro han implementado controladores imperativos como mecanismo para proporcionar acceso a algunas características nativas comunes que podrían ser útiles para usted. Puede utilizar las siguientes características:
Establecer el foco para que usted establezca el foco del usuario en un componente específico.
Desenfocar para eliminar el foco del componente.
Desplazarse hasta el componente para poder llevar al usuario a un área específica de la página.
Estas características se proporcionan a través de la propiedad ref, que las expone de la siguiente manera:
Aunque algunos componentes de Jutro pueden proporcionar características complementarias o una función de ayuda para facilitar el proceso de validación, es su responsabilidad, como desarrollador, manejar la validación de cualquier entrada del usuario (con o sin ayudantes complementarios) y decidir qué mensajes de error se mostrarán.
Los componentes de Jutro se comportan en función de la implementación del desarrollador.
¿Cuándo se muestran los mensajes de error?
Los mensajes de error solo se muestran cuando los pasa al componente a través de la propiedad stateMessages. Esta propiedad recibe un objeto con el siguiente contenido:
El componente muestra cada mensaje de error proporcionado en el mismo orden que en la matriz.
¿Cuándo se produce la validación?
Esta decisión es suya, en calidad de desarrollador. Dado que los componentes no determinan cuándo se realiza la validación ni cuándo se debe mostrar el error, debe implementar la lógica para manejarla de acuerdo con los requisitos del proyecto, por ejemplo, mientras el usuario edita el contenido, cuando el componente pierde el foco y en el envío de formularios.
Consulte la sección Uso para obtener más información sobre cómo y cuándo utilizar MultipleCombobox, y las pestañas específicas para obtener más información sobre las funciones que proporciona el componente.
El gancho useFilteredOptions se utiliza para implementar el mecanismo de filtro basado en la entrada del usuario. Sin embargo, por razones de claridad y simplicidad, no se incluye en algunos ejemplos. Encontrará información más detallada sobre el gancho aquí.
Note: La mayoría de las funciones y propiedades de los cuatro componentes menú desplegable proporcionados no tienen diferencias en cuanto al uso. Algunos ejemplos de otros componentes también pueden ser relevantes para MultipleCombobox.
Cuadro combinado filtrado por la entrada del usuario
Puede deshabilitar por completo cualquiera de los componentes menú desplegable si establece propiedad disabled en true. También puede deshabilitar solo las opciones específicas utilizando la propiedad disabled de los componentes SelectOption y ComboboxOption. En caso de que todo el componente esté deshabilitado, la propiedad disabled de las opciones no tiene ningún efecto.
Este es un comportamiento común para todos los componentes menú desplegables: cuando se establece la propiedad value, el usuario no puede modificar directamente el componente, sino que la implementación del desarrollador la administrará en su totalidad.
Este ejemplo se aplica a todos los componentes menú desplegable:
exportfunctionMultiComboControlled(){ const[updatedValue, setNewValue]=useState([]); constonChange=(e, newValue)=>{ setNewValue(newValue); }; const options =[ <ComboboxOption value={{ id:'1', label:'Option 1', }} />, <ComboboxOption value={{ id:'2', label:'Option 2', }} />, <ComboboxOption value={{ id:'3', label:'Option 3', }} />, <ComboboxOption value={{ id:'4', label:'Option 4', }} />, <ComboboxOption value={{ id:'5', label:'Option 5', }} />, ]; return( <div> <MultipleCombobox label="Choose values" secondaryLabel="This value will be passed to the list of options below" onChange={onChange}> {options} </MultipleCombobox> <br/> <MultipleCombobox label="Changes with the above" value={updatedValue}> {options} </MultipleCombobox> </div> ); }
Utilizando la propiedad ref y los controladores imperativos proporcionados ('focus', 'blur' y 'scrollIntoView'), es posible realizar diferentes acciones nativas. Por ejemplo, establecer el foco en el componente.
En este ejemplo, se utiliza el componente MultipleCombobox:
Los componentes menú desplegable no manejan el proceso de validación, pero usted puede manejar el estado de error y los mensajes que se mostrarán mediante la propiedad stateMessages.
La lógica de mensajes de estado funciona para todos los componentes menú desplegable; a continuación, se muestra un ejemplo de MultipleSelect:
El gancho useFilteredOptions proporciona un manejo básico de datos para el filtrado.
importReact,{ useState }from'react'; import{IntlMessageShape}from'@jutro/prop-types'; import{ useTranslator }from'@jutro/locale'; type SelectValue={ id: string; label:IntlMessageShape; [index:PropertyKey]: unknown; }; /** * @typedef {Object} FilterHookReturnObject * @property {TValue[]} filteredOptions - array of filtered options * @property {function} onSearch - function that takes the onSearch input event * and filters the options based on it * @property {function} resetFilter - used to reset the filtering for options, * after using filteredOptions array resets to initial one * @property {function} onAddNew - function that adds new value to the internal * options array inside the hook and calls appendToSelection that is responsible * for selecting this new value inside the dropdown */ /** * Helper hook for filtering options based on user input. * * @param {TValue[]} initialOptions - initial list of options in component * @param {function} createNewValue - function for constructing value object * from string * @param {function} appendToSelection - callback that is responsible for * appending value to the controlled list of selected values * * @returns {FilterHookReturnObject} - helpers for filtering purposes: * filtered options array, onAddNew and onSearch function to be supplied * to component and resetFilter function */ exportconst useFilteredOptions =<TValueextendsSelectValue=SelectValue>( initialOptions:TValue[], createNewValue?:(value: string)=>TValue, appendToSelection?:(value:TValue)=>void ):{ filteredOptions:TValue[]; onSearch:(event:React.ChangeEvent<HTMLInputElement>) => void; resetFilter: () => void; onAddNew: (newValue: string) => void; } => { const translator =useTranslator(); const[query, setQuery]=useState(''); const[options, setOptions]=useState(initialOptions); // Basic filtering. This part should be changed to cover your needs. const filteredOptions = options.filter(val=> translator(val.label) .trim() .toLowerCase() .includes(query.trim().toLowerCase()) ); // Function that should be passed to the Combobox onSearch prop. // It gets the value of the search term inside Combobox. const onSearch =(event:React.ChangeEvent<HTMLInputElement>) => { setQuery(event.target.value); }; // Function that is responsible for clearing the query // only when the Combobox is on active browser tab. // Typically connected to Combobox onBlur. const resetFilter = () => { if(document.visibilityState==='visible'&&document.hasFocus()){ setQuery(''); } }; // Function responsible on adding new values to both // internal state of filtered items and external // controlled state value const onAddNew = (newValue: string) => { const valueTransformed = createNewValue?.(newValue); setQuery(''); if(valueTransformed){ // adds the value to the internal state setOptions(prevOptions=>[...prevOptions, valueTransformed]); // adds the value to the controlled state appendToSelection?.(valueTransformed); } }; return { filteredOptions, onSearch, resetFilter, onAddNew }; };
Ejemplo de implementación con llamadas de API asíncronas
Las llamadas asincrónicas de la API no se manejan dentro del gancho useFilteredOptions básico. Para este propósito, quizás deba crear su propia implementación que se adapte a sus necesidades específicas. Este es un ejemplo de un gancho personalizado para el componente MultipleCombobox:
importReact,{ useEffect, useState }from'react'; import{ComboboxOption,MultipleCombobox}from'@jutro/components'; import{ useTranslator }from'@jutro/locale'; import{IntlMessageShape}from'@jutro/prop-types'; type SelectValue={ id: string; label:IntlMessageShape; [index:PropertyKey]: unknown; }; constsomeAPICallback=asyncquery=>{ console.log('calling the API'); constCHARACTERS=[ {id:'1',label:'Anakin Skywalker'}, {id:'2',label:'Luke Skywalker'}, {id:'3',label:'Master Yoda'}, {id:'4',label:'Han Solo'}, ]; const result =newPromise(resolve=>{ setTimeout( ()=> resolve( CHARACTERS.filter(val=> val.label .trim() .toLowerCase() .includes(query.trim().toLowerCase()) ) ), 3000 ); }); return result; }; const useFilteredOptions =<TValueextendsSelectValue=SelectValue>():{ filteredOptions:TValue[]; onSearch:(event:React.ChangeEvent<HTMLInputElement>) => void; resetFilter: () => void; loading: boolean; } => { const[query, setQuery]=useState(''); const[filteredOptions, setFilteredOptions]=useState([]); const[loading, setLoading]=useState(true); useEffect(()=>{ setLoading(true); // This is a simple example only, the API callback should be debounced // to ensure the async operation does not overlap with the query change. someAPICallback(query).then((opts:TValue[])=>{ setFilteredOptions(opts); setLoading(false); }); },[query]); // Function that should be passed to the Combobox onSearch prop. // It gets the value of the search term inside Combobox. const onSearch =(event:React.ChangeEvent<HTMLInputElement>) => { setQuery(event.target.value); }; // Function that is responsible for clearing the query // only when the Combobox is on active browser tab. // Typically connected to Combobox onBlur. const resetFilter = () => { if(document.visibilityState==='visible'&&document.hasFocus()){ setQuery(''); } }; return { filteredOptions, onSearch, resetFilter, loading }; }; export const Welcome: React.FC = () => { const translator =useTranslator(); const{ filteredOptions, onSearch, resetFilter, loading }= useFilteredOptions(); return( <MultipleCombobox label="Select options" secondaryLabel="Options filtered by user input" onSearch={onSearch} onBlur={resetFilter} > {loading ?( <span>{translator('Loading...')}</span> ):( filteredOptions.map(({ id, label })=>( <ComboboxOptionkey={id}value={{ id, label }}/> )) )} </MultipleCombobox> ); };
El comportamiento predeterminado del componente MultipleCombobox es contraer las etiquetas de opción cuando no caben en una sola línea. El componente se expande a una vista de varias líneas al hacer clic en la etiqueta que contiene las opciones agrupadas. Este comportamiento es controlado por la propiedad tagsAlwaysExpanded y, de forma predeterminada, está establecido en false.
Para activar el borrado de la entrada con un solo clic en el botón de ícono, establezca la propiedad clearable en true. El botón aparece cuando se selecciona al menos una opción o se escribe cualquier texto. Permite al usuario anular las opciones seleccionadas o eliminar el texto escrito de una vez.
Se agregó la propiedad tagsAlwaysExpanded, la que, cuando se establece en true, anula el comportamiento predeterminado de las etiquetas de opción contraídas.
Se agregó la propiedad clearable, que, cuando se establece en true, permite al usuario borrar las opciones seleccionadas o eliminar el texto escrito con un solo clic en el botón del ícono.
Se introdujo un nuevo componente @jutro/components/MultipleCombobox.
El componente anterior TypeaheadMultiSelectField quedó obsoleto y se trasladó al paquete @jutro/legacy. Para ver su documentación, consulte la versión de la documentaci ón anterior a la 10.0.