Skip to content

feat: editable tables design#3539

Open
RafaMellado wants to merge 1 commit intomainfrom
editable-table/design
Open

feat: editable tables design#3539
RafaMellado wants to merge 1 commit intomainfrom
editable-table/design

Conversation

@RafaMellado
Copy link
Contributor

@RafaMellado RafaMellado commented Feb 26, 2026

Grabacion.de.pantalla.2026-03-03.a.las.16.17.31.mov

Copilot AI review requested due to automatic review settings February 26, 2026 14:34
@RafaMellado RafaMellado force-pushed the editable-table/design branch from 28e6bdd to e010849 Compare February 26, 2026 14:38
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds styling and plumbing needed for “editable tables” UI, including a transparent input mode and per-cell rendering behavior to better match the table design.

Changes:

  • Thread a new transparent prop through InputInputField and use it in editable table cells.
  • Extend table cellRenderer to receive isLastColumn and adjust cell padding/borders accordingly.
  • Introduce BaseCell wrapper for editable table cell layout/borders.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
packages/react/src/ui/input.tsx Passes transparent through Input and updates prop typing.
packages/react/src/ui/InputField/InputField.tsx Adds transparent prop and conditional class logic for transparent rendering.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/Row.tsx Extends cellRenderer to receive isLastColumn and tweaks row/cell classes when rendering custom cells.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/types.ts Import order/layout change.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/index.ts Minor formatting change.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/TextCell.tsx Wraps text cell with BaseCell and uses transparent Input.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/BaseCell.tsx Adds a base wrapper providing consistent cell sizing/borders.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx Accepts isLastColumn and applies right border conditionally.
packages/react/src/experimental/Forms/Fields/Input/internal.tsx Prop typing updated to include transparent.
packages/react/src/experimental/Forms/Fields/Input/F0Input.tsx Adds className to exported input props.

Comment on lines +40 to 41
| "transparent"
>
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"transparent" is added to the Omit list for InputProps, but the component then destructures and forwards transparent. This makes transparent not part of InputProps and will cause a TypeScript error / mismatch. Remove "transparent" from the Omit list, or explicitly add transparent?: boolean back onto InputProps after the Omit.

Suggested change
| "transparent"
>
> & {
transparent?: boolean
}

Copilot uses AI. Check for mistakes.
onKeyDown,
readonly,
buttonToggle,
transparent,
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"transparent" is added to the Omit list for InputProps, but the component then destructures and forwards transparent. This makes transparent not part of InputProps and will cause a TypeScript error / mismatch. Remove "transparent" from the Omit list, or explicitly add transparent?: boolean back onto InputProps after the Omit.

Copilot uses AI. Check for mistakes.
inputRef={ref}
readonly={readonly}
buttonToggle={buttonToggle}
transparent={transparent}
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"transparent" is added to the Omit list for InputProps, but the component then destructures and forwards transparent. This makes transparent not part of InputProps and will cause a TypeScript error / mismatch. Remove "transparent" from the Omit list, or explicitly add transparent?: boolean back onto InputProps after the Omit.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Props are destructured but in the component below

@@ -395,7 +397,7 @@ const InputField = forwardRef<HTMLDivElement, InputFieldProps<string>>(
className={cn(
"flex flex-col gap-2",
"pointer-events-none",
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the previous disabled && "cursor-not-allowed" class entirely (it was replaced by the transparent styling). Disabled inputs likely no longer show the not-allowed cursor. Keep the disabled cursor class and add transparent styles in addition (e.g., include both conditions).

Suggested change
"pointer-events-none",
"pointer-events-none",
disabled && "cursor-not-allowed",

Copilot uses AI. Check for mistakes.
disableHover && "hover:bg-transparent",
isSelected && "bg-f1-background-selected-secondary"
isSelected && "bg-f1-background-selected-secondary",
CellRenderer && "bg-f1-background-secondary"
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When CellRenderer is present, the row gets bg-f1-background-secondary after the selected background class, which can override the selected styling due to class order. Consider moving the CellRenderer background before isSelected (or making it conditional on !isSelected) so selection remains visually correct.

Suggested change
CellRenderer && "bg-f1-background-secondary"
CellRenderer && !isSelected && "bg-f1-background-secondary"

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be decided

rowWithChildren,
tableWithChildren,
}}
{...(CellRenderer ? { className: "p-0 align-middle" } : {})}
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting className via a conditional spread can overwrite any existing className coming from earlier props (e.g., column/cell props) and is easy to break as attributes change. Prefer computing a merged className with cn(...) and passing it explicitly so existing cell-level classes are preserved.

Suggested change
{...(CellRenderer ? { className: "p-0 align-middle" } : {})}
className={CellRenderer ? "p-0 align-middle" : undefined}

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +3

export function BaseCell({ children }: { children: React.ReactNode }) {
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file references React.ReactNode but does not import React types. In a TSX module, React won’t be in scope just for types. Import type { ReactNode } from "react" and use children: ReactNode, or import type * as React from "react".

Suggested change
export function BaseCell({ children }: { children: React.ReactNode }) {
import type { ReactNode } from "react"
export function BaseCell({ children }: { children: ReactNode }) {

Copilot uses AI. Check for mistakes.
Comment on lines +55 to +56
isLastColumn,
}: CellRendererProps<R, Sortings, Summaries> & { isLastColumn: boolean }) {
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Row’s cellRenderer prop type was updated to accept isLastColumn?: boolean (optional), but EditableCellRenderer now requires isLastColumn: boolean. To keep the renderer usable where isLastColumn isn’t provided, make it optional here (and default it), or align the types so both sides agree.

Suggested change
isLastColumn,
}: CellRendererProps<R, Sortings, Summaries> & { isLastColumn: boolean }) {
isLastColumn = false,
}: CellRendererProps<R, Sortings, Summaries> & { isLastColumn?: boolean }) {

Copilot uses AI. Check for mistakes.
Comment on lines +2 to +7

export function BaseCell({ children }: { children: React.ReactNode }) {
return (
<div
className={cn(
"flex w-full min-w-0 min-h-12 border-0 border-r-[1px] border-solid border-f1-border-secondary",
Copy link

Copilot AI Feb 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BaseCell always renders a right border, but the table cell renderer now has isLastColumn to suppress the last-column border. If BaseCell is used in the last column, it will still draw a right border and defeat that intent. Consider letting BaseCell accept an isLastColumn/showRightBorder prop (or removing the border from BaseCell and centralizing border logic in the table cell renderer).

Suggested change
export function BaseCell({ children }: { children: React.ReactNode }) {
return (
<div
className={cn(
"flex w-full min-w-0 min-h-12 border-0 border-r-[1px] border-solid border-f1-border-secondary",
import React from "react"
export function BaseCell({
children,
showRightBorder = true,
}: {
children: React.ReactNode
showRightBorder?: boolean
}) {
return (
<div
className={cn(
"flex w-full min-w-0 min-h-12 border-0 border-r-[1px] border-solid border-f1-border-secondary",
!showRightBorder && "border-r-0",

Copilot uses AI. Check for mistakes.
Base automatically changed from feature/new-editable-table-visualization to main March 3, 2026 08:35
@RafaMellado RafaMellado force-pushed the editable-table/design branch from e010849 to 748673b Compare March 3, 2026 10:35
@github-actions github-actions bot added feat react Changes affect packages/react labels Mar 3, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

✅ No New Circular Dependencies

No new circular dependencies detected. Current count: 0

Copilot AI review requested due to automatic review settings March 3, 2026 14:41
@RafaMellado RafaMellado force-pushed the editable-table/design branch from 748673b to 767d327 Compare March 3, 2026 14:41
@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

🔍 Visual review for your branch is published 🔍

Here are the links to:

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

📦 Alpha Package Version Published

Use pnpm i github:factorialco/f0#npm/alpha-pr-3539 to install the package

Use pnpm i github:factorialco/f0#cc894715557a108f83d47c34e944b1da612b1733 to install this specific commit

@github-actions
Copy link
Contributor

github-actions bot commented Mar 3, 2026

Coverage Report for packages/react

Status Category Percentage Covered / Total
🔵 Lines 40.91% 8159 / 19942
🔵 Statements 40.29% 8374 / 20782
🔵 Functions 32.07% 1788 / 5574
🔵 Branches 30.61% 4836 / 15795
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/react/src/experimental/Forms/Fields/Input/internal.tsx 86.66% 40% 100% 86.66% 65-70, 81
packages/react/src/experimental/OneDataCollection/types.ts 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/EditableTable.tsx 11.11% 100% 0% 11.11% 43-77
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/consts.ts 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/types.ts 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx 80% 68.57% 100% 85.71% 29-33
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/BaseCell.tsx 100% 66.66% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/TextCell.tsx 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/index.ts 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/Table.tsx 73.62% 49.66% 59.25% 73.86% 53-69, 221-225, 393, 441, 472-550, 567, 591-670
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/Row.tsx 94.73% 64.1% 100% 94.73% 157-173
packages/react/src/experimental/OneTable/TableCell/index.tsx 65% 55.55% 25% 65% 193-224
packages/react/src/ui/input.tsx 100% 100% 100% 100%
packages/react/src/ui/InputField/InputField.tsx 80% 85.11% 86.66% 80% 310, 348-349, 362-376, 386-387
packages/react/src/ui/value-display/index.tsx 100% 100% 100% 100%
packages/react/src/ui/value-display/types.ts 100% 100% 100% 100%
packages/react/src/ui/value-display/types/text/index.tsx 100% 100% 100% 100%
Generated in workflow #11466 for commit 2042afa by the Vitest Coverage Report Action

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx:101

  • In edit mode, isLastColumn is used to drop the right border for read-only cells, but editable cells always render BaseCell with showRightBorder defaulting to true, so the last editable column will still show a right border. Pass the isLastColumn information through (e.g. via EditableCellProps / BaseCell.showRightBorder) or move the border styling to a wrapper that can consistently apply it for both editable and read-only content.
  if (isEditable && hasId && cellEditType) {
    const CellComponent = editableCellMap[cellEditType]

    if (CellComponent) {
      const value = getCellValue(localItem, editableColumn)
      const error = editableColumn.id
        ? cellErrors[editableColumn.id]
        : undefined
      const loading = editableColumn.id
        ? (cellLoading[editableColumn.id] ?? false)
        : false

      return (
        // eslint-disable-next-line jsx-a11y/no-static-element-interactions -- stops cell navigation (href/onClick) from firing when interacting with the editor
        <div
          className="pointer-events-auto"
          onClickCapture={(e) => e.stopPropagation()}
          onMouseDownCapture={(e) => e.stopPropagation()}
        >
          <CellComponent
            label={editableColumn.label}
            value={value}
            align={editableColumn.align}
            error={error}
            loading={loading}
            onChange={(v) => {
              if (editableColumn.id) {
                handleCellChange(editableColumn.id, v)
              }
            }}
          />

<CellRenderer item={item} column={column} cellIndex={cellIndex}>
<CellRenderer
item={item}
isLastColumn={cellIndex === columns.length - 1}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isLastColumn is calculated only from columns.length, but rows can render an additional Item Actions column after the mapped columns. When item actions are present, the last data column is not actually the last visible column, so renderers relying on isLastColumn (e.g. to remove the right border) will behave incorrectly. Consider incorporating hasItemActions (and any other trailing columns) into the isLastColumn calculation.

Suggested change
isLastColumn={cellIndex === columns.length - 1}
isLastColumn={!hasItemActions && cellIndex === columns.length - 1}

Copilot uses AI. Check for mistakes.
Comment on lines +239 to +244
<CellRenderer
item={item}
isLastColumn={cellIndex === columns.length - 1}
column={column}
cellIndex={cellIndex}
>
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Table has existing unit tests for cellRenderer customization, but there is no coverage for the newly-added isLastColumn prop being passed to the renderer (including the edge case where an Item Actions column is present). Adding/adjusting a test in Table/__tests__/Table.spec.tsx would prevent regressions for this new API surface.

Copilot generated this review using guidance from repository custom instructions.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot open a new pull request to apply changes based on this feedback

disabled && "cursor-not-allowed bg-f1-background-tertiary",
inputFieldVariants({ size, canGrow }),
],
transparent && "h-full w-full"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When transparent is true, the wrapper drops all focus-within:* ring/border classes (and the input itself doesn't apply focusRing()), which can make keyboard focus indication invisible. Please ensure transparent inputs still have a visible focus style (e.g. apply focusRing()/focus-visible styles to the input or keep a minimal focus ring on the wrapper in transparent mode).

Suggested change
transparent && "h-full w-full"
transparent && [
"h-full w-full",
"relative transition-all group",
"focus-within:outline-none focus-within:ring-1 focus-within:ring-offset-1 focus-within:ring-f1-border-hover",
"active-within:ring-1 active-within:ring-f1-border-hover",
]

Copilot uses AI. Check for mistakes.
Comment on lines +17 to +24
EditableTableCellEditType,
ComponentType<EditableCellProps>
> = {
text: TextCell,
date: TextCell,
select: TextCell,
multiselect: TextCell,
}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EditableTableCellEditType exposes "date" | "select" | "multiselect", but the registry currently maps all of these to TextCell, which is misleading for consumers and makes it easy to accidentally ship the wrong UI. Consider narrowing the union/registry to only the edit types that are actually implemented (e.g. just "text") until dedicated cells exist, or implement distinct components for the additional types.

Suggested change
EditableTableCellEditType,
ComponentType<EditableCellProps>
> = {
text: TextCell,
date: TextCell,
select: TextCell,
multiselect: TextCell,
}
Extract<EditableTableCellEditType, "text">,
ComponentType<EditableCellProps>
> = {
text: TextCell,
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, this is going to be modified soon!

@@ -0,0 +1,24 @@
import { ComponentType } from "react"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ComponentType is only used as a type here; using a type-only import avoids adding an unnecessary runtime import in the emitted JS.

Suggested change
import { ComponentType } from "react"
import type { ComponentType } from "react"

Copilot uses AI. Check for mistakes.
Comment on lines 11 to 15
export type InputProps<T extends string> = Omit<
InputInternalProps<T>,
(typeof privateProps)[number]
>
> & { className?: string }

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change adds className to the public props of the (experimental) Input field. In packages/react, the convention is to avoid exposing className on public component APIs (prefer keeping it private via the privateProps pattern) to reduce styling API surface and make future refactors easier.

Copilot uses AI. Check for mistakes.
@RafaMellado RafaMellado force-pushed the editable-table/design branch 2 times, most recently from e889455 to 5a71400 Compare March 3, 2026 15:41
Copilot AI review requested due to automatic review settings March 3, 2026 15:41
@RafaMellado RafaMellado marked this pull request as ready for review March 3, 2026 15:42
@RafaMellado RafaMellado requested a review from a team as a code owner March 3, 2026 15:42
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx:103

  • isLastColumn is computed and passed down, but it's only used in the non-editable fallback. For editable cells, BaseCell always applies a right border, so the last column will still render a divider (inconsistent with headers and read-only cells). Consider plumbing isLastColumn into the editable cell (e.g., via EditableCellProps) and pass it to BaseCell as showRightBorder={!isLastColumn} (or handle the border in the renderer wrapper).
  if (isEditable && hasId && cellEditType) {
    const CellComponent = editableCellMap[cellEditType]

    if (CellComponent) {
      const value = getCellValue(localItem, editableColumn)
      const error = editableColumn.id
        ? cellErrors[editableColumn.id]
        : undefined
      const loading = editableColumn.id
        ? (cellLoading[editableColumn.id] ?? false)
        : false

      return (
        // eslint-disable-next-line jsx-a11y/no-static-element-interactions -- stops cell navigation (href/onClick) from firing when interacting with the editor
        <div
          className="pointer-events-auto h-full"
          onClickCapture={(e) => e.stopPropagation()}
          onMouseDownCapture={(e) => e.stopPropagation()}
        >
          <CellComponent
            label={editableColumn.label}
            value={value}
            align={editableColumn.align}
            error={error}
            loading={loading}
            onChange={(v) => {
              if (editableColumn.id) {
                handleCellChange(editableColumn.id, v)
              }
            }}
          />
        </div>
      )

@@ -30,11 +30,6 @@ function getCellValue<R extends RecordType>(
if (typeof rendered === "string") return rendered
if (typeof rendered === "number") return String(rendered)

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getCellValue() now silently coerces unsupported render outputs (anything non-string/number) to an empty string. This can make cells appear blank without any signal, which is hard to debug when a column render accidentally returns a renderer definition / ReactNode. Consider restoring a console.warn() in development (or otherwise surfacing an explicit fallback) when a non-primitive is returned.

Suggested change
if (process.env.NODE_ENV !== "production") {
// In development, warn when a non-primitive value is returned from column.render,
// since getCellValue will coerce it to an empty string and the cell will appear blank.
// This commonly happens if a ReactNode or renderer definition is returned by mistake.
// eslint-disable-next-line no-console -- development-only diagnostic
console.warn(
"[EditableTable] getCellValue received a non-primitive render output.",
{
columnId: column.id,
renderedValue: rendered,
}
)
}

Copilot uses AI. Check for mistakes.
@@ -69,16 +68,8 @@ export function EditableCellRenderer<

const hasId = editableColumn.id !== undefined

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the editable path, columns with editType but without an id are now silently rendered as read-only (since updates/errors/loading are keyed by id). Consider restoring a development-time warning when isEditable is true but editableColumn.id is missing, so misconfigured columns are caught early.

Suggested change
if (
process.env.NODE_ENV !== "production" &&
isEditable &&
!hasId &&
typeof console !== "undefined"
) {
// In the editable path, columns without an `id` cannot be updated or tracked for
// errors/loading since those are keyed by `id`. Warn in development so that
// misconfigured columns (with `editType`/editable but no `id`) are caught early.
console.warn(
"[EditableTable] Editable column is missing `id` and will be rendered as read-only.",
{
columnLabel: editableColumn.label,
columnKey: editableColumn.key,
}
)
}

Copilot uses AI. Check for mistakes.
Comment on lines +30 to +31
error={error}
loading={loading}
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TextCell passes error/loading into Input while also enabling transparent. InputField will still render InputMessages for errors, which can expand a table row/cell beyond the intended fixed height. Consider adding a way to suppress inline messages for table cells (and instead show an error border/tooltip), or avoid passing error down in this context.

Suggested change
error={error}
loading={loading}

Copilot uses AI. Check for mistakes.
"focus-within:outline-none focus-within:ring-1 focus-within:ring-offset-1",
"group focus-within:border-f1-border-hover focus-within:ring-1 focus-within:ring-f1-border-hover",
],
transparent && "h-full w-full "
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: there’s trailing whitespace in the transparent && "h-full w-full " class string. Consider removing it to keep classnames clean (also makes twMerge output easier to reason about).

Suggested change
transparent && "h-full w-full "
transparent && "h-full w-full"

Copilot uses AI. Check for mistakes.
@siguenzaraul
Copy link
Contributor

Can you add a description pls?

@RafaMellado RafaMellado force-pushed the editable-table/design branch from 5a71400 to 5a3ac8c Compare March 3, 2026 16:26
Copilot AI review requested due to automatic review settings March 3, 2026 16:51
@RafaMellado RafaMellado force-pushed the editable-table/design branch from 5a3ac8c to 8dce903 Compare March 3, 2026 16:51
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Comment on lines 108 to +114
<div
className={cn(
editableColumn.align === "right" ? "justify-end" : "",
"flex"
"flex p-4 min-h-12 items-center border-0 h-full",
!isLastColumn &&
"border-r-[1px] border-solid border-f1-border-secondary",
"bg-f1-background-secondary h-full"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Readonly cells conditionally omit the right border via !isLastColumn && ..., but editable cells render TextCell/BaseCell without any knowledge of isLastColumn, so the last editable column will still render a right border. Consider threading isLastColumn (or showRightBorder) into the editable cell component so borders are consistent between editable and readonly cells/headers.

Copilot uses AI. Check for mistakes.
Comment on lines +107 to 109
/** Indicates the source visualization type */
fromVisualization?: "table" | "editableTable"
} & VisualizationOptions
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fromVisualization is introduced on the generic CollectionProps, but it’s currently used as a TableCollection-only styling/behavior switch. This broadens the public props surface for every visualization and creates coupling to specific table variants. Consider moving this flag to TableCustomizationProps/table-specific options (or replacing it with a more focused table variant prop) so other visualizations don’t inherit an unrelated prop.

Suggested change
/** Indicates the source visualization type */
fromVisualization?: "table" | "editableTable"
} & VisualizationOptions
} & VisualizationOptions
/**
* Table-specific visualization options.
*
* This type is intended to be used only by table visualizations so that
* table-only styling/behavior flags do not leak into other visualizations.
*/
export type TableVisualizationOptions = {
/** Indicates the source table visualization variant */
fromVisualization?: "table" | "editableTable"
}

Copilot uses AI. Check for mistakes.
tableWithChildren,
}}
className={
CellRenderer
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TableCell styling is changed for any cellRenderer usage (fixed height + p-0 + removing first:pl-6/last:pr-6). This is a behavioral change for TableCollection customization: wrappers that only want to augment default rendering will now lose standard table padding/height. Consider scoping this styling to the editable-table variant (e.g. gate it behind fromVisualization === "editableTable" or a dedicated flag) so existing cellRenderer consumers keep the default cell layout.

Suggested change
CellRenderer
CellRenderer && fromVisualization === "editableTable"

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary for now

Copilot AI review requested due to automatic review settings March 3, 2026 17:00
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (1)

packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx:102

  • isLastColumn is only used in the read-only branch to remove the right border, but editable cells always render BaseCell which applies a right border by default. This will leave a right border on the last editable column while the last read-only column has none. Consider passing isLastColumn (or showRightBorder) into the cell component and wiring it through to BaseCell so borders are consistent.
  if (isEditable && hasId && cellEditType) {
    const CellComponent = editableCellMap[cellEditType]

    if (CellComponent) {
      const value = getCellValue(localItem, editableColumn)
      const error = editableColumn.id
        ? cellErrors[editableColumn.id]
        : undefined
      const loading = editableColumn.id
        ? (cellLoading[editableColumn.id] ?? false)
        : false

      return (
        // eslint-disable-next-line jsx-a11y/no-static-element-interactions -- stops cell navigation (href/onClick) from firing when interacting with the editor
        <div
          className="pointer-events-auto h-full"
          onClickCapture={(e) => e.stopPropagation()}
          onMouseDownCapture={(e) => e.stopPropagation()}
        >
          <CellComponent
            label={editableColumn.label}
            value={value}
            align={editableColumn.align}
            error={error}
            loading={loading}
            onChange={(v) => {
              if (editableColumn.id) {
                handleCellChange(editableColumn.id, v)
              }
            }}
          />
        </div>

@@ -0,0 +1,26 @@
import { ReactNode } from "react"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ReactNode is a type-only import here. Use import type { ReactNode } from "react" to avoid emitting an unnecessary runtime import and to match the type-import pattern used elsewhere in the codebase.

Suggested change
import { ReactNode } from "react"
import type { ReactNode } from "react"

Copilot uses AI. Check for mistakes.
import { Input } from "@/experimental/Forms/Fields/Input"
import { cn } from "@/lib/utils"

import { EditableCellProps } from "."
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EditableCellProps is a type-only import. Prefer import type { EditableCellProps } from "." to prevent generating a runtime import and to keep type/value imports consistent.

Suggested change
import { EditableCellProps } from "."
import type { EditableCellProps } from "."

Copilot uses AI. Check for mistakes.
@RafaMellado RafaMellado force-pushed the editable-table/design branch from e447126 to 2042afa Compare March 3, 2026 17:18
Copy link
Contributor

Copilot AI commented Mar 4, 2026

@RafaMellado I've opened a new pull request, #3584, to work on those changes. Once the pull request is ready, I'll request review from you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat react Changes affect packages/react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants