bazza/ui

repository·main·Indexed 21 days ago

https://github.com/bazzalabs/ui

An open-source library of modern React components. It features specialized tools for data tables, including the useDataTableFilters hook for managing client-side and server-side filtering, a type-safe column configuration builder (createColumnConfigHelper), and the DataTableFilter UI component. The library also provides utility components like TypeTable for displaying technical property information and Info for popover descriptions, with built-in integration support for TanStack Table.

Tokens
11.5K
Snippets
38
Records
48
Agent score
73%

What's inside bazza/ui

  1. How to handle option and multi-option columns

    main

    For columns with discrete choices (option or multiOption), you can provide options in two ways:

    1. Declared Options

    Use this for fixed sets of options (static) or options fetched from an API (remote). Use the .options() method on the builder.

    2. Inferred Options

    Only available for client-side filtering. This is useful when options aren't known at build time and you don't have a dedicated endpoint. The component loops through the available data to extract unique values. If the values aren't already in the ColumnOption shape, use .transformOptionFn() to map them.

    Note: For server-side filtering, you must use the declared options approach because the client data is not representative of the full dataset.

    dtf
      .option()
      .accessor((row) => row.assignee)
      .id('assignee')
      .displayName('Assignee')
      .icon(UserCheckIcon)
      .transformOptionFn((u) => ({
        value: u.id,
        label: u.name,
        icon: <UserAvatar user={u} />
      }))
  2. How filtering strategies work (Client vs Server)

    main

    The FilterStrategy determines where the data filtering logic is executed:

    • client strategy: The client receives the entire dataset and performs filtering locally in the browser. This is ideal for smaller datasets.
    • server strategy: The client sends filter requests to the server. The server applies the filters and returns only the matching subset of data. This is required for large datasets to avoid loading everything into memory.
  3. How useDataTableFilters works

    main

    The useDataTableFilters hook is the primary entrypoint for managing filter state and logic. It decouples the filtering logic from the UI, allowing you to use the same state with any table library (TanStack Table, AG Grid, etc.) or even no library at all.

    Each table should have its own instance. The hook returns:

    • columns: The processed column configurations.
    • filters: The current state of all active filters.
    • actions: Methods to mutate the filter state.
    • strategy: The filtering strategy being used ('client' or 'server').

    To render the UI, pass these returned values into the <DataTableFilters /> component.

    const { columns, filters, actions, strategy } = useDataTableFilters({
      strategy: 'client',
      data: issues.data ?? [],
      columnsConfig,
    })
    
    return (
      <div>
        <DataTableFilters
          columns={columns}
          filters={filters}
          actions={actions}
          strategy={strategy}
        />
        <DataTable />
        <DataTablePagination />
      </div>
    )
  4. Integrate data table filters with TanStack Table

    main

    If you are using TanStack Table (TST) with client-side filtering, you can use the provided integration to automatically map the data table's filter state and logic to TST.

    Note: If you are using server-side filtering, this integration is not required; simply feed your data into your TST instance.

    Key Functions

    • createTSTColumns: Overrides the filterFn property for each filterable TST column with the appropriate internal filter function based on your column configurations.
    • createTSTFilters: Converts the filter state from useDataTableFilters() into a TST-compatible ColumnFiltersState.

    Requirements

    Important: You must specify an id for each TST column definition that matches the id of the corresponding column filter configuration.

    const { columns, filters, actions, strategy } = useDataTableFilters({ /* ... */ })
    
    const tstColumns = useMemo(
      () =>
        createTSTColumns({
          columns: tstColumnDefs, // your TanStack Table column definitions
          configs: columns, // Your column configurations
        }),
      [columns],
    )
    
    const tstFilters = useMemo(() => createTSTFilters(filters), [filters])
    
    const table = useReactTable({
      data: issues.data ?? [],
      columns: tstColumns,
      getRowId: (row) => row.id,
      getCoreRowModel: getCoreRowModel(),
      getFilteredRowModel: getFilteredRowModel(),
      state: {
        columnFilters: tstFilters
      }
    })
  5. Migrate TanStack Table to the new filtering system

    main

    If you are using TanStack Table, you must migrate from using the meta property in column definitions to the new column configuration builder and filter instance model.

    Follow these steps to migrate:

    1. Remove meta property: Delete the meta property from your existing TanStack Table column definitions.
    2. Use Column Configuration Builder: Implement the new column configuration using the column configuration builder.
    3. Create a Filters Instance: Initialize a new filters instance to manage filtering logic.
    4. Setup TST Integration: Configure the TanStack Table (TST) integration to connect the new filtering logic with your table instance.
  6. Implement server-side filtering

    main

    To perform filtering on the server rather than the client, set the strategy to 'server' in the useDataTableFilters configuration.

    When using server-side filtering, you typically:

    1. Manage filter state in the URL (e.g., using nuqs).
    2. Pass the filters state to your data fetching query.
    3. Provide options (for option-based columns) and faceted data (for unique/min/max values) to the hook so it can render the UI correctly.

    Example configuration:

    const { columns, filters, actions, strategy } = useDataTableFilters({
      strategy: 'server',
      data: issues.data ?? [],
      columnsConfig,
      options: {
        status: statusOptions,
        assignee: userOptions,
        labels: labelOptions,
      },
      faceted: {
        status: facetedStatuses.data,
        assignee: facetedUsers.data,
        labels: facetedLabels.data,
        estimatedHours: facetedEstimatedHours.data,
      },
    })