Skip to content

Tshepo/f/drawer component#3197

Merged
James-Baloyi merged 3 commits intoshesha-io:mainfrom
Tshepo1103-lab:tshepo/f/drawer-component
Apr 29, 2025
Merged

Tshepo/f/drawer component#3197
James-Baloyi merged 3 commits intoshesha-io:mainfrom
Tshepo1103-lab:tshepo/f/drawer-component

Conversation

@Tshepo1103-lab
Copy link
Copy Markdown
Contributor

@Tshepo1103-lab Tshepo1103-lab commented Apr 25, 2025

#3018

Summary by CodeRabbit

  • New Features
    • Enhanced drawer component styling options, allowing separate background styles, flexible width and height settings, and advanced box styling.
  • Refactor
    • Centralized and simplified style management for the drawer component, consolidating multiple style properties into unified structures.
    • Updated settings form to use stable IDs and new property names for header and footer styles.
  • Chores
    • Improved default style handling and removed unused constants for cleaner configuration.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 25, 2025

Walkthrough

This update refactors the styling system for the Drawer component by centralizing and renaming style-related properties. The IShaDrawer interface now uses backgroundStyles instead of background, introduces a dimensions object for width and height, and adds stylingBoxAsCSS for more granular box styling. The Drawer component's internal logic is simplified, consolidating style management and removing asynchronous fetching and validation. The settings form updates property namespaces for header and footer styles, and component IDs are now fixed. The defaultStyles function incorporates new default properties, while the legacy initialStyle object is removed.

Changes

File(s) Change Summary
shesha-reactjs/src/designer-components/drawer/drawer.tsx Updated IShaDrawer interface: renamed background to backgroundStyles, added dimensions and stylingBoxAsCSS. Component now uses dimensions for sizing, separates background and box styling, and updates how styles are merged and applied throughout the Drawer.
shesha-reactjs/src/designer-components/drawer/index.tsx Refactored Drawer Factory: consolidated style management into allStyles, removed separate state/effects for styles, eliminated async style fetching/validation, and simplified style merging. Migrator now adds headerStyles and footerStyles to device-specific objects. Imports reorganized.
shesha-reactjs/src/designer-components/drawer/models.ts Removed individual style-related properties (background, border, shadow, etc.) from IDrawerProps; added headerStyles and footerStyles for consolidated style management. Re-added background later in the interface.
shesha-reactjs/src/designer-components/drawer/settingsForm.ts Replaced dynamic IDs with fixed strings in settings form. Updated property namespaces from headerStyle/footerStyle to headerStyles/footerStyles and adjusted nested property paths. Changed some default values (e.g., width) and refined tooltips/expressions. No changes to function signatures or control flow.
shesha-reactjs/src/designer-components/drawer/utils.ts Modified defaultStyles to include style and a shadow object with default values. Removed the exported initialStyle constant, consolidating all style defaults into defaultStyles.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant DrawerComponent
    participant ShaDrawer
    participant StylesManager

    User->>DrawerComponent: Configure Drawer (settings, styles, dimensions)
    DrawerComponent->>StylesManager: Consolidate allStyles (headerStyles, footerStyles, backgroundStyles, stylingBoxAsCSS, dimensions)
    DrawerComponent->>ShaDrawer: Pass consolidated styles and dimensions
    ShaDrawer->>ShaDrawer: Apply styles (backgroundStyles, stylingBoxAsCSS, dimensions)
    ShaDrawer-->>User: Render styled Drawer
Loading

Possibly related PRs

  • shesha-io/shesha-framework#3128: Adds a simple background property to IShaDrawer and adjusts style application; the current PR extends and refines this with backgroundStyles, dimensions, and stylingBoxAsCSS.

Suggested reviewers

  • James-Baloyi
  • AlexStepantsov

Poem

In the Drawer’s cozy nook,
Styles and shadows undertook
A tidy dance, now all aligned—
Dimensions, boxes, well-defined.
With IDs fixed and names renewed,
The rabbit hops, quite pleased and cheered,
For drawers now look sharp and steered!

((\
( -.-)
o_(")(")

✨ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🔭 Outside diff range comments (2)
shesha-reactjs/src/designer-components/drawer/settingsForm.ts (2)

608-914: ⚠️ Potential issue

Prop path mismatch: UI writes headerStyles.* but component still reads headerStyle

settingsForm now stores header styles under headerStyles, while drawer.tsx expects headerStyle. Unless a mapper converts between them, headers will render with default styling.

Confirm the mapping layer or rename the prop in drawer.tsx.


916-1220: ⚠️ Potential issue

Same issue for footerStyles vs footerStyle

footerStyles written here is never consumed. Align prop names across settings, state model and component.

🧹 Nitpick comments (3)
shesha-reactjs/src/designer-components/drawer/drawer.tsx (1)

161-175: Inconsistent source of dimensions & spread order risk

  1. You already have dimensions in scope – prefer it to props.dimensions.
  2. style is spread before padding overrides; any padding* specified in style will override the derived values.
-        wrapper: {
-          width: style?.width || props.dimensions?.width,
-          height: style?.height || props.dimensions?.height,
+        wrapper: {
+          width: style?.width ?? dimensions?.width,
+          height: style?.height ?? dimensions?.height,
           ...rest,
         },

Re-ordering (spread rest first) protects explicit style overrides if that’s desired.

shesha-reactjs/src/designer-components/drawer/models.ts (1)

33-34: Remove legacy background prop or rename to backgroundStyles for consistency

Elsewhere (ShaDrawer, index.tsx) the refactor renamed the prop to backgroundStyles, but the model still exposes background. Keeping both will confuse consumers and future contributors.

-  background?: IBackgroundValue;
+  /** @deprecated – superseded by `allStyles.backgroundStyles` */
+  // background?: IBackgroundValue;

Either deprecate and later delete, or migrate existing data so only the new property remains.

shesha-reactjs/src/designer-components/drawer/index.tsx (1)

23-24: style is destructured but never used – triggers linter errors

const { allStyles, style, headerStyles, footerStyles, ...props } = model;

Unless you intend to support a direct style override, drop it from the pattern:

-const { allStyles, style, headerStyles, footerStyles, ...props } = model;
+const { allStyles, headerStyles, footerStyles, ...props } = model;

This keeps the bundle free of unused variables and passes no-unused-vars.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 50304d9 and 9c486d4.

📒 Files selected for processing (5)
  • shesha-reactjs/src/designer-components/drawer/drawer.tsx (4 hunks)
  • shesha-reactjs/src/designer-components/drawer/index.tsx (3 hunks)
  • shesha-reactjs/src/designer-components/drawer/models.ts (2 hunks)
  • shesha-reactjs/src/designer-components/drawer/settingsForm.ts (30 hunks)
  • shesha-reactjs/src/designer-components/drawer/utils.ts (1 hunks)
🔇 Additional comments (3)
shesha-reactjs/src/designer-components/drawer/utils.ts (1)

17-24: Shadow block lacks a type definition

You’ve added a shadow literal but no TS interface / type for it. Down-stream consumers will receive any, defeating type-safety.

Consider:

export interface IShadowStyle {
  offsetX: number;
  offsetY: number;
  color: string;
  blurRadius: number;
  spreadRadius: number;
}

and change the function return type accordingly.

shesha-reactjs/src/designer-components/drawer/drawer.tsx (1)

154-156: Ant-Design Drawer has no height prop

height is accepted only when placement is top | bottom. Passing it un-conditionally may log warnings. Add a conditional:

height={['top', 'bottom'].includes(placement as string) ? dimensions?.height : undefined}
shesha-reactjs/src/designer-components/drawer/settingsForm.ts (1)

16-32: Replacing nanoid() with hard-coded IDs risks collisions

Hard-coding UUID-like strings removes determinism benefits without eliminating collision risk.
If the goal is diff stability, consider:

  • keep nanoid(), but memoise per-session, or
  • enforce uniqueness through a central registry.

Comment on lines +17 to +24
style: '',
shadow: {
offsetX: 0,
offsetY: 0,
color: '#000',
blurRadius: 0,
spreadRadius: 0
}
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

style should default to an object, not an empty string

style is later treated as a CSSProperties object (e.g. it is spread into content in drawer.tsx). Initialising it as '' breaks that contract and may trigger runtime errors when a string is spread.

-        style: '',
+        style: {},
📝 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
style: '',
shadow: {
offsetX: 0,
offsetY: 0,
color: '#000',
blurRadius: 0,
spreadRadius: 0
}
style: {},
shadow: {
offsetX: 0,
offsetY: 0,
color: '#000',
blurRadius: 0,
spreadRadius: 0
}

Comment on lines +29 to 35
backgroundStyles?: CSSProperties;
dimensions?: {
width?: string | number;
height?: string | number;
};
stylingBoxAsCSS?: CSSProperties;
}
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

Old & new props co-exist ⇒ API ambiguity

width (legacy) and dimensions.width (new) now sit side-by-side.
Keeping both will confuse users and complicate maintenance. Deprecate one path explicitly (JSDoc or runtime warning) and remove it in the next major.

Comment on lines +68 to 69
const { paddingTop, paddingRight, paddingBottom, paddingLeft, ...rest } = stylingBoxAsCSS;

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

Possible destructuring crash when stylingBoxAsCSS is undefined

If the prop is omitted, destructuring throws. Guard with a default:

-  const { paddingTop, paddingRight, paddingBottom, paddingLeft, ...rest } = stylingBoxAsCSS;
+  const {
+    paddingTop,
+    paddingRight,
+    paddingBottom,
+    paddingLeft,
+    ...rest
+  } = stylingBoxAsCSS ?? {};
📝 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
const { paddingTop, paddingRight, paddingBottom, paddingLeft, ...rest } = stylingBoxAsCSS;
const {
paddingTop,
paddingRight,
paddingBottom,
paddingLeft,
...rest
} = stylingBoxAsCSS ?? {};

Comment on lines +31 to +34
headerStyles?: IDrawerProps;
footerStyles?: any;
background?: IBackgroundValue;

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

⚠️ Potential issue

Avoid self-referential type explosion & restore type-safety

headerStyles recursively points to the entire IDrawerProps interface and footerStyles is typed as any.
This opens two problems:

  1. Infinite depth – any JSON–serialisation / deep-clone util walking the object tree could hit an endless loop or stack overflow because every headerStyles again contains its own headerStyles, and so on.
  2. Loss of compile-time guarantees for footerStyles.

Introduce a dedicated, flat style interface (e.g. IDrawerSectionStyles) that only exposes the properties really needed by the header/footer. Then reference it in both places.

-  headerStyles?: IDrawerProps;
-  footerStyles?: any;
+  headerStyles?: IDrawerSectionStyles;
+  footerStyles?: IDrawerSectionStyles;

Don’t forget to export the new interface and update usages in index.tsx, the migrator and the settings form.

📝 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
headerStyles?: IDrawerProps;
footerStyles?: any;
background?: IBackgroundValue;
headerStyles?: IDrawerSectionStyles;
footerStyles?: IDrawerSectionStyles;
background?: IBackgroundValue;

Comment on lines 41 to 46
const additionalStyles: CSSProperties = removeUndefinedProps({
...shadowStyles,
...stylingBoxAsCSS,
...borderStyles,
stylingBoxAsCSS,
...jsStyle,
});
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

stylingBoxAsCSS is passed twice and pollutes inline CSS

stylingBoxAsCSS is already forwarded as an explicit prop (line 62) yet it is also embedded inside the style object – thereby producing an invalid CSS property and risking React warnings.

-const additionalStyles: CSSProperties = removeUndefinedProps({
-  ...shadowStyles,
-  ...borderStyles,
-  stylingBoxAsCSS,
-  ...jsStyle,
-});
+const additionalStyles: CSSProperties = removeUndefinedProps({
+  ...shadowStyles,
+  ...borderStyles,
+  ...jsStyle,
+});

A single source of truth avoids duplication and keeps the generated style object valid.

📝 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
const additionalStyles: CSSProperties = removeUndefinedProps({
...shadowStyles,
...stylingBoxAsCSS,
...borderStyles,
stylingBoxAsCSS,
...jsStyle,
});
const additionalStyles: CSSProperties = removeUndefinedProps({
...shadowStyles,
...borderStyles,
...jsStyle,
});

Comment on lines 97 to 114
.add<IDrawerProps>(4, (prev) => ({
...migratePrevStyles(prev, defaultStyles()),
desktop: { ...migratePrevStyles(prev, defaultStyles()).desktop, ...initialStyle },
tablet: { ...migratePrevStyles(prev, defaultStyles()).tablet, ...initialStyle },
mobile: { ...migratePrevStyles(prev, defaultStyles()).mobile, ...initialStyle },
desktop: {
...migratePrevStyles(prev, defaultStyles()).desktop,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
tablet: {
...migratePrevStyles(prev, defaultStyles()).tablet,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
mobile: {
...migratePrevStyles(prev, defaultStyles()).mobile,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
})),
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

Migrate only once to reduce computation & dodge subtle divergence

migratePrevStyles(prev, defaultStyles()) is executed four times, producing four independent objects that can diverge if defaultStyles() ever becomes non-deterministic (timestamp, random IDs, etc.). It is also wasteful.

-      .add<IDrawerProps>(4, (prev) => ({
-        ...migratePrevStyles(prev, defaultStyles()),
-        desktop: {
-          ...migratePrevStyles(prev, defaultStyles()).desktop,
+      .add<IDrawerProps>(4, (prev) => {
+        const migrated = migratePrevStyles(prev, defaultStyles());
+        return {
+          ...migrated,
+          desktop: {
+            ...migrated.desktop,
             headerStyles: defaultStyles(),
             footerStyles: defaultStyles(),
           },
           tablet: {
-          ...migratePrevStyles(prev, defaultStyles()).tablet,
+            ...migrated.tablet,
             headerStyles: defaultStyles(),
             footerStyles: defaultStyles(),
           },
           mobile: {
-          ...migratePrevStyles(prev, defaultStyles()).mobile,
+            ...migrated.mobile,
             headerStyles: defaultStyles(),
             footerStyles: defaultStyles(),
           },
-        },
-      })),
+        };
+      }))

This single evaluation improves performance and guarantees consistency across breakpoints.

📝 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
.add<IDrawerProps>(4, (prev) => ({
...migratePrevStyles(prev, defaultStyles()),
desktop: { ...migratePrevStyles(prev, defaultStyles()).desktop, ...initialStyle },
tablet: { ...migratePrevStyles(prev, defaultStyles()).tablet, ...initialStyle },
mobile: { ...migratePrevStyles(prev, defaultStyles()).mobile, ...initialStyle },
desktop: {
...migratePrevStyles(prev, defaultStyles()).desktop,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
tablet: {
...migratePrevStyles(prev, defaultStyles()).tablet,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
mobile: {
...migratePrevStyles(prev, defaultStyles()).mobile,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
})),
.add<IDrawerProps>(4, (prev) => {
const migrated = migratePrevStyles(prev, defaultStyles());
return {
...migrated,
desktop: {
...migrated.desktop,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
tablet: {
...migrated.tablet,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
mobile: {
...migrated.mobile,
headerStyles: defaultStyles(),
footerStyles: defaultStyles(),
},
};
}))

@Tshepo1103-lab Tshepo1103-lab changed the base branch from main-temp-pr to main April 29, 2025 08:28
@James-Baloyi James-Baloyi merged commit dc7ec85 into shesha-io:main Apr 29, 2025
2 checks passed
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