[Bug]: PropertyFilter `virtualScroll` is ignored for enum token value lists

Abierto Apto para principiantes
#5,244 1 comentario 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

@Mittalnew ya está trabajando en esto.

Desde el 6/11/2026.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
72/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
react, typescript
Área
frontend

Línea de trabajo

Empieza en internal.tsx, donde virtualScroll se pasa a PropertyFilterAutosuggest, y luego sigue la rama enum hasta PropertyEditorContentEnum, que no acepta ni reenvía la prop a EmbeddedMultiselect. Revisa también ValueInputEnum, que renderiza InternalMultiselect sin virtualScroll, y compáralo con ValueInputAuto. Está terminado cuando las listas de valores enum se virtualizan tanto en el campo de entrada del filtro como en el editor de tokens, y la reproducción muestra que el número de opciones se mantiene pequeño.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug
Browser

Firefox

Package version

v3.0.1409

React version

v18.3.1

Description

Description

PropertyFilter has a virtualScroll prop for large filteringOptions sets. Its docs say to turn it on above about 500 options. The prop works for regular (tokenType: 'value') properties, but it has no effect on properties whose operator uses tokenType: 'enum'. Their value list is always rendered in full.

Two places show an enum value list, and neither gets the prop:

  1. Filtering input (typing Property = ): internal.tsx passes virtualScroll to PropertyFilterAutosuggest. When the enum step is active, though, PropertyFilterAutosuggest renders customForm.content (PropertyEditorContentEnum → EmbeddedMultiselect) and returns before the options list that receives virtualScroll. PropertyEditorContentEnum doesn't accept or forward the prop.
  2. Token editor (editing an existing enum token): ValueInputEnum renders InternalMultiselect without virtualScroll. By comparison, ValueInputAuto hardcodes virtualScroll={true}.

EmbeddedMultiselect and InternalMultiselect both already support virtualScroll, so the prop just needs to be passed through.

Expected: Setting virtualScroll on PropertyFilter virtualizes enum value lists in both places, the same way it does for value tokens.

Actual: Enum value lists always render every option. With a few thousand values, opening the list gets slow.

Source code
import React, { useEffect, useRef, useState } from 'react';
import Box from '@cloudscape-design/components/box';
import ColumnLayout from '@cloudscape-design/components/column-layout';
import Container from '@cloudscape-design/components/container';
import Header from '@cloudscape-design/components/header';
import PropertyFilter from '@cloudscape-design/components/property-filter';
import SpaceBetween from '@cloudscape-design/components/space-between';

const HOST_VALUE_COUNT = 5000;

const HOST_FILTERING_OPTIONS = Array.from({ length: HOST_VALUE_COUNT }, (_, index) => ({
  propertyKey: 'host',
  value: `host-${index}`,
}));

const VALUE_TOKEN_PROPERTIES = [
  {
    key: 'host',
    propertyLabel: 'Host',
    groupValuesLabel: 'Host values',
    operators: [{ operator: '=', tokenType: 'value' }],
  },
];

const ENUM_TOKEN_PROPERTIES = [
  {
    key: 'host',
    propertyLabel: 'Host',
    groupValuesLabel: 'Host values',
    operators: [{ operator: '=', tokenType: 'enum' }],
  },
];

const I18N_STRINGS = {
  filteringAriaLabel: 'Filter hosts',
  filteringPlaceholder: 'Type "Host = " to open the value list',
  groupValuesText: 'Values',
  groupPropertiesText: 'Properties',
  operatorsText: 'Operators',
  operationAndText: 'and',
  operationOrText: 'or',
  operatorEqualsText: 'Equals',
  operatorDoesNotEqualText: 'Does not equal',
  operatorContainsText: 'Contains',
  operatorDoesNotContainText: 'Does not contain',
  editTokenHeader: 'Edit filter',
  propertyText: 'Property',
  operatorText: 'Operator',
  valueText: 'Value',
  cancelActionText: 'Cancel',
  applyActionText: 'Apply',
  allPropertiesLabel: 'All properties',
  clearFiltersText: 'Clear filters',
  removeTokenButtonAriaLabel: () => 'Remove token',
  enteredTextLabel: text => `Use: "${text}"`,
};

function useRenderedOptionCount(containerRef) {
  const [renderedOptionCount, setRenderedOptionCount] = useState(0);
  useEffect(() => {
    const intervalId = setInterval(() => {
      const container = containerRef.current;
      setRenderedOptionCount(container ? container.querySelectorAll('[role="option"]').length : 0);
    }, 300);
    return () => clearInterval(intervalId);
  }, [containerRef]);
  return renderedOptionCount;
}

function HostPropertyFilterDemo({ title, filteringProperties }) {
  const containerRef = useRef(null);
  const [query, setQuery] = useState({ operation: 'and', tokens: [] });
  const renderedOptionCount = useRenderedOptionCount(containerRef);

  return (
    <Container header={<Header variant="h2">{title}</Header>}>
      <SpaceBetween size="m">
      <Box variant="awsui-key-label">Options currently in the DOM</Box>
        <Box fontSize="display-l" fontWeight="bold">
          {renderedOptionCount}
        </Box>
        <div ref={containerRef}>
          <PropertyFilter
            virtualScroll={true}
            query={query}
            onChange={({ detail }) => setQuery(detail)}
            filteringProperties={filteringProperties}
            filteringOptions={HOST_FILTERING_OPTIONS}
            i18nStrings={I18N_STRINGS}
            countText={`${query.tokens.length} filters`}
          />
        </div>
      </SpaceBetween>
    </Container>
  );
}

export default function App() {
  return (
    <Box padding="l">
      <SpaceBetween size="l">
        <Header
          variant="h1"
          description={`Both filters set virtualScroll={true} and have ${HOST_VALUE_COUNT} host values. Type "Host = " into each one.`}
        >
          PropertyFilter virtualScroll with enum tokens
        </Header>
        <ColumnLayout columns={2}>
          <HostPropertyFilterDemo title="tokenType: 'value' (virtualized)" filteringProperties={VALUE_TOKEN_PROPERTIES} />
          <HostPropertyFilterDemo title="tokenType: 'enum' (not virtualized)" filteringProperties={ENUM_TOKEN_PROPERTIES} />
        </ColumnLayout>
      </SpaceBetween>
    </Box>
  );
}
Reproduction

https://codesandbox.io/p/sandbox/elastic-lamport-5lfgg5?file=%2Fsrc%2FApp.js%3A63%2C53

Code of Conduct
Lenguaje dominante
TypeScript
Estrellas
2.7k
Forks
248
Merge medio
2 d 4 h
PR fusionados (30 d)
93

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de cloudscape-design/components

Todos los issues de cloudscape-design/components

Issues similares

Más issues de TypeScript

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.