Skip to content

Editable table/design nested#3588

Draft
RafaMellado wants to merge 3 commits intoeditable-table/designfrom
editable-table/design-nested
Draft

Editable table/design nested#3588
RafaMellado wants to merge 3 commits intoeditable-table/designfrom
editable-table/design-nested

Conversation

@RafaMellado
Copy link
Contributor

Description

Screenshots (if applicable)

[Link to Figma Design](Figma URL here)

Implementation details

Copilot AI review requested due to automatic review settings March 4, 2026 11:24
@github-actions github-actions bot added the react Changes affect packages/react label Mar 4, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

🔍 Visual review for your branch is published 🔍

Here are the links to:

@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

📦 Alpha Package Version Published

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

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

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

This PR refines the nested/hierarchical table rendering for the EditableTable visualization by threading a fromVisualization hint through table rows/cells, adjusting connector/layout styles, and updating the EditableTable cell editability model.

Changes:

  • Introduce TableVisualizationType and propagate fromVisualization down to Row/NestedRow/TableCell/TreeConnector to allow visualization-specific styling/behavior.
  • Update nested connector + loading skeleton sizing to better match the editable-table layout.
  • Remove the editable(item) callback from EditableTable columns in favor of editType(item) (adding "display-only" / "disabled"), and update stories/tests/docs accordingly.

Reviewed changes

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

Show a summary per file
File Description
packages/react/src/experimental/OneTable/TableCell/index.tsx Passes fromVisualization into nested connector and adjusts loading skeleton min-height by visualization.
packages/react/src/experimental/OneTable/TableCell/TreeConnector/index.tsx Adds visualization-specific CSS variables for nested tree connectors.
packages/react/src/experimental/OneTable/TableCell/NestedCell/index.tsx Adjusts nested cell layout to fill height and changes internal layout/border behavior.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/RowLoading/index.tsx Threads fromVisualization through loading-row rendering.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/Row.tsx Threads fromVisualization into nested row/cell rendering and tweaks first-cell padding logic.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/NestedRow.tsx Makes hierarchical border-hiding logic conditional on being in "table" visualization.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/LoadMore/index.tsx Forces load-more child row columns to be "display-only" for editable-table compatibility.
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/Table.tsx Passes fromVisualization down into Row.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/types.ts Removes the editable(item) column callback.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/consts.ts Extends edit-type registry with "display-only" / "disabled" mappings.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/status/NonEditableCell.tsx Adds a dedicated “display-only” cell component.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/status/DisabledCell.tsx Adds a dedicated “disabled” cell component.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/index.ts Refactors EditableCellProps and adds new edit-type literals.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/TextCell.tsx Updates cell props usage to consume editableColumn.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/EditableCellRenderer.tsx Switches to editType-only control flow and reuses NonEditableCell.
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/tests/EditableCellRenderer.test.tsx Updates tests to align with removal of editable(item).
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/README.md Updates docs to reflect editType-driven behavior (but contains an invalid example).
packages/react/src/experimental/OneDataCollection/types.ts Introduces TableVisualizationType and reuses it in CollectionProps.
packages/react/src/experimental/OneDataCollection/stories/visualizations/editable-table/editable-table.stories.tsx Updates story column config to use editType instead of editable.
packages/react/src/experimental/OneDataCollection/stories/visualizations/editable-table/editable-table.mdx Updates docs/examples to remove editable and use "display-only".
packages/react/src/experimental/OneDataCollection/stories/mockData.tsx Updates mock visualization configs to remove editable and use new edit types.

