refactor(ui): migrate entity sidebar from antd/MUI to Alchemy components CAT-1544#16635
Conversation
Replace all Ant Design (Collapse, Typography) and Material-UI (AddRoundedIcon, DraftsOutlinedIcon, EditOutlinedIcon) components in the entity profile sidebar with Alchemy components (Button, Icon, Pill, Tooltip) and Phosphor icons. Key changes: - Replace antd Collapse with custom useState-driven collapsible sections - Replace MUI icons with Phosphor icons via Alchemy Icon component - Replace antd Typography.Text with styled.span - Migrate all hardcoded colors, REDESIGN_COLORS, ANTD_GRAY, and colors.gray[X] imports to semantic theme tokens (theme.colors.*) - Replace styled(Link) wrapping Button anti-pattern with Button + useHistory - Use Alchemy Pill (filled variant) for status indicators - Use Alchemy Button (text/link variants) for show-more and link actions - Standardize sidebar section padding (20px horizontal, 8px vertical) - Make section dividers edge-to-edge - Move collapse caret to right side of section headers - Update Cypress tests to use data-testid selectors instead of removed antd class selectors (.ant-collapse-header-text, AddRoundedIcon) 50 files changed, net reduction of ~150 lines. All unit tests, ESLint, Prettier, and type-check pass. Made-with: Cursor
|
Linear: CAT-1557 |
|
✅ Meticulous spotted visual differences in 168 of 1736 screens tested, but all differences have already been approved: view differences detected. Meticulous evaluated ~9 hours of user flows against your PR. Last updated for commit ac57391. This comment will update as new commits are pushed. |
Bundle ReportChanges will increase total bundle size by 3.07kB (0.01%) ⬆️. This is within the configured threshold ✅ Detailed changes
Affected Assets, Files, and Routes:view changes for bundle: datahub-react-web-esmAssets Changed:
Files in
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…ebar-alchemy-migration Made-with: Cursor # Conflicts: # datahub-web-react/src/app/entityV2/shared/containers/profile/sidebar/EntitySidebarTabs.tsx # datahub-web-react/src/app/entityV2/shared/containers/profile/sidebar/SidebarSection.tsx
Align with tree-shaking changes from #16338 — Icon component now accepts React.ComponentType instead of string names with source prop. Made-with: Cursor
| if (user.type) return user.type; | ||
| return user.__typename === 'CorpGroup' ? EntityType.CorpGroup : EntityType.CorpUser; | ||
| } | ||
|
|
There was a problem hiding this comment.
I appreciate that checking the private __typename as backup is defensive coding but I believe it's unnecessary as .type should be guaranteed to exist.
So just this should work:
function resolveActorEntityType(actor: CorpUser | CorpGroup): EntityType {
return actor.type;
}| const relativeTime = moment(time); | ||
| if (relativeTime.isAfter(moment().subtract(1, 'week'))) { | ||
| return `${REDESIGN_COLORS.GREEN_NORMAL}`; | ||
| return 'green'; |
There was a problem hiding this comment.
Shouldn't these be tokens too?
There was a problem hiding this comment.
These are Alchemy Pill component color variant names ('green', 'yellow', 'red'), not CSS color values — they get passed to <Pill color={pillColor} /> in SyncedOrShared.tsx. So no token needed here.
| overflow: hidden; | ||
| `} | ||
| `; | ||
|
|
There was a problem hiding this comment.
line-clamp is now supported pretty much anywhere so I would add it (you can still keep -webkit prefix if you want since it's harmless).
const ClampedText = styled.div<{ $expanded: boolean }>`
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
line-clamp: ${({ $expanded }) => ($expanded ? 'unset' : VISIBLE_LINES)};
-webkit-line-clamp: ${({ $expanded }) => ($expanded ? 'unset' : VISIBLE_LINES)};
`;| setIsClamped(el.scrollHeight > LINE_HEIGHT * VISIBLE_LINES + 2); | ||
| } | ||
| }, [about, isAboutEditable]); | ||
|
|
There was a problem hiding this comment.
This magic pixel calculation seems a bit fragile and might break if font size or line height changes. How about something like
useEffect(() => {
const el = textRef.current;
if (el) {
setIsClamped(el.scrollHeight > el.clientHeight);
}
}, [about, isAboutEditable]);|
should we have the collapse carets on the right side like this? it used to be on the left and i think that's what we usually do and when it's not next to the section name we've heard confusion from folks before. and then you should be able to click on the name of the section in order to expand/collapse the section as well |
Resolve conflicts in SidebarStyledComponents.tsx and NotesSection.tsx from avatar-pills PR merge. Keep Phosphor icons over MUI, adopt master's semantic token updates. Replace AvatarPillWithLinkAndHover with ExpandedOwner in OwnershipTypeSection for proper remove-owner support. Made-with: Cursor
- Simplify resolveEntityType to just return user.type (no __typename fallback) - Add unprefixed line-clamp alongside -webkit-line-clamp in AboutSidebarSection - Replace magic pixel calculation with scrollHeight > clientHeight for clamped text detection Made-with: Cursor
…gration - Add data-testid to GroupProfileInfoCard and AboutSidebarSection for edit buttons that lost their MUI-generated testids after Phosphor migration - Update v2_managing_groups.js selectors to use new explicit data-testids - Fix v2_nested_domains.js race condition: wait for sidebar to render after cy.reload() before DatasetHelper.assignTag interacts with it - Remove dead setIsThemeV2Enabled calls in createGroup command and dataset_ownership.js (command was removed in v1 UI cleanup) Made-with: Cursor
Resolve conflicts keeping alchemy migration changes: - SidebarStyledComponents: keep SideBarSubSection, SubscriptionContainer, and styled.div OwnershipContainer - StatusSection: keep custom DeprecatedHeader over antd StyledCollapse - styledComponents: keep InstanceIcon and StyledLabel Made-with: Cursor
After the sidebar migration from styled.div to alchemy Button, the
add-tags-button renders as <button disabled> while entity privileges
load. React ignores onClick on disabled buttons even with Cypress's
force:true, so the tag modal never opens. Add .should("not.be.disabled")
to wait for privileges to load before clicking.
Made-with: Cursor
- SidebarEntityHeader: remove redundant margin-left, use 8px gap, only render PlatformHeaderIcons when platform exists, use 16px LR padding with logo and 20px without - OwnershipTypeSection: replace margin-right with gap on parent, remove margin-top, bump type label to 12px, 4px gap between title and pills, 4px gap between pills - SidebarOwnerSection: add 8px gap between ownership type groups Made-with: Cursor
…line styles - Remove unused StyledLabel, InstanceIcon, ContentText from styledComponents - Consolidate ContentText into LabelText in SyncedOrShared - Remove unnecessary $collapsible prop from StatusSection - Add flex-wrap to OwnershipContainer for wrapping owned entities - Use AvatarPillWithLinkAndHover for Groups sidebar section - Remove empty AddLinksWrapper from LinksSection - Replace inline textDecoration styles with StyledAnchor in LinkButton and SourceRefSection Made-with: Cursor
Before:




After:






Summary
theme.colors.*), eliminating hardcoded hex values,REDESIGN_COLORS,ANTD_GRAY, and directcolors.gray[X]imports across 47 frontend files.ant-collapse-header-text,AddRoundedIcon) by updating to stabledata-testidselectorsWhat changed
Collapse/Collapse.PaneluseState-driven collapsibleAddRoundedIcon,DraftsOutlinedIcon,EditOutlinedIconIconcomponentTypography.Textstyled.spanwith semantic tokensREDESIGN_COLORS,ANTD_GRAY,colors.gray[X], hardcoded hextheme.colors.*semantic tokensPill(filled variant)Button(text/link variants)styled(Link)wrappingButtonButton+useHistoryExpandedOwnercomponentAvatarPillWithLinkAndHover+AvatarStackWithHoverDeferred to follow-up PRs
SidebarApplicationSectionuses antdModal.confirm(AlchemyModalitself wraps antd internally)EntitySidebarTabsuses antdTabs(no Alchemy equivalent yet)DomainLink,ApplicationLink,DataProductLink,EntityPreviewTag(antdTag)Test plan
yarn prettier --write src— all files formattedyarn lint(ESLint + format-check + type-check) — zero errorsSidebarLogicSection.test.tsx— 5/5 passedEntityProfile.test.tsx— 4 passed, 1 skipped (pre-existing)OwnerUtils.test.ts— 21/21 passeddata-testidandidselectors still presentv2_siblings.js,v2_glossary.js,dataset_helper.js)Made with Cursor