Skip to content

Gustavohsdp/lec 223 create base table component presentation layer#251

Merged
JoaoGSP merged 11 commits into
developmentfrom
gustavohsdp/lec-223-create-base-table-component-presentation-layer
May 23, 2025
Merged

Gustavohsdp/lec 223 create base table component presentation layer#251
JoaoGSP merged 11 commits into
developmentfrom
gustavohsdp/lec-223-create-base-table-component-presentation-layer

Conversation

@Gustavohsdp

@Gustavohsdp Gustavohsdp commented May 17, 2025

Copy link
Copy Markdown
Contributor

Pull request info

Link to Linear task

linear task

Description of the changes proposed

  • Refactored and standardized table implementations by extracting them into reusable and modular components. This improves code maintainability, consistency across the application, and facilitates future enhancements or reuse.

DOD checklist

  • The code is complete and according to developers’ standards.
  • I have performed a self-review of my code.
  • Meet the acceptance criteria.
  • Unit tests are written and green.
  • Test coverage: __ %.
  • Integration tests are written and green.
  • Changes were communicated and updated in the ticket description.
  • Reviewed and accepted by the Product Owner.
  • End-to-end test are successful.

Summary by CodeRabbit

  • New Features

    • Introduced a reusable modal for defining array types with multiple dimensions, enhancing user experience and accessibility.
    • Added a generic, flexible table component supporting selection, filtering, resizing, and inline editing for various data types.
  • Refactor

    • Unified multiple individual table action buttons into a single reusable actions component for streamlined interfaces.
    • Replaced custom table and modal implementations across array, enumerated, structure, global variables, instances, tasks, and variables editors with generic, reusable components.
    • Simplified and improved layout and responsiveness of editor action bars and controls.
  • Style

    • Improved styling of table rows, modal dialogs, and action buttons with enhanced accessibility and dark mode compatibility.
  • Chores

    • Removed obsolete components and code, reducing duplication and simplifying the codebase.

@Gustavohsdp
Gustavohsdp requested a review from JoaoGSP May 17, 2025 20:18
@linear

linear Bot commented May 17, 2025

Copy link
Copy Markdown

@coderabbitai

coderabbitai Bot commented May 17, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

This update introduces a set of reusable table and modal components to standardize UI patterns across the application. Custom table and modal implementations are replaced with generic components, and table action buttons are consolidated into a single, configurable component. The codebase is refactored for consistency, maintainability, and improved accessibility.

Changes

File(s) Change Summary
src/renderer/components/_atoms/generic-table/index.tsx
src/renderer/components/_atoms/generic-data-type-table/index.tsx
Added new generic table components for flexible, reusable table rendering and data management.
src/renderer/components/_atoms/table-actions/index.tsx Added a new component to render configurable table action buttons as a group.
src/renderer/components/_atoms/dimensions-modal/index.tsx Added a reusable modal component for array dimension editing.
src/renderer/components/_atoms/dimensions-modal/array-dimensions-input/index.tsx Refactored input styling and accessibility for dimension input fields.
src/renderer/components/_molecules/data-types/array/table/index.tsx
src/renderer/components/_molecules/data-types/enumerated/table/index.tsx
Refactored to use the new generic data type table component, removing manual table rendering.
src/renderer/components/_molecules/data-types/array/index.tsx
src/renderer/components/_molecules/data-types/enumerated/index.tsx
src/renderer/components/_molecules/data-types/structure/index.tsx
Replaced individual table action buttons with the new TableActions component and adjusted layouts.
src/renderer/components/_molecules/data-types/structure/table/index.tsx
src/renderer/components/_molecules/global-variables-table/index.tsx
src/renderer/components/_molecules/instances-table/index.tsx
src/renderer/components/_molecules/task-table/index.tsx
src/renderer/components/_molecules/variables-table/index.tsx
Replaced custom table logic with the new GenericTable component, removing manual DOM and state management.
src/renderer/components/_molecules/data-types/structure/table/elements/array-modal.tsx
src/renderer/components/_molecules/variables-table/elements/array-modal.tsx
Replaced custom array dimension modals with the new DimensionsModal component.
src/renderer/components/_molecules/variables-table/elements/array-input.tsx Removed the old ArrayDimensionsInput component (now handled by the new modal).
src/renderer/components/_organisms/global-variables-editor/index.tsx
src/renderer/components/_organisms/instances-editor/index.tsx
src/renderer/components/_organisms/task-editor/index.tsx
src/renderer/components/_organisms/variables-editor/index.tsx
Refactored to use the new TableActions component for table row actions.
src/renderer/components/_organisms/explorer/index.tsx Minor code clean-up and class name adjustment for layout consistency.

Sequence Diagram(s)

sequenceDiagram
    participant ParentComponent
    participant GenericTable
    participant TableActions
    participant DimensionsModal

    ParentComponent->>GenericTable: Pass columns, data, selection, update handler
    ParentComponent->>TableActions: Pass actions array (add, remove, move, etc.)
    ParentComponent->>DimensionsModal: Pass open state, type, dimensions, handlers
    GenericTable->>ParentComponent: Call update handler on cell edit
    TableActions->>ParentComponent: Invoke action handlers on button click
    DimensionsModal->>ParentComponent: Invoke callbacks on save/cancel/type change
Loading

Assessment against linked issues

Objective Addressed Explanation
Create a generic, reusable table component for any data (LEC-223)
Support for various cell types (input, select, span/paragraph) in the table (LEC-223)
Provide visual feedback for the active row in the table (LEC-223)

Suggested labels

enhancement

Suggested reviewers

  • JoaoGSP

Poem

In the code garden where tables grow,
Rabbits hop where new components flow.
Rows now shimmer, actions align,
Modals pop up, looking fine!
With buttons grouped and logic neat,
This refactor’s a bunny treat! 🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn config production Use --omit=dev instead.
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-05-23T02_26_13_062Z-debug-0.log

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02ff66d and 7ad52c2.

📒 Files selected for processing (4)
  • src/renderer/components/_molecules/data-types/array/index.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/enumerated/index.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/structure/index.tsx (2 hunks)
  • src/renderer/components/_organisms/task-editor/index.tsx (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/renderer/components/_organisms/task-editor/index.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/renderer/components/_molecules/data-types/array/index.tsx
  • src/renderer/components/_molecules/data-types/enumerated/index.tsx
  • src/renderer/components/_molecules/data-types/structure/index.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build (windows-latest)
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🔭 Outside diff range comments (8)
src/renderer/components/_molecules/data-types/array/table/index.tsx (2)

35-55: ⚠️ Potential issue

Memoisation array misses handleBlur (and captures a stale closure)

handleBlur is defined after this useMemo and is recreated on every render, but it is not included in the dependency list.
Consequently, columns may hold on to an outdated version of handleBlur, and therefore to stale tableData / updateDatatype references, leading to silently‐dropped updates.

-const columns = React.useMemo(
-  () => [
+const handleBlur = React.useCallback(
+  (rowIndex: number) => {
+    /* ...existing body... */
+  },
+  [tableData, name, updateDatatype, setArrayTable],
+)
+
+const columns = React.useMemo(
+  () => [

and update the deps to:

-  [name, selectedRow],
+  [name, selectedRow, handleBlur],

This keeps columns and the captured callback safely in sync.


57-90: 🛠️ Refactor suggestion

Avoid direct DOM queries inside React components

handleBlur reaches for the input with document.getElementById.
Because the component already owns the value via React state (DimensionCell), the same operation can be performed without breaking out of the React data-flow, e.g.:

cell: (cellProps) => (
  <DimensionCell
    /* … */
    onBlur={(value) => handleBlur(cellProps.row.index, value)}
  />
)

and pass the edited value directly, removing both the getElementById call and the need to trim again.

This reduces coupling to the DOM structure and eliminates a potential source of bugs when IDs collide.

src/renderer/components/_molecules/data-types/structure/table/elements/array-modal.tsx (2)

65-78: ⚠️ Potential issue

dimensions.splice mutates state in place – causes unpredictable behaviour

splice operates on the same array instance stored in React state, yet setDimensions is not called afterwards.
Although setSelectedInput triggers a re-render, React still sees the same array reference and may bail out of updates or produce subtle bugs.

-const [removed] = dimensions.splice(index, 1)
-dimensions.splice(index - 1, 0, removed)
-setSelectedInput((index - 1).toString())
+setDimensions((prev) => {
+  const next = [...prev]
+  const [removed] = next.splice(index, 1)
+  next.splice(index - 1, 0, removed)
+  return next
+})
+setSelectedInput((index - 1).toString())

Do the same for the down branch.
This preserves immutability, plays well with React dev-tools, and avoids side-effects in render logic.


102-111: 🛠️ Refactor suggestion

Guard against empty or whitespace-only dimensions earlier

dimensionToSave filters only empty strings, so a value like " " passes through.
arrayValidation already rejects this, but calling it once per dimension (during blur) can miss the scenario where all rows are blank due to mass deletion.

Simplest fix:

-const dimensionToSave = dimensions.filter((value) => value !== '')
+const dimensionToSave = dimensions.map((v) => v.trim()).filter(Boolean)

This rejects whitespace-only entries and avoids malformed PLC type strings.

src/renderer/components/_molecules/global-variables-table/index.tsx (1)

28-33: ⚠️ Potential issue

cell: 'Global' is typed as an accessor, not a renderer
createColumnHelper().accessor expects a renderer function for cell; passing a raw string is interpreted as an accessor key, which will look for row.original['Global'] and render undefined. Use a constant renderer instead:

-  columnHelper.accessor('class', {
-    header: 'Class',
-    enableResizing: true,
-    cell: 'Global',
-  }),
+  columnHelper.accessor('class', {
+    header: 'Class',
+    enableResizing: true,
+    cell: () => 'Global',
+  }),
src/renderer/components/_molecules/data-types/enumerated/index.tsx (2)

25-31: ⚠️ Potential issue

initialValueData never updates when the prop changes

The first useEffect runs only on mount. If the parent edits data.initialValue later, the local state will be stale.

-useEffect(() => {
-  setInitialValueData(data.initialValue || '')
-}, [])
+useEffect(() => {
+  setInitialValueData(data.initialValue || '')
+}, [data.initialValue])

88-91: 🛠️ Refactor suggestion

Avoid mutating prevRows inside setState

Inside the moveRowUp callback you reassign prevRows = newRows.
Even though it “works”, mutating the parameter defies React’s immutability expectations and may hide bugs in the future.

Replace the whole callback with a pure calculation and return the new array only once.

src/renderer/components/_organisms/variables-editor/index.tsx (1)

189-203: ⚠️ Potential issue

Deleting the last (or only) row can leave selectedRow at ‑2

When the table has a single variable, selectedRow is 0.
After deletion we compute selectedRow - 1 (→ -1) and immediately store it, which later becomes parseInt(selectedRow) → -1 → out-of-bounds access.

Guard against the empty-table case:

-      updateModelVariables({ display: 'table', selectedRow: selectedRow - 1 })
+      updateModelVariables({
+        display: 'table',
+        selectedRow: Math.max(selectedRow - 1, ROWS_NOT_SELECTED),
+      })

(or skip the field altogether when no rows remain).

🧹 Nitpick comments (13)
src/renderer/components/_molecules/data-types/array/index.tsx (1)

207-254: Well-executed refactoring of array dimensions UI section

The consolidation of table action buttons using the TableActions component and the restructured layout improves code organization and maintainability.

However, the use of a fixed width (w-[600px]) on line 207 may limit responsiveness on smaller screens. Consider using a relative width (e.g., w-full with a max-width constraint) for better adaptability across different screen sizes.

-      <div className='flex w-[600px] flex-col gap-3'>
+      <div className='flex w-full max-w-[600px] flex-col gap-3'>
src/renderer/components/_molecules/data-types/array/table/index.tsx (1)

92-127: Border-reset logic duplicates behaviour now owned by GenericDataTypeTable

All the manual class-name juggling (resetBorders, setBorders) replicates selection styling that the new generic table could expose internally.
Consider moving the styling concern into GenericDataTypeTable (or a shared hook) to:

  1. Keep this component declarative and focused on data.
  2. Eliminate two imperative useEffect runs per row selection and the repeated className string concat.

Reducing DOM mutations will also improve rendering performance on large tables.

src/renderer/components/_atoms/dimensions-modal/array-dimensions-input/index.tsx (1)

40-55: Accessibility nit – input lacks an explicit label and useful aria-* attributes

Because the surrounding <div> is clickable and the <input> can be non-interactive (pointer-events-none), screen-reader users might have trouble understanding what the field represents.

Consider:

-<input
+<input
+  aria-label={`Array dimension ${id}`}
+  aria-disabled={selectedInput !== id}

or tying it to a visually-hidden <label htmlFor={id}>Dimension {id}</label> for better semantics.

src/renderer/components/_atoms/generic-table/index.tsx (2)

102-106: maxSize == size prevents growth

defaultColumn sets size and maxSize to 128, effectively disabling expansion while still allowing shrink to minSize.
If the design should allow the user to widen columns, set a larger maxSize or omit it (react-table falls back to ∞).


117-118: Disable debugTable in production builds

debugTable: true floods the console and ships unnecessary code. Flip it to false (or gate behind process.env.NODE_ENV !== 'production').

src/renderer/components/_molecules/data-types/enumerated/index.tsx (2)

123-125: Hard-coded width (600px) hinders re-use

Embedding magic numbers inside the component makes it impossible to adapt to different layouts/break-points.

Expose it as a prop or rely on flex/grid to size naturally:

-<div className='w-[600px]'>
+<div className={cn('w-full', props.fixedWidth && `max-w-[${props.fixedWidth}px]`)}>

152-165: Duplicate enable/disable logic – consider extracting

The up/down buttons repeat the same long boolean expressions.
Extract a helper:

const canMoveUp   = selectedRow > 0;
const canMoveDown = selectedRow > -1 && selectedRow < tableData.length - 1;

This improves readability and de-duplicates the predicates.

src/renderer/components/_molecules/data-types/structure/table/index.tsx (1)

57-82: Heavy re-mapping on every cell edit

updateData maps the entire tableData array for each change, causing O(n) work per keystroke.
For large structures this may lag.

Consider:

  1. Updating only the changed item (produce from immer is handy).
  2. Debouncing updateDatatype if it triggers expensive store writes.
src/renderer/components/_molecules/variables-table/index.tsx (2)

11-60: Consider deduplicating the two column-sets to remove maintenance overhead

columnsPrograms and columns are 95 % identical. Every time a header is renamed, a size is tuned, or a cell component evolves, both arrays must be kept in sync, which is error-prone.

A tiny helper that injects / removes the location column would avoid the duplication:

-const columnsPrograms = [...]
-const columns = [...]
+const baseColumns = [
+  idCol(),
+  nameCol(),
+  classCol(),
+  typeCol(),
+  initialValueCol(),
+  documentationCol(),
+  debugCol(),
+]
+
+const columnsPrograms = baseColumns          // program POU – no location
+const columns         = [
+  ...baseColumns.slice(0, 4),
+  locationCol(),                              // insert location
+  ...baseColumns.slice(4),
+]

Besides being DRY this makes both tables evolve uniformly.


137-160: Return value from updateData is ignored – consider making it void

updateData currently does return updateVariable(...), but GenericTable never consumes that value.
If updateVariable is asynchronous this could create a false expectation of “fire-and-await”.
Explicitly discarding the return value clarifies intent:

-      updateData={(rowIndex, columnId, value) => {
+      updateData={(rowIndex, columnId, value): void => {
         if (columnId === 'class' && filterValue !== undefined && filterValue !== 'all' && filterValue !== value) {
           return
         }
-        return updateVariable({ ... })
+        updateVariable({ ... })
       }}
src/renderer/components/_organisms/variables-editor/index.tsx (2)

347-421: Action button set duplicated – extract to a helper to keep desktop & mobile in sync

The actions array for TableActions is copy-pasted for the XL and the mobile view. Any tweak (e.g. disabling logic, tool-tips, icon change) must be performed twice.

A quick win is to memoise the array once and reuse it:

const commonActions = useMemo(() => [
  { ariaLabel: 'Add table row button',    onClick: handleCreateVariable,
    icon: <PlusIcon className='!stroke-brand' />, id: 'add-variable-button' },
  { ariaLabel: 'Remove table row button', onClick: handleRemoveVariable,
    disabled: selectedRowInvalid || forbiddenVariableToBeRemoved,
    icon: <MinusIcon />, id: 'remove-variable-button' },
  { ariaLabel: 'Move table row up button', onClick: () => handleRearrangeVariables(-1),
    disabled: selectedRowInvalid || selectedRow === 0,
    icon: <StickArrowIcon direction='up' className='stroke-[#0464FB]' />,
    id: 'move-variable-up-button' },
  { ariaLabel: 'Move table row down button', onClick: () => handleRearrangeVariables(1),
    disabled: selectedRowInvalid || selectedRow === tableData.length - 1,
    icon: <StickArrowIcon direction='down' className='stroke-[#0464FB]' />,
    id: 'move-variable-down-button' },
], [editorVariables, tableData.length, forbiddenVariableToBeRemoved])

…and then <TableActions actions={commonActions} /> in both places.
That guarantees perfect parity and makes further maintenance simpler.


205-215: handleFilterChange mixes “All”/'all' cases – normalise once

The function lower-cases the filter value only when adding it to columnFilters, but editorVariables.classFilter stores the original cased enum.
Later comparisons keep juggling .toLowerCase().

Consider storing the canonical lower-case in the model and formatting for display only in the UI, reducing the number of conversions required.

src/renderer/components/_atoms/dimensions-modal/index.tsx (1)

68-101: Minor accessibility improvement – connect label & select with htmlFor/id

The “Base type” <label> is not programmatically associated with the <SelectTrigger> (no matching htmlFor/id).
Screen-reader users will not know what the combo-box does.

-<label ...>Base type</label>
-<SelectTrigger id='array-base-type' .../>
+<label htmlFor='array-base-type' ...>Base type</label>
+<SelectTrigger id='array-base-type' .../>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 45ab6aa and 02ff66d.

📒 Files selected for processing (23)
  • src/renderer/components/_atoms/dimensions-modal/array-dimensions-input/index.tsx (1 hunks)
  • src/renderer/components/_atoms/dimensions-modal/index.tsx (1 hunks)
  • src/renderer/components/_atoms/generic-data-type-table/index.tsx (1 hunks)
  • src/renderer/components/_atoms/generic-table/index.tsx (1 hunks)
  • src/renderer/components/_atoms/table-actions/index.tsx (1 hunks)
  • src/renderer/components/_molecules/data-types/array/index.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/array/table/index.tsx (3 hunks)
  • src/renderer/components/_molecules/data-types/enumerated/index.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/enumerated/table/index.tsx (3 hunks)
  • src/renderer/components/_molecules/data-types/structure/index.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/structure/table/elements/array-modal.tsx (2 hunks)
  • src/renderer/components/_molecules/data-types/structure/table/index.tsx (3 hunks)
  • src/renderer/components/_molecules/global-variables-table/index.tsx (2 hunks)
  • src/renderer/components/_molecules/instances-table/index.tsx (2 hunks)
  • src/renderer/components/_molecules/task-table/index.tsx (2 hunks)
  • src/renderer/components/_molecules/variables-table/elements/array-input.tsx (0 hunks)
  • src/renderer/components/_molecules/variables-table/elements/array-modal.tsx (2 hunks)
  • src/renderer/components/_molecules/variables-table/index.tsx (3 hunks)
  • src/renderer/components/_organisms/explorer/index.tsx (2 hunks)
  • src/renderer/components/_organisms/global-variables-editor/index.tsx (2 hunks)
  • src/renderer/components/_organisms/instances-editor/index.tsx (2 hunks)
  • src/renderer/components/_organisms/task-editor/index.tsx (3 hunks)
  • src/renderer/components/_organisms/variables-editor/index.tsx (9 hunks)
💤 Files with no reviewable changes (1)
  • src/renderer/components/_molecules/variables-table/elements/array-input.tsx
🧰 Additional context used
🧬 Code Graph Analysis (7)
src/renderer/components/_molecules/variables-table/elements/array-modal.tsx (1)
src/renderer/components/_atoms/dimensions-modal/index.tsx (1)
  • DimensionsModal (34-174)
src/renderer/components/_molecules/data-types/structure/table/elements/array-modal.tsx (1)
src/renderer/components/_atoms/dimensions-modal/index.tsx (1)
  • DimensionsModal (34-174)
src/renderer/components/_molecules/task-table/index.tsx (2)
src/renderer/components/_atoms/generic-table/index.tsx (1)
  • GenericTable (177-177)
src/types/PLC/open-plc.ts (1)
  • PLCTask (327-327)
src/renderer/components/_atoms/generic-table/index.tsx (2)
src/utils/index.ts (1)
  • cn (3-3)
src/renderer/components/_atoms/table/index.tsx (6)
  • Table (132-132)
  • TableHeader (132-132)
  • TableRow (132-132)
  • TableHead (132-132)
  • TableBody (132-132)
  • TableCell (132-132)
src/renderer/components/_molecules/data-types/structure/table/index.tsx (2)
src/renderer/components/_atoms/generic-table/index.tsx (1)
  • GenericTable (177-177)
src/types/PLC/open-plc.ts (1)
  • PLCStructureVariable (326-326)
src/renderer/components/_organisms/variables-editor/index.tsx (1)
src/utils/index.ts (1)
  • cn (3-3)
src/renderer/components/_atoms/dimensions-modal/index.tsx (2)
src/types/PLC/open-plc.ts (1)
  • BaseType (311-311)
src/renderer/components/_atoms/dimensions-modal/array-dimensions-input/index.tsx (1)
  • ArrayDimensionsInput (65-65)
🔇 Additional comments (18)
src/renderer/components/_organisms/explorer/index.tsx (1)

69-69: LGTM! Good UI enhancement.

The addition of the max-w-lg class to the ResizablePanel helps maintain a consistent UI by preventing the explorer panel from becoming too wide on larger screens.

src/renderer/components/_organisms/global-variables-editor/index.tsx (1)

165-199: Great refactoring to improve component reusability.

Replacing multiple individual action buttons with the consolidated TableActions component significantly improves code maintainability while preserving the original functionality. This change follows good component design principles by:

  1. Reducing code duplication
  2. Creating a consistent UI pattern for table actions
  3. Maintaining proper accessibility with aria labels
  4. Preserving all original functionality and disabled states

This aligns well with the PR's goal of standardizing table implementations.

src/renderer/components/_organisms/instances-editor/index.tsx (1)

155-189: Consistent implementation of the TableActions pattern.

The refactoring maintains consistency with the same pattern used in other editor components, which is excellent for codebase uniformity. This approach ensures that:

  1. All table interactions follow the same UI pattern
  2. Future modifications to table actions will be easier to implement
  3. The code remains DRY (Don't Repeat Yourself)

This standardization aligns perfectly with the PR objective of creating reusable and modular components.

src/renderer/components/_organisms/task-editor/index.tsx (1)

156-192: Good TableActions implementation with improved spacing.

The refactoring successfully implements the standardized TableActions pattern while also improving the UI with better spacing through the added mr-2 class. This change:

  1. Maintains consistency with other editor components
  2. Improves the visual appearance with proper spacing
  3. Preserves all the original functionality and disabled states

This comprehensive approach to standardization across all table-based components will significantly enhance maintainability.

src/renderer/components/_molecules/data-types/structure/index.tsx (1)

192-223: Well-executed refactoring of table actions!

Consolidating the individual action buttons into a single TableActions component significantly improves code maintainability. The approach keeps all the same functionality while creating a more consistent UI pattern throughout the application.

src/renderer/components/_molecules/data-types/enumerated/table/index.tsx (3)

1-1: Good import addition for new generic table component

The import of GenericDataTypeTable aligns with the goal of standardizing table implementations across the application.


7-8: Clean import refactoring

Streamlining the imports to include only the necessary functions from @tanstack/react-table improves code clarity.


190-197: Excellent simplification of table rendering logic

Replacing the custom table implementation with the reusable GenericDataTypeTable component reduces code duplication and improves maintainability while preserving all the original functionality.

src/renderer/components/_molecules/variables-table/elements/array-modal.tsx (2)

1-1: Good import addition for new dimensions modal component

The import of DimensionsModal aligns with the standardization goals of the PR.


151-166: Excellent modal implementation refactoring

The replacement of custom modal implementation with the reusable DimensionsModal component significantly simplifies the code while preserving all functionality. All necessary props are correctly passed to maintain the same behavior.

src/renderer/components/_molecules/data-types/array/index.tsx (2)

4-4: Good import addition for new table actions component

The import of TableActions aligns with the standardization goals of the PR.


216-243: Well-executed implementation of TableActions component

The refactoring of multiple individual action buttons into a single TableActions component with an array of configuration objects maintains all functionality while promoting consistency and reusability across the application.

src/renderer/components/_atoms/generic-data-type-table/index.tsx (1)

34-36: handleRowClick typing likely breaks with custom TableRow component
You declare handleRowClick: (target: HTMLTableRowElement) => void but pass e.currentTarget coming from a custom TableRow component, not a native <tr>. Unless TableRow forwards the ref to an actual <tr>, this violates the contract and can produce runtime‐only bugs when consumers access native properties (e.g. .cells). Consider:

type HandleRowClick = (rowElement: HTMLElement) => void

or expose the row’s logical data instead of the DOM element altogether.

src/renderer/components/_molecules/global-variables-table/index.tsx (1)

73-82: Row index ≠ stable row identifier – confirm updateVariable expectation
updateVariable({ scope: 'global', rowId: rowIndex, ... }) passes the visible row index. If rows can be sorted, filtered, or removed, the index may not match the variable’s persistent id, causing the wrong row to be updated.

Please verify what rowId represents in the store and pass a stable key instead (e.g. tableData[rowIndex].id).

src/renderer/components/_molecules/task-table/index.tsx (1)

61-70: Validate row identifier passed to updateTask
As with the variables table, rowId is the array index, not a unique task identifier. Re-ordering tasks (e.g. by priority) will risk updating the wrong store entry. Pass tableData[rowIndex].id or similar to guarantee correctness.

src/renderer/components/_atoms/generic-table/index.tsx (1)

86-97: Effect dependencies look incomplete

filterValue is compared by reference; when the parent supplies a new string instance with the same value the effect will still run.
More importantly, if you ever switch to controlled filtering (columnFilters) the borders will not reset unless you remember to add that state to this array.

-}, [filterValue])
+}, [filterValue, columnFilters])

Please double-check the intended re-paint triggers.

src/renderer/components/_molecules/data-types/enumerated/index.tsx (1)

54-70: selectedRow !== null check is inconsistent with the sentinel -1

selectedRow is initialised with -1, so the condition passes even when nothing is selected.
Prefer a unified sentinel (either null or -1) and test explicitly:

-if (arrayTable.selectedRow !== null) {
+if (arrayTable.selectedRow > -1) {

This applies to removeRow, moveRowUp, and moveRowDown.

src/renderer/components/_molecules/data-types/structure/table/index.tsx (1)

11-19: id accessor may break if the data lacks an id field

PLCStructureVariable (see open-plc.ts) has no explicit id property.
React-Table will therefore read undefined, and the column will render empty while still relying on the value for keys.

If the intention is to show the row index, switch to:

columnHelper.display({
  id: '#',
  header: '#',
  cell: (info) => info.row.index + 1,
  size: 64,
  enableResizing: true,
})

Comment on lines +49 to +57
<GenericTable<PLCInstance>
columns={columns}
tableData={tableData}
selectedRow={selectedRow}
handleRowClick={handleRowClick}
// @ts-expect-error - The data value is a literal type that need to be parsed
updateData={(rowIndex, columnId, value) => updateInstance({ rowId: rowIndex, data: { [columnId]: value } })}
tableContext='Instances'
/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

ts-expect-error hides a typing mismatch that is easy to solve

The generic updateData lambda is re-created on every render and suppresses the TypeScript error instead of fixing it.
Two quick wins:

  1. Memoise the callback:

    const updateData = React.useCallback(
      (rowIndex: number, columnId: keyof PLCInstance, value: PLCInstance[keyof PLCInstance]) =>
        updateInstance({ rowId: rowIndex, data: { [columnId]: value } }),
      [updateInstance],
    )
  2. Pass it without the @ts-expect-error.

Removing the suppression improves static safety and avoids unnecessary re-renders.

🤖 Prompt for AI Agents
In src/renderer/components/_molecules/instances-table/index.tsx around lines 49
to 57, the updateData callback is recreated on every render and uses
@ts-expect-error to suppress a typing mismatch. To fix this, memoize the
updateData function using React.useCallback with the correct parameter types
(rowIndex as number, columnId as keyof PLCInstance, and value as
PLCInstance[keyof PLCInstance]) and include updateInstance in the dependency
array. Then remove the @ts-expect-error comment and pass the memoized updateData
callback to the GenericTable component to improve type safety and prevent
unnecessary re-renders.

Comment on lines +22 to +29
<TableActionButton
key={index}
aria-label={action.ariaLabel}
onClick={action.onClick}
disabled={action.disabled}
id={action.id}
{...buttonProps}
>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure per-action disabled/id props are not accidentally overridden
{...buttonProps} is spread after the action-specific attributes, so any disabled or id coming from buttonProps will silently win over the values coming from action. This makes the component harder to reason about and can break row-level logic.

-          disabled={action.disabled}
-          id={action.id}
-          {...buttonProps}
+          {...buttonProps}
+          disabled={action.disabled}
+          id={action.id}

Re-ordering keeps the override direction intuitive: generic defaults first, then action specifics.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<TableActionButton
key={index}
aria-label={action.ariaLabel}
onClick={action.onClick}
disabled={action.disabled}
id={action.id}
{...buttonProps}
>
<TableActionButton
key={index}
aria-label={action.ariaLabel}
onClick={action.onClick}
{...buttonProps}
disabled={action.disabled}
id={action.id}
>
🤖 Prompt for AI Agents
In src/renderer/components/_atoms/table-actions/index.tsx around lines 22 to 29,
the spread of {...buttonProps} comes after the action-specific props like
disabled and id, causing any disabled or id in buttonProps to override the
action values. To fix this, reorder the props so that {...buttonProps} is spread
first, followed by the action-specific props, ensuring that action.disabled and
action.id take precedence and prevent accidental overrides.

Comment on lines +21 to +24
{actions.map((action, index) => (
<TableActionButton
key={index}
aria-label={action.ariaLabel}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid using array index as React key
key={index} will force React to re-mount buttons when the order of actions changes, losing focus/animation state. Prefer a stable identifier (action.id or ariaLabel).

-        <TableActionButton
-          key={index}
+        <TableActionButton
+          key={action.id ?? action.ariaLabel}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{actions.map((action, index) => (
<TableActionButton
key={index}
aria-label={action.ariaLabel}
{actions.map((action, index) => (
<TableActionButton
key={action.id ?? action.ariaLabel}
aria-label={action.ariaLabel}
🤖 Prompt for AI Agents
In src/renderer/components/_atoms/table-actions/index.tsx around lines 21 to 24,
replace the use of the array index as the React key in the TableActionButton
component with a stable and unique identifier such as action.id or
action.ariaLabel to prevent unnecessary remounting and preserve component state
during reordering.

Comment on lines +28 to +33
{table.getRowModel().rows.map((row, index: number) => (
<TableRow
id={`${index}`}
key={index}
className='h-8'
selected={selectedRow === index}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Stable row keys improve diffing & accessibility
key={index} and id={${index}} are brittle when the data order changes (sort, filter, drag-reorder). Use row.id (from TanStack) or a domain identifier if available.

-                id={`${index}`}
-                key={index}
+                id={String(row.id)}
+                key={row.id}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{table.getRowModel().rows.map((row, index: number) => (
<TableRow
id={`${index}`}
key={index}
className='h-8'
selected={selectedRow === index}
{table.getRowModel().rows.map((row, index: number) => (
<TableRow
- id={`${index}`}
- key={index}
+ id={String(row.id)}
+ key={row.id}
className='h-8'
selected={selectedRow === index}
🤖 Prompt for AI Agents
In src/renderer/components/_atoms/generic-data-type-table/index.tsx around lines
28 to 33, replace the use of index for the key and id props with a stable
identifier like row.id provided by TanStack. This ensures keys remain consistent
across data operations like sorting or filtering, improving React's diffing
performance and accessibility. Update both key and id attributes to use row.id
or another unique domain-specific identifier if available.

Comment on lines +67 to +69
// @ts-expect-error - The data value is a literal type that need to be parsed
updateData={(rowIndex, columnId, value) => updateTask({ rowId: rowIndex, data: { [columnId]: value } })}
tableContext='Tasks'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid silencing type errors with @ts-expect-error; fix the typing instead
The comment hides a genuine mismatch between value’s literal type and the expected field type, which will propagate unchecked data into the store.

Suggestion: overload updateData generically or cast value as PLCTask[keyof PLCTask] to satisfy the compiler without suppressing it globally.

-      // @ts-expect-error - The data value is a literal type that need to be parsed
-      updateData={(rowIndex, columnId, value) => updateTask({ rowId: rowIndex, data: { [columnId]: value } })}
+      updateData={(rowIndex, columnId, value) =>
+        updateTask({ rowId: rowIndex, data: { [columnId]: value as PLCTask[keyof PLCTask] } })
+      }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// @ts-expect-error - The data value is a literal type that need to be parsed
updateData={(rowIndex, columnId, value) => updateTask({ rowId: rowIndex, data: { [columnId]: value } })}
tableContext='Tasks'
updateData={(rowIndex, columnId, value) =>
updateTask({ rowId: rowIndex, data: { [columnId]: value as PLCTask[keyof PLCTask] } })
}
tableContext='Tasks'
🤖 Prompt for AI Agents
In src/renderer/components/_molecules/task-table/index.tsx around lines 67 to
69, the use of @ts-expect-error to suppress type errors on the updateData prop
hides a real type mismatch between the literal type of value and the expected
field type. To fix this, remove the @ts-expect-error comment and instead either
create a generic overload for updateData that properly types value or explicitly
cast value as PLCTask[keyof PLCTask] to satisfy the TypeScript compiler while
preserving type safety.

Comment on lines +43 to +61
const resetBorders = () => {
const parent = tableBodyRef.current
const header = tableHeaderRef.current
if (!parent?.children || !header?.children) return

const rows = Array.from(parent.children)
const headers = Array.from(header.children)
rows.forEach((row) => {
row.className = cn(
row.className,
'[&:last-child>td]:border-b-neutral-500 [&>td:first-child]:border-l-neutral-500 [&>td:last-child]:border-r-neutral-500 [&>td]:border-b-neutral-300',
'dark:[&>td:first-child]:border-l-neutral-500 dark:[&>td:last-child]:border-r-neutral-500 dark:[&>td]:border-b-neutral-800',
'shadow-none dark:shadow-none',
)
})
headers.forEach((header) => {
header.className = cn(header.className, '[&>th]:border-neutral-300 dark:[&>th]:border-neutral-800')
})
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid costly DOM class mutations inside resetBorders

resetBorders iterates over every row and header element and blindly appends utility-classes to the existing className.
On tables with hundreds of rows this runs on every selectedRow / filterValue change, leading to unnecessary layout thrashing and ever-growing className strings (duplicates are never removed).

Consider a render-time approach instead:

-rows.forEach((row) => { row.className = cn(row.className, /* … */) })
+// Prefer: add a CSS class conditionally in JSX (e.g. `selected` / `unselected`)
+// and let Tailwind / CSS handle the style, avoiding imperative DOM updates.

This removes a whole class of performance issues and makes the visual state declarative.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/components/_atoms/generic-table/index.tsx around lines 43 to 61,
the resetBorders function inefficiently mutates the className of every row and
header on each call, causing performance issues and className bloat. Refactor to
remove this DOM manipulation by applying the border utility classes
declaratively during render, using conditional className logic or CSS-in-JS to
ensure classes are set once based on state, avoiding repeated appends and
improving performance.

Comment on lines +63 to +84
const setBorders = () => {
const row = tableBodyRowRef.current
const parent = tableBodyRef.current
const header = tableHeaderRef.current
if (!row || !parent || !header) return

const headerRow = row === parent?.firstChild ? header?.lastElementChild : null
const element = headerRow ?? row?.previousElementSibling

if (element) {
element.className = cn(
element.className,
'[&>td]:border-b-brand dark:[&>td]:border-b-brand',
'[&>th]:border-b-brand dark:[&>th]:border-b-brand',
)
}
row.className = cn(
row.className,
'[&:last-child>td]:border-b-brand [&>td:first-child]:border-l-brand [&>td:last-child]:border-r-brand [&>td]:border-b-brand',
'dark:[&>td:first-child]:border-l-brand dark:[&>td:last-child]:border-r-brand dark:[&>td]:border-b-brand',
)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Risk of stale border-highlight & duplicated classes in setBorders

  1. The method only adds the “brand” border utilities; resetBorders never strips them, so toggling the same row several times can accumulate duplicate class names.
  2. row === parent?.firstChild works only if React never re-orders DOM nodes; virtualised tables or future re-sorts will break the logic.
  3. Direct string concatenation bypasses React’s diffing and may collide with Tailwind’s class-dedupe.

If the visual emphasis must remain imperative, at least use classList APIs:

-element.className = cn(element.className, '[&>td]:border-b-brand', …)
+element.classList.add('border-brand-highlight')

…and remove the class first to guarantee idempotency.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/renderer/components/_atoms/generic-table/index.tsx around lines 63 to 84,
the setBorders function adds border classes by concatenating strings, which can
cause duplicate classes and stale highlights when toggling rows multiple times.
To fix this, replace the string concatenation with classList.add and
classList.remove calls to ensure classes are added and removed idempotently.
Also, avoid relying on row === parent?.firstChild for header detection; instead,
use a more reliable method to identify the header row to support dynamic table
reordering or virtualization.

Comment on lines +145 to +153
<TableRow
id={row.id}
key={row.id}
className='h-8 cursor-pointer'
onClick={(e) => handleRowClick(e.currentTarget)}
selected={selectedRow === parseInt(row.id)}
ref={selectedRow === parseInt(row.id) ? tableBodyRowRef : null}
>
{row.getVisibleCells().map((cell) => (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

row.id is not guaranteed to be numeric

parseInt(row.id) assumes row.id is "0" | "1" | …".
As soon as you add grouping or pagination, ids become "0_1" or "row_42", breaking selection logic.

-selected={selectedRow === parseInt(row.id)}
-ref={selectedRow === parseInt(row.id) ? tableBodyRowRef : null}
+selected={selectedRow === row.index}
+ref={selectedRow === row.index ? tableBodyRowRef : null}

React-Table exposes row.index explicitly for exactly this purpose.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<TableRow
id={row.id}
key={row.id}
className='h-8 cursor-pointer'
onClick={(e) => handleRowClick(e.currentTarget)}
selected={selectedRow === parseInt(row.id)}
ref={selectedRow === parseInt(row.id) ? tableBodyRowRef : null}
>
{row.getVisibleCells().map((cell) => (
<TableRow
id={row.id}
key={row.id}
className='h-8 cursor-pointer'
onClick={(e) => handleRowClick(e.currentTarget)}
- selected={selectedRow === parseInt(row.id)}
- ref={selectedRow === parseInt(row.id) ? tableBodyRowRef : null}
+ selected={selectedRow === row.index}
+ ref={selectedRow === row.index ? tableBodyRowRef : null}
>
{row.getVisibleCells().map((cell) => (
🤖 Prompt for AI Agents
In src/renderer/components/_atoms/generic-table/index.tsx around lines 145 to
153, the code uses parseInt(row.id) assuming row.id is numeric, but row.id can
be non-numeric with grouping or pagination, breaking selection logic. Replace
all instances of parseInt(row.id) with row.index, which React-Table provides
explicitly as a reliable numeric identifier for rows, to fix the selection and
ref assignment logic.

Comment thread src/renderer/components/_atoms/dimensions-modal/index.tsx
Comment on lines +114 to +138
<TableActions
actions={[
{
ariaLabel: 'Add table row button',
onClick: onAddDimension,
icon: <PlusIcon className='!stroke-brand' />,
id: 'add-new-row-button',
},
{
ariaLabel: 'Remove table row button',
onClick: () => onRemoveDimension(selectedInput),
icon: <MinusIcon className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row up button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'up'),
icon: <StickArrowIcon direction='up' className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row down button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'down'),
icon: <StickArrowIcon direction='down' className='stroke-[#0464FB]' />,
},
]}
/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Disable “remove / move” actions when no dimension is selected

onRemoveDimension(selectedInput) and Number(selectedInput) execute even when selectedInput === '', which will pass an empty string / NaN to your handlers.

Add disabled flags mirroring the variables editor pattern:

-{
-  ariaLabel: 'Remove table row button',
-  onClick: () => onRemoveDimension(selectedInput),
-  icon: <MinusIcon ... />,
-},
+{
+  ariaLabel: 'Remove table row button',
+  onClick: () => onRemoveDimension(selectedInput),
+  disabled: selectedInput === '',
+  icon: <MinusIcon ... />,
+},

…and the same for the up/down actions.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<TableActions
actions={[
{
ariaLabel: 'Add table row button',
onClick: onAddDimension,
icon: <PlusIcon className='!stroke-brand' />,
id: 'add-new-row-button',
},
{
ariaLabel: 'Remove table row button',
onClick: () => onRemoveDimension(selectedInput),
icon: <MinusIcon className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row up button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'up'),
icon: <StickArrowIcon direction='up' className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row down button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'down'),
icon: <StickArrowIcon direction='down' className='stroke-[#0464FB]' />,
},
]}
/>
<TableActions
actions={[
{
ariaLabel: 'Add table row button',
onClick: onAddDimension,
icon: <PlusIcon className='!stroke-brand' />,
id: 'add-new-row-button',
},
{
ariaLabel: 'Remove table row button',
onClick: () => onRemoveDimension(selectedInput),
disabled: selectedInput === '',
icon: <MinusIcon className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row up button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'up'),
disabled: selectedInput === '',
icon: <StickArrowIcon direction='up' className='stroke-[#0464FB]' />,
},
{
ariaLabel: 'Move table row down button',
onClick: () => onRearrangeDimensions(Number(selectedInput), 'down'),
disabled: selectedInput === '',
icon: <StickArrowIcon direction='down' className='stroke-[#0464FB]' />,
},
]}
/>
🤖 Prompt for AI Agents
In src/renderer/components/_atoms/dimensions-modal/index.tsx around lines 114 to
138, the remove and move actions are enabled even when no dimension is selected,
causing handlers to receive invalid inputs like empty string or NaN. Fix this by
adding a disabled property to the remove, move up, and move down actions that is
true when selectedInput is empty or invalid, preventing these actions from being
triggered without a valid selection.

onBlur={() => handleUpdate()}
onBlur={handleUpdate}
value={inputValue}
aria-selected={selectedInput === id ? 'true' : 'false'}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Q: Does this need to be a string?

@JoaoGSP

JoaoGSP commented May 23, 2025

Copy link
Copy Markdown
Member

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 23, 2025

Copy link
Copy Markdown
Contributor
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@JoaoGSP JoaoGSP left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@JoaoGSP
JoaoGSP merged commit 19311ed into development May 23, 2025
@JoaoGSP
JoaoGSP deleted the gustavohsdp/lec-223-create-base-table-component-presentation-layer branch May 23, 2025 14:26
@coderabbitai coderabbitai Bot mentioned this pull request Jun 13, 2025
9 tasks
This was referenced Jul 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants