Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

refactor: migrate CopyableValue from MUI to Radix UI#20261

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
jaaydenh merged 7 commits intomainfromjaaydenh/refactor-copyable-value
Nov 10, 2025

Conversation

@jaaydenh
Copy link
Contributor

@jaaydenhjaaydenh commentedOct 12, 2025
edited
Loading

Summary

Migrates theCopyableValue component from Material-UI Tooltip to Radix UI Tooltip.

Changes

CopyableValue Component

  • Removed unused prop:PopperProps (never used in any call site)
  • Renamed prop:placementside (Radix naming convention)
  • Updated pattern: Now uses TooltipProvider/Tooltip/TooltipTrigger/TooltipContent composition

Minimal API surface change:

  • placement prop renamed toside (only affects 1 call site - already updated)
  • PopperProps removed (was never used)

Replace MUI Tooltip with Radix Tooltip components and migrate Emotion CSSto Tailwind utility classes. This is part of the ongoing effort tostandardize on Radix UI/shadcn components and Tailwind CSS.Changes:- Replace @mui/material/Tooltip with components/Tooltip/Tooltip (Radix)- Remove unused PopperProps (not used anywhere in codebase)- Rename placement prop to side to match Radix API- Replace Emotion css={{ cursor: "pointer" }} with Tailwind cursor-pointer class- Update single call site in IconsPage.tsx (placement → side)- Wrap in TooltipProvider as required by RadixTechnical details:- Radix uses Provider/Tooltip/Trigger/Content pattern (more verbose but flexible)- Maintained backward compatibility for all other call sites (6 files)- No functional changes to component behavior🤖 Generated with [Claude Code](https://claude.com/claude-code)Co-Authored-By: Claude <noreply@anthropic.com>
Comment on lines 40 to 41
if(showCopiedSuccess){
setShowCopiedText(true);
Copy link
Member

Choose a reason for hiding this comment

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

why have bothshowCopiedSuccess andshowCopiedText? this just feels like duplicated state with messy synchronization code

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I'm struggling to wrap my head around what the code is trying to solve that isn't handled by usingshowCopiedSuccess directly.

The hook already has timeouts built in (with cleanup). Is the goal to expose a different timeout value to the rest of the component? Because if so, it feels like the better change is to updateuseClipboard so that the timeout is parameterized

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

My original goal was to make it so that the tooltip is removed after showCopiedSuccess returns to false as it felt like a better experience when I originally looked at this. I think after thinking over this again. The existing functionality makes sense and I will remove all of this extra logic.

Copy link
Contributor

@buenos-nachosbuenos-nachos left a comment

Choose a reason for hiding this comment

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

The current code breaks a bunch of React rules, and I don't see any benefits to it. I see a lot of these changes causing bugs down the line

Comment on lines 40 to 41
if(showCopiedSuccess){
setShowCopiedText(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, I'm struggling to wrap my head around what the code is trying to solve that isn't handled by usingshowCopiedSuccess directly.

The hook already has timeouts built in (with cleanup). Is the goal to expose a different timeout value to the rest of the component? Because if so, it feels like the better change is to updateuseClipboard so that the timeout is parameterized

@jaaydenh
Copy link
ContributorAuthor

@Parkreiner@aslilac Removed the code where there was concerns and fixed issues with keyboard handling as well. The component should have now have parity with the MUI implementation.

Copy link
Contributor

@buenos-nachosbuenos-nachos left a comment

Choose a reason for hiding this comment

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

We're making progress, but I don't think we're there just yet

Comment on lines 46 to 47
{...attrs}
{...clickableProps}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is gong to cause prop shadowing for all the props thatclickableProps currently has (as in, if a consumer passes in any oftabIndex,role,onClick,onKeyDown oronKeyUp, they'll get dropped in favor of theclickableProps versions)

I feel like we want to be more finer-grained with how we wire everything together (this just illustrates the main idea, and doesn't account for all the other code comments I made):

exportconstCopyableValue:FC<CopyableValueProps>=({value,side="bottom",children,className,role,tabIndex,onClick,onKeyDown,onKeyUp,...attrs})=>{const{ showCopiedSuccess, copyToClipboard}=useClipboard();const[tooltipOpen,setTooltipOpen]=useState(false);const[isFocused,setIsFocused]=useState(false);constclickableProps=useClickable<HTMLSpanElement>(()=>{copyToClipboard(value);setTooltipOpen(true);});return(<TooltipProviderdelayDuration={100}><Tooltipopen={tooltipOpen}onOpenChange={(next)=>{if(!next&&isFocused)return;setTooltipOpen(next);}}><TooltipTriggerasChild><spanref={clickableProps.ref}{...attrs}className={cn("cursor-pointer",className)}role={role??clickableProps.role}tabIndex={tabIndex??clickableProps.tabIndex}onClick={(event)=>{clickableProps.onClick(event);onClick?.(event);}}onKeyDown={(event)=>{clickableProps.onKeyDown(event);onKeyDown?.(event);}}onKeyUp={(event)=>{clickableProps.onKeyUp(event);onKeyUp?.(event);}}onMouseEnter={()=>{setIsFocused(true);setTooltipOpen(true);}}onMouseLeave={()=>{setTooltipOpen(false);}}onFocus={()=>{setIsFocused(true);}}onBlur={()=>{setTooltipOpen(false);}}>{children}</span></TooltipTrigger><TooltipContentside={side}>{showCopiedSuccess ?"Copied!" :"Click to copy"}</TooltipContent></Tooltip></TooltipProvider>);};

jaaydenh reacted with thumbs up emoji
})=>{
const{ showCopiedSuccess, copyToClipboard}=useClipboard();
const[tooltipOpen,setTooltipOpen]=useState(false);
const[isFocused,setIsFocused]=useState(false);
Copy link
Contributor

@buenos-nachosbuenos-nachosOct 22, 2025
edited
Loading

Choose a reason for hiding this comment

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

What is our goal with the focus state? Because right now, it looks like we're flipping the state within React, but we're not actually changing the focus behavior on the actual HTML element

The main area where I'm worried about drift between React and the underlying HTML is theonMouseEnter prop settingisFocused to true

Comment on lines +57 to +59
onFocus={()=>{
setIsFocused(true);
}}
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we also want to open the tooltip here?

Comment on lines 39 to 40
// Always keep the tooltip open when in focus to handle issues when onOpenChange is unexpectedly false
if(!next&&isFocused)return;
Copy link
Contributor

Choose a reason for hiding this comment

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

What situations were you running into that was causing this problem? I know that the libraries can get a little unruly and sometimes need these hacks, but I'm wondering if there's a chance we could remove the need for this

<CopyableValuekey={icon.url}value={icon.url}placement="bottom">
<StackalignItems="center"css={{margin:12}}>
<CopyableValuekey={icon.url}value={icon.url}>
<divclassName="flex flex-col gap-4 items-center max-w-full m-3">
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
<divclassName="flex flex-col gap-4 items-center max-w-fullm-3">
<divclassName="flex flex-col gap-4 items-center max-w-fullp-3">

can we dopadding instead if it looks the same?

jaaydenh reacted with thumbs up emoji
<TooltipProviderdelayDuration={100}>
<Tooltip
open={tooltipOpen}
onOpenChange={(next)=>{
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
onOpenChange={(next)=>{
onOpenChange={(shouldBeOpen)=>{

the namenext just makes this really hard to reason about for me. if I substitute it for something like this in my head it makes it clearer.

jaaydenh reacted with thumbs up emoji
@github-actionsgithub-actionsbot added the staleThis issue is like stale bread. labelNov 6, 2025
@jaaydenhjaaydenh reopened thisNov 10, 2025
@jaaydenhjaaydenh merged commit47c703a intomainNov 10, 2025
31 checks passed
@jaaydenhjaaydenh deleted the jaaydenh/refactor-copyable-value branchNovember 10, 2025 22:15
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsNov 10, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.

Reviewers

@aslilacaslilacaslilac approved these changes

+1 more reviewer

@buenos-nachosbuenos-nachosbuenos-nachos left review comments

Reviewers whose approvals may not affect merge requirements

Assignees

@jaaydenhjaaydenh

Labels

staleThis issue is like stale bread.

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

4 participants

@jaaydenh@aslilac@buenos-nachos

[8]ページ先頭

©2009-2025 Movatter.jp