Comment on lines +9 to +28
export function NonEditableCell<R extends RecordType>({
editableColumn,
item,
}: EditableCellProps<R>) {
const i18n = useI18n()

return (
<BaseCell>
<div
className={cn(
"flex w-full min-w-0",
"cursor-text items-center",
"cursor-pointer w-full",
editableColumn.align === "right" && "justify-end"
)}
>
{renderProperty(item, editableColumn, "editableTable", i18n)}
</div>
</BaseCell>
)
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

NonEditableCell wraps content with BaseCell but never uses isLastColumn to disable the right border. Since BaseCell defaults showRightBorder=true, the last column will still render a right border (and the existing tests expect it to be removed). Pass showRightBorder={!isLastColumn} to BaseCell (and consider readonly if you want the same grey background as the previous readonly rendering).

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +31
export function DisabledCell<R extends RecordType>({
editableColumn,
item,
isLastColumn,
}: EditableCellProps<R>) {
const i18n = useI18n()

return (
<BaseCell>
<div
className={cn(
editableColumn.align === "right" ? "justify-end" : "",
"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",
"cursor-pointer w-full"
)}
>
{renderProperty(item, editableColumn, "editableTable", i18n)}
</div>
</BaseCell>
)
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

DisabledCell conditionally adds a right border based on isLastColumn, but it is wrapped in BaseCell which already applies a right border by default. This means the last column will still have a border (and non-last columns may end up with a double border depending on CSS). Thread isLastColumn into BaseCell via showRightBorder={!isLastColumn} and remove the redundant border classes from the inner div.

Copilot uses AI. Check for mistakes.
render: (item) => item.status,
// No editType → always readonly
editable: () => false,
editType: (item) => "readonly",
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The README example uses editType: (item) => "readonly", but "readonly" is not part of EditableTableCellEditType (current literals include e.g. "display-only" / "disabled", or editType can be omitted/return undefined). This doc snippet will not type-check and may confuse consumers—update it to a valid pattern.

Suggested change
editType: (item) => "readonly",

Copilot uses AI. Check for mistakes.
Comment on lines 6 to 25
@@ -15,10 +14,12 @@ import { TextCell } from "./components/cells/TextCell"
*/
export const editableCellMap: Record<
EditableTableCellEditType,
ComponentType<EditableCellProps>
EditableCellComponent
> = {
text: TextCell,
date: TextCell,
select: TextCell,
multiselect: TextCell,
"display-only": NonEditableCell,
disabled: DisabledCell,
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

EditableCellComponent doesn't include DisabledCell, but editableCellMap assigns disabled: DisabledCell. This should fail type-checking (the record value type excludes typeof DisabledCell). Expand the union to include typeof DisabledCell (or switch back to a generic ComponentType<EditableCellProps<...>> approach).

Copilot uses AI. Check for mistakes.
? {
"--horizontal-offset": `${horizontalOffset + (isDetailedVariant ? 12 : 8)}px`,
"--starting-y": "52px",
"--line-height": `calc(${lineHeight} - ${isDetailedVariant ? 12 : 0}px)`,
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

editableTableVars sets "--line-height": calc(${lineHeight} - ...), but lineHeight can be false when height === 0 (see the height !== 0 && ... expression). That can produce invalid CSS like calc(false - 12px). Only set the editable-table --line-height override when lineHeight is truthy (or compute from height directly as a number).

Suggested change
"--line-height": `calc(${lineHeight} - ${isDetailedVariant ? 12 : 0}px)`,
...(lineHeight
? { "--line-height": `calc(${lineHeight} - ${isDetailedVariant ? 12 : 0}px)` }
: {}),

Copilot uses AI. Check for mistakes.
Comment on lines 63 to +69
const hasId = editableColumn.id !== undefined

if (isEditable && hasId && cellEditType) {
const onChange = (value: string) => {
if (editableColumn.id) {
handleCellChange(editableColumn.id, value)
}
}
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

The onChange guard uses if (editableColumn.id) which will skip updates for falsy-but-valid ids (e.g. an empty string). Since hasId is already computed as id !== undefined, it’s safer to gate on editableColumn.id !== undefined (or reuse hasId).

Copilot uses AI. Check for mistakes.
Comment on lines 92 to 97
it("renders readonly cell when editable returns false", () => {
const column = createEditableColumn({
editable: () => false,
editType: () => "disabled" as const,
})

render(
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

Test name no longer matches the behavior: this case now sets editType: () => "disabled" (the editable callback was removed from the API), but the test description still mentions editable returns false. Update the test name/assertions to reflect the new editType-driven status behavior.

Copilot uses AI. Check for mistakes.
import { AnimatePresence, motion } from "motion/react"
import { useRef } from "react"

import { TableVisualizationType } from "@/experimental/OneDataCollection/types"
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

TableVisualizationType is a type-only export, but it's imported as a value import here. Prefer import type { TableVisualizationType } ... to avoid unnecessary runtime imports and reduce the chance of circular-dependency side effects.

Suggested change
import { TableVisualizationType } from "@/experimental/OneDataCollection/types"
import type { TableVisualizationType } from "@/experimental/OneDataCollection/types"

Copilot uses AI. Check for mistakes.
@@ -1,3 +1,4 @@
import { TableVisualizationType } from "@/experimental/OneDataCollection/types"
Copy link

Copilot AI Mar 4, 2026

Choose a reason for hiding this comment

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

TableVisualizationType is only used as a TypeScript type in this module. Use a type-only import (import type ...) to avoid emitting/keeping a runtime import unnecessarily.

Suggested change
import { TableVisualizationType } from "@/experimental/OneDataCollection/types"
import type { TableVisualizationType } from "@/experimental/OneDataCollection/types"

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Contributor

github-actions bot commented Mar 4, 2026

Coverage Report for packages/react

Status Category Percentage Covered / Total
🔵 Lines 40.93% 8166 / 19947
🔵 Statements 40.32% 8382 / 20787
🔵 Functions 32.11% 1790 / 5574
🔵 Branches 30.58% 4837 / 15815
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/react/src/experimental/OneDataCollection/types.ts 100% 100% 100% 100%
packages/react/src/experimental/OneDataCollection/__stories__/mockData.tsx 0% 0% 0% 0% 80-1883
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 89.65% 71.42% 100% 92.59% 28-30
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/TextCell.tsx 100% 50% 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/EditableTable/components/cells/status/DisabledCell.tsx 100% 75% 100% 100%
packages/react/src/experimental/OneDataCollection/visualizations/collection/EditableTable/components/cells/status/NonEditableCell.tsx 100% 50% 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, 592-671
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/NestedRow.tsx 7.27% 0% 0% 7.27% 104-327, 389
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/Row.tsx 95% 60% 100% 95% 160-177
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/LoadMore/index.tsx 15.78% 0% 0% 16.66% 43-80
packages/react/src/experimental/OneDataCollection/visualizations/collection/Table/components/RowLoading/index.tsx 20% 0% 0% 20% 63-87, 182-215
packages/react/src/experimental/OneTable/TableCell/index.tsx 65% 53.57% 25% 65% 212-243
packages/react/src/experimental/OneTable/TableCell/NestedCell/index.tsx 6.25% 0% 0% 6.25% 40-125
packages/react/src/experimental/OneTable/TableCell/TreeConnector/index.tsx 18.18% 0% 0% 18.18% 40-78, 106-159
packages/react/src/experimental/OneTable/TableCell/utils/nested.ts 76.92% 26.66% 25% 76.92% 22, 32-35, 39, 50, 65-66, 74
Generated in workflow #11497 for commit e94f698 by the Vitest Coverage Report Action

@@ -54,7 +53,6 @@ Use `type: "editableTable"` in the `visualizations` prop:
id: "email",
label: "Email",
editType: () => "text",
Copy link
Contributor

Choose a reason for hiding this comment

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

then this should be:

Suggested change
editType: () => "text",
editType: () => item.role === "Designer" ? "text" : "display-only",

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

Labels

react Changes affect packages/react

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants