Share: What I'm building with the new Polaris Web Components

@Alan_G Below you’ll find some code that you can copy into the react-router template (no dependencies) demonstrating how I’m doing selection/bulk action at the moment – tapping into the page actions. I’ve excluded the non-selection bits (like search, sort, filtering) to make it simple. Check it out on your mobile and on web – it’s not a great experience on mobile, but at least the action menu shows well, i.e. it overlays the screen even as you scroll.

Here’s what it looks like in my app at the moment:
output

import { useCallback, useState } from "react";

interface DemoProduct {
  id: string;
  name: string;
  sku: string;
  price: string;
  stock: number;
  status: "active" | "archived";
  createdDate: string;
}

const DEMO_PRODUCTS: DemoProduct[] = [
  {
    id: "1",
    name: "Wireless Headphones",
    sku: "WH-001",
    price: "$79.99",
    stock: 45,
    status: "active",
    createdDate: "2024-10-15",
  },
  {
    id: "2",
    name: "USB-C Cable",
    sku: "UC-002",
    price: "$12.99",
    stock: 120,
    status: "active",
    createdDate: "2024-09-22",
  },
  {
    id: "3",
    name: "Phone Case",
    sku: "PC-003",
    price: "$24.99",
    stock: 0,
    status: "archived",
    createdDate: "2024-08-10",
  },
  {
    id: "4",
    name: "Screen Protector",
    sku: "SP-004",
    price: "$9.99",
    stock: 200,
    status: "active",
    createdDate: "2024-10-01",
  },
  {
    id: "5",
    name: "Portable Charger",
    sku: "PC-005",
    price: "$49.99",
    stock: 32,
    status: "active",
    createdDate: "2024-09-15",
  },
];

export default function TableDemo() {
  const [rowSelection, setRowSelection] = useState<Record<string, boolean>>({});

  const selectedCount = Object.values(rowSelection).filter((v) => v).length;

  const handleSelectAll = useCallback((checked: boolean) => {
    if (checked) {
      const allSelected: Record<string, boolean> = {};
      DEMO_PRODUCTS.forEach((product) => {
        allSelected[product.id] = true;
      });
      setRowSelection(allSelected);
    } else {
      setRowSelection({});
    }
  }, []);

  const handleRowSelect = useCallback((productId: string, checked: boolean) => {
    setRowSelection((prev) => ({
      ...prev,
      [productId]: checked,
    }));
  }, []);

  const allSelected = DEMO_PRODUCTS.every((p) => rowSelection[p.id]);

  return (
    <s-page heading="Table Demo">
      {selectedCount > 0 && (
        <>
          <s-button
            commandFor="bulk-actions-menu"
            accessibilityLabel="Selected product bulk actions"
            slot="secondary-actions"
          >
            {selectedCount} products selected
          </s-button>
          <s-menu accessibilityLabel="Bulk actions" id="bulk-actions-menu">
            <s-button icon="person">Assign to consignor</s-button>
            <s-button icon="person-remove" tone="critical">
              Remove from consignor
            </s-button>
            <s-button icon="money">Set commission</s-button>
          </s-menu>
        </>
      )}
      <s-section padding="none">
        <s-table>
          <s-table-header-row>
            <s-table-header listSlot="inline">
              <s-checkbox
                checked={allSelected}
                onChange={(e) => handleSelectAll(e.currentTarget.checked)}
              />
            </s-table-header>
            <s-table-header listSlot="primary">Product Name</s-table-header>
            <s-table-header>SKU</s-table-header>
            <s-table-header format="currency">Price</s-table-header>
            <s-table-header format="numeric">Stock Level</s-table-header>
            <s-table-header listSlot="secondary">Status</s-table-header>
            <s-table-header>Created Date</s-table-header>
          </s-table-header-row>

          <s-table-body>
            {DEMO_PRODUCTS.map((product) => (
              <s-table-row key={product.id}>
                <s-table-cell>
                  <s-checkbox
                    checked={rowSelection[product.id] ?? false}
                    onChange={(e) =>
                      handleRowSelect(product.id, e.currentTarget.checked)
                    }
                  />
                </s-table-cell>
                <s-table-cell>{product.name}</s-table-cell>
                <s-table-cell>{product.sku}</s-table-cell>
                <s-table-cell>{product.price}</s-table-cell>
                <s-table-cell>{product.stock}</s-table-cell>
                <s-table-cell>
                  <s-badge
                    tone={product.status === "active" ? "success" : "auto"}
                  >
                    {product.status}
                  </s-badge>
                </s-table-cell>
                <s-table-cell>{product.createdDate}</s-table-cell>
              </s-table-row>
            ))}
          </s-table-body>
        </s-table>
      </s-section>
    </s-page>
  );
}