Skip to content

Chore(UI): Core components update#26704

Open
aniketkatkar97 wants to merge 4 commits intomainfrom
core-components-update
Open

Chore(UI): Core components update#26704
aniketkatkar97 wants to merge 4 commits intomainfrom
core-components-update

Conversation

@aniketkatkar97
Copy link
Member

This pull request primarily focuses on code style consistency and maintainability improvements across several UI component files. The most significant change is the consistent use of single quotes for string literals, replacing double quotes throughout the codebase. Additionally, a new flexible Box layout component is introduced, and some minor refactors and style improvements are made to existing components.

Code Style Consistency:

  • Standardized all string literals to use single quotes instead of double quotes in files such as tabs.tsx and button-group.tsx, improving code consistency and reducing potential linting issues. [1] [2] [3] [4] [5] [6] [7] [8]

Component Enhancements:

  • Added a new Box component (box.tsx) that provides a flexible, configurable flexbox container with support for direction, alignment, justification, wrapping, and gap utilities, streamlining layout creation.

Refactor and Minor Improvements:

  • Updated className handling and improved prop destructuring for better readability and maintainability in the TabList, TabPanel, Tab, and Tabs components. [1] [2] [3] [4]
  • Improved the button-group.tsx component by updating spacing calculations and maintaining consistency in style definitions.

Utility Improvements:

  • Ensured all utility imports (such as cx and sortCx) use the new single quote convention and are consistently ordered.

These changes collectively improve the codebase's readability, maintainability, and consistency for future development.

Added more props to card component
Fixed spacing in button group component
@aniketkatkar97 aniketkatkar97 self-assigned this Mar 23, 2026
Copilot AI review requested due to automatic review settings March 23, 2026 17:07
@github-actions github-actions bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Mar 23, 2026
@aniketkatkar97 aniketkatkar97 changed the title Chor(UI): Core components update Chore(UI): Core components update Mar 23, 2026
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 updates openmetadata-ui-core-components to improve component ergonomics and consistency by introducing a new Box layout primitive, expanding the Card API with sub-components, refining existing Tabs/Divider/ButtonGroup implementations, and enhancing Storybook stories/argTypes to better document these components.

Changes:

  • Added a new Box flex layout component, supporting direction/alignment/justification/wrap and gap utilities, plus a supporting Tailwind class mapping constant.
  • Refactored Card to a composed sub-component API (Card.Header, Card.Content, Card.Footer) with variant/color/size/interactive styling.
  • Updated Tabs, Divider, and ButtonGroup implementations and expanded Storybook stories/argTypes for better documentation.

Reviewed changes

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

Show a summary per file
File Description
openmetadata-ui-core-components/src/main/resources/ui/src/stories/Tabs.stories.tsx Reworked Tabs stories to use the core-components Tabs API and added more usage examples.
openmetadata-ui-core-components/src/main/resources/ui/src/stories/Divider.stories.tsx Added argTypes to document Divider prop unions in Storybook.
openmetadata-ui-core-components/src/main/resources/ui/src/stories/Card.stories.tsx Added argTypes and expanded stories to cover variants/colors/sizes and sub-components.
openmetadata-ui-core-components/src/main/resources/ui/src/stories/ButtonGroup.stories.tsx Added argTypes and a trailing-icon story example.
openmetadata-ui-core-components/src/main/resources/ui/src/stories/Box.stories.tsx Added Storybook coverage for the new Box component behaviors.
openmetadata-ui-core-components/src/main/resources/ui/src/constants/tailwindClasses.constants.ts Introduced static Tailwind class maps for gap utilities.
openmetadata-ui-core-components/src/main/resources/ui/src/components/index.ts Exported the new Box component from the package entrypoint.
openmetadata-ui-core-components/src/main/resources/ui/src/components/base/divider/divider.tsx Updated Divider rendering to use <hr> for unlabeled dividers.
openmetadata-ui-core-components/src/main/resources/ui/src/components/base/card/card.tsx Implemented composed Card API with sizing context and variant/color styling.
openmetadata-ui-core-components/src/main/resources/ui/src/components/base/button-group/button-group.tsx Refactored ButtonGroup styles and imports; kept react-aria ToggleButtonGroup usage.
openmetadata-ui-core-components/src/main/resources/ui/src/components/base/box/box.tsx Added the new Box component implementation.
openmetadata-ui-core-components/src/main/resources/ui/src/components/application/tabs/tabs.tsx Reformatted/refined Tabs component and related styling helpers.
Comments suppressed due to low confidence (1)

openmetadata-ui-core-components/src/main/resources/ui/src/components/base/divider/divider.tsx:23

  • DividerProps extends HTMLAttributes<HTMLDivElement>, but the component returns an <hr> for the common (unlabeled) horizontal and vertical cases. This makes the prop typing inaccurate (and allows passing children, which React warns about on void elements like <hr>). Consider splitting props by render path (e.g., <hr> props vs labeled <div> props) or using a safer common type that omits children for the <hr> branches.
export type DividerOrientation = "horizontal" | "vertical";
export type DividerLabelAlignment = "start" | "center" | "end";

export interface DividerProps extends HTMLAttributes<HTMLDivElement> {
  orientation?: DividerOrientation;
  label?: ReactNode;
  labelAlign?: DividerLabelAlignment;
}

Comment on lines +81 to +83
const gapValue = gap ? gapClassMapping[gap] : undefined;
const rowGapValue = rowGap ? rowGapClassMapping[rowGap] : undefined;
const colGapValue = colGap ? colGapClassMapping[colGap] : undefined;
Copy link

Choose a reason for hiding this comment

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

⚠️ Edge Case: Box: gap=0 is silently ignored due to falsy check

In box.tsx, the gap values are guarded with a truthiness check (gap ? gapClassMapping[gap] : undefined). Since 0 is falsy in JavaScript, passing gap={0} (or rowGap={0} / colGap={0}) will not apply the tw:gap-0 class, even though gapClassMapping[0] is defined as 'tw:gap-0'.

A consumer might explicitly pass gap={0} to reset gap (e.g., overriding a parent style), and it would silently do nothing. The same issue applies to rowGap and colGap.

Suggested fix:

const gapValue = gap != null ? gapClassMapping[gap] : undefined;
const rowGapValue = rowGap != null ? rowGapClassMapping[rowGap] : undefined;
const colGapValue = colGap != null ? colGapClassMapping[colGap] : undefined;

Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion

ref
) => {
return (
<CardContext.Provider value={{ size }}>
Copy link

Choose a reason for hiding this comment

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

💡 Performance: Card context value not memoized unlike TabList and ButtonGroup

In CardBase, the context value { size } is created inline on every render (<CardContext.Provider value={{ size }}>), which creates a new object reference each time and may cause unnecessary re-renders of CardHeader, CardContent, and CardFooter consumers.

This PR already added useMemo for the same pattern in TabList (line 184-187) and ButtonGroup (line 120), but the Card component was missed.

Suggested fix:

// Add useMemo import, then in CardBase:
const contextValue = useMemo(() => ({ size }), [size]);
return (
  <CardContext.Provider value={contextValue}>
    ...
  </CardContext.Provider>
);

Was this helpful? React with 👍 / 👎 | Reply gitar fix to apply this suggestion

@gitar-bot
Copy link

gitar-bot bot commented Mar 23, 2026

Code Review ⚠️ Changes requested 1 resolved / 3 findings

Core components update adds Box component and enhances Card with additional props, but Box silently ignores gap=0 due to falsy check validation, and CardBase context value lacks memoization for consistency with TabList and ButtonGroup. Address these issues before merging.

⚠️ Edge Case: Box: gap=0 is silently ignored due to falsy check

📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/base/box/box.tsx:81-83

In box.tsx, the gap values are guarded with a truthiness check (gap ? gapClassMapping[gap] : undefined). Since 0 is falsy in JavaScript, passing gap={0} (or rowGap={0} / colGap={0}) will not apply the tw:gap-0 class, even though gapClassMapping[0] is defined as 'tw:gap-0'.

A consumer might explicitly pass gap={0} to reset gap (e.g., overriding a parent style), and it would silently do nothing. The same issue applies to rowGap and colGap.

Suggested fix
const gapValue = gap != null ? gapClassMapping[gap] : undefined;
const rowGapValue = rowGap != null ? rowGapClassMapping[rowGap] : undefined;
const colGapValue = colGap != null ? colGapClassMapping[colGap] : undefined;
💡 Performance: Card context value not memoized unlike TabList and ButtonGroup

📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/base/card/card.tsx:181

In CardBase, the context value { size } is created inline on every render (<CardContext.Provider value={{ size }}>), which creates a new object reference each time and may cause unnecessary re-renders of CardHeader, CardContent, and CardFooter consumers.

This PR already added useMemo for the same pattern in TabList (line 184-187) and ButtonGroup (line 120), but the Card component was missed.

Suggested fix
// Add useMemo import, then in CardBase:
const contextValue = useMemo(() => ({ size }), [size]);
return (
  <CardContext.Provider value={contextValue}>
    ...
  </CardContext.Provider>
);
✅ 1 resolved
Bug: Divider: HTMLDivElement type mismatch after changing to

📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/base/divider/divider.tsx:19 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/base/divider/divider.tsx:34 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/base/divider/divider.tsx:47
The DividerProps interface extends HTMLAttributes<HTMLDivElement>, but the element was changed from <div> to <hr> in two of three code paths (vertical and no-label). Since <hr> is an HTMLHRElement, spreading HTMLDivElement attributes onto it is a type mismatch. While this works at runtime (both are basic HTML elements with similar attributes), it breaks type correctness — e.g., ref typed as Ref<HTMLDivElement> would be wrong. The third code path (with label) still renders a <div>, creating an inconsistency.

Additionally, <hr> is self-closing and has implicit role="separator", so aria-orientation usage here is good — but consider whether the mixed element approach is intentional.

🤖 Prompt for agents
Code Review: Core components update adds Box component and enhances Card with additional props, but Box silently ignores gap=0 due to falsy check validation, and CardBase context value lacks memoization for consistency with TabList and ButtonGroup. Address these issues before merging.

1. ⚠️ Edge Case: Box: gap=0 is silently ignored due to falsy check
   Files: openmetadata-ui-core-components/src/main/resources/ui/src/components/base/box/box.tsx:81-83

   In `box.tsx`, the gap values are guarded with a truthiness check (`gap ? gapClassMapping[gap] : undefined`). Since `0` is falsy in JavaScript, passing `gap={0}` (or `rowGap={0}` / `colGap={0}`) will not apply the `tw:gap-0` class, even though `gapClassMapping[0]` is defined as `'tw:gap-0'`.
   
   A consumer might explicitly pass `gap={0}` to reset gap (e.g., overriding a parent style), and it would silently do nothing. The same issue applies to `rowGap` and `colGap`.

   Suggested fix:
   const gapValue = gap != null ? gapClassMapping[gap] : undefined;
   const rowGapValue = rowGap != null ? rowGapClassMapping[rowGap] : undefined;
   const colGapValue = colGap != null ? colGapClassMapping[colGap] : undefined;

2. 💡 Performance: Card context value not memoized unlike TabList and ButtonGroup
   Files: openmetadata-ui-core-components/src/main/resources/ui/src/components/base/card/card.tsx:181

   In `CardBase`, the context value `{ size }` is created inline on every render (`<CardContext.Provider value={{ size }}>`), which creates a new object reference each time and may cause unnecessary re-renders of `CardHeader`, `CardContent`, and `CardFooter` consumers.
   
   This PR already added `useMemo` for the same pattern in `TabList` (line 184-187) and `ButtonGroup` (line 120), but the Card component was missed.

   Suggested fix:
   // Add useMemo import, then in CardBase:
   const contextValue = useMemo(() => ({ size }), [size]);
   return (
     <CardContext.Provider value={contextValue}>
       ...
     </CardContext.Provider>
   );

Options

Auto-apply is off → Gitar will not commit updates to this branch.
Display: compact → Showing less information.

Comment with these commands to change:

Auto-apply Compact
gitar auto-apply:on         
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

@github-actions
Copy link
Contributor

🟡 Playwright Results — all passed (18 flaky)

✅ 3415 passed · ❌ 0 failed · 🟡 18 flaky · ⏭️ 183 skipped

Shard Passed Failed Flaky Skipped
✅ Shard 1 455 0 0 2
🟡 Shard 2 304 0 1 1
🟡 Shard 3 674 0 7 33
🟡 Shard 4 700 0 6 41
✅ Shard 5 672 0 0 73
🟡 Shard 6 610 0 4 33
🟡 18 flaky test(s) (passed on retry)
  • Pages/DataContracts.spec.ts › Create Data Contract and validate for MlModel (shard 2, 1 retry)
  • Features/BulkImport.spec.ts › Database (shard 3, 1 retry)
  • Features/DataQuality/TestCaseImportExportE2eFlow.spec.ts › EditAll User: Complete export-import-validate flow (shard 3, 1 retry)
  • Features/DataQuality/TestCaseIncidentPermissions.spec.ts › User with TEST_CASE.EDIT_ALL can see edit icon on incidents (shard 3, 1 retry)
  • Features/DataQuality/TestCaseResultPermissions.spec.ts › User with TEST_CASE.EDIT_ALL can see edit action on test case (shard 3, 1 retry)
  • Features/DataQuality/TestDefinitionPermissions.spec.ts › should allow viewing test definitions but not create, edit, or delete (shard 3, 1 retry)
  • Features/Glossary/LargeGlossaryPerformance.spec.ts › should maintain scroll position when loading more terms (shard 3, 1 retry)
  • Features/Permissions/GlossaryPermissions.spec.ts › Team-based permissions work correctly (shard 3, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should not display soft deleted assets in search suggestions (shard 4, 1 retry)
  • Flow/NotificationAlerts.spec.ts › Task source alert (shard 4, 1 retry)
  • Pages/Customproperties-part2.spec.ts › entityReferenceList shows item count, scrollable list, no expand toggle (shard 4, 1 retry)
  • Pages/Domains.spec.ts › Rename domain with owners and experts preserves assignments (shard 4, 1 retry)
  • Pages/DomainUIInteractions.spec.ts › Add owner to data product via UI (shard 4, 1 retry)
  • Pages/Entity.spec.ts › Column detail panel data type display and nested column navigation (shard 4, 1 retry)
  • Pages/ODCSImportExport.spec.ts › Multi-object ODCS contract - object selector shows all schema objects (shard 6, 1 retry)
  • Pages/Tag.spec.ts › Verify Tag UI for Data Consumer (shard 6, 1 retry)
  • Pages/Users.spec.ts › Create and Delete user (shard 6, 1 retry)
  • Pages/Users.spec.ts › Permissions for table details page for Data Consumer (shard 6, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

return (
<div
{...props}
className={cx(
"tw:outline-focus-ring tw:focus-visible:outline-2 tw:focus-visible:outline-offset-2 tw:relative tw:overflow-hidden tw:rounded-xl tw:ring-1 tw:ring-inset tw:ring-secondary tw:bg-primary",
className,
'tw:flex tw:items-start tw:justify-between tw:gap-4 tw:border-b tw:border-secondary',
Copy link
Contributor

Choose a reason for hiding this comment

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

This change may cause issue where it is used.
Previously Card just had a border to it, now we have changed the default layout here.
Confirm the usages

Copy link
Contributor

Choose a reason for hiding this comment

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

Also why are restricting usage of flex in default

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

Labels

safe to test Add this label to run secure Github workflows on PRs UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants