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

fix: improve click UX and styling for Auth Token page#11863

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
Parkreiner merged 32 commits intomainfrommes/clipboard-fix
Feb 1, 2024

Conversation

Parkreiner
Copy link
Member

@ParkreinerParkreiner commentedJan 26, 2024
edited
Loading

No issue to link – ended up adding this to the workpile, since Blueberry decided that we'd be launching with token auth for Backstage's alpha release

Changes made

  • Revamps theuseClipboard hook to be based on a more "synchronization-based" API
    • No more timeouts
    • The hook now "listens" more directly to the clipboard and updates state whenever the clipboard changes
    • It also is set up to revalidate the clipboard if the user leaves the Coder tab and then comes back
  • Adds test file foruseClipboard
  • Revamps theCodeExample component to have a much larger clickable area (underlying HTML semantics have not been changed)
    • Also increases the security when thesecret prop is true (and also makes sure that the value defaults totrue)
  • Updates howuseQuery is integrated into the page to follow newer Coder conventions
  • Touches up styling for auth page (mainly spacing and text formatting)

Notes

  • I had to do some slightly hokey tests foruseClipboard because even thoughuserEvent.setup sets up a clipboard mock automatically (it normally doesn't exist in JSDOM), I couldn't get it to trigger events predictably. If anybody has suggestions for how to get rid of my home-spun mock, I have a bunch of tacos waiting for you

@ParkreinerParkreiner self-assigned thisJan 26, 2024
@ParkreinerParkreiner changed the titlechore: clean up AuthPagefix: improve URL syncs and styling for Auth pageJan 26, 2024
Comment on lines 29 to 36
const{
text,
ctaCopy,
wrapperStyles,
buttonStyles,
onClick:outsideOnClick,
tooltipTitle=Language.tooltipTitle,
}=props;
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Generally try to keep prop definitions inlined, but Prettier's auto-formatting made the code super ugly to look at

Comment on lines 48 to 51
onClick={(event)=>{
voidcopyToClipboard();
outsideOnClick?.(event);
}}
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

This is the only major change for the component. The rest of the diff is just from theforwardRef call increasing the indentation

@ParkreinerParkreiner requested review froma team,BrunoQuaresma andcode-asher and removed request fora team andcode-asherJanuary 27, 2024 03:11
@ParkreinerParkreiner marked this pull request as ready for reviewJanuary 27, 2024 03:21
@ParkreinerParkreiner changed the titlefix: improve URL syncs and styling for Auth pagefix: improve URL syncs and styling for Auth Token pageJan 27, 2024
Comment on lines 159 to 175
// Absolutely cartoonish logic, but it's how you do things with the exec API
constpreviousFocusTarget=document.activeElement;
constdummyInput=document.createElement("input");
dummyInput.style.visibility="hidden";
document.body.appendChild(dummyInput);
dummyInput.focus();

// Confusingly, you want to use the command opposite of what you actually want
// to do to interact with the execCommand method
constcommand=operation==="read" ?"paste" :"copy";
constisExecSupported=document.execCommand(command);
constvalue=dummyInput.value;
dummyInput.remove();

if(previousFocusTargetinstanceofHTMLElement){
previousFocusTarget.focus();
}
Copy link
MemberAuthor

@ParkreinerParkreinerJan 27, 2024
edited
Loading

Choose a reason for hiding this comment

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

All of these changes together might be a bit overkill, but I didn't want to leave things to chance. The biggest issue before was that when the dummy input received focus, there was nothing in place to put it back on the original element once the function was done

Comment on lines +27 to +34
Copy the session token below and
{/*
* This looks silly, but it's a case where you want to hide the space
* visually because it messes up the centering, but you want the space
* to still be available to screen readers
*/}
<spancss={{ ...visuallyHidden}}>{VISUALLY_HIDDEN_SPACE}</span>
<strongcss={{display:"block"}}>paste it in your terminal.</strong>
Copy link
MemberAuthor

@ParkreinerParkreinerJan 27, 2024
edited
Loading

Choose a reason for hiding this comment

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

Changed the previous markup because thenowrap styling had a risk of breaking the text rendering at smaller viewport sizes

@github-actionsGitHub Actions
Copy link


🚀 Deploying PR 11863 ...

github-actions[bot] reacted with eyes emoji

@bpmct
Copy link
Member

bpmct commentedJan 29, 2024
edited
Loading

On Safari, the button doesn't revert to the clipboard icon (the copy still works)

Screen.Recording.2024-01-28.at.6.35.03.PM.mov

I haven't seen a copy UX like this (that is clipboard-aware and maintains confirmation state), but I see the immediate feedback being quite common. Here is Iconfinder, for example:

https://medium.com/iconfinder/copy-to-clipboard-b4e37b6fe20b

I could be wrong and this is a more common paradigm, but as much as possible I'd love to avoid complexity on this page (or manually test with various browsers) as it's a critical CLI flow

variant="text"
onClick={(event)=>{
voidcopyToClipboard();
outsideOnClick?.(event);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need this?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

More just for flexibility. It might be because I've been in a Backstage mindset, where we need a lot more API flexibility, but my thinking was this would let someone attach anonClick handler without overriding the main copy functionality

Copy link
Collaborator

Choose a reason for hiding this comment

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

In the Coder app context + this component context, what would be a common use case for this?

Copy link
MemberAuthor

@ParkreinerParkreinerJan 30, 2024
edited
Loading

Choose a reason for hiding this comment

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

For this context, it is over-engineering, yeah. I'll remove it


typeResult<T=unknown>=voidextendsT ?VoidResult :ResultWithData<T>;

asyncfunctionreadFromClipboard():Promise<Result<string>>{
Copy link
Collaborator

Choose a reason for hiding this comment

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

I did not understand this part. Why do we need to read something from the clipboard? I would expect to just write things in it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe listing the flow using bullet points would make things easier to understand for me.

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

It's mainly for setting up a way to watch the clipboard, since there isn't an observer-based API for it, like there is for a lot of other browser APIs

The main idea is thatisCopied is always a derived value that comes from checking whether the text passed into the hook matches the text currently in the clipboard. And the only way to check the current clipboard is by reading from it – if we only write to it, then we can't make any assumptions about what's actually in the clipboard, because it can also change from sources outside React

So basically, there's three main "sync cues":

  1. The user copies our text to the clipboard
  2. The user changes their clipboard text while in the same page
  3. The user changes to a different tab, and then comes back

In all of the cases, we don't have a direct, event-based way to check the clipboard contents to verify that the content matches. You would think that writing to the clipboard would expose that information, but the event objects don't actually contain the new clipboard text. So in all three cases, the only choice is reading from it

Copy link
Collaborator

Choose a reason for hiding this comment

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

Why do we need to check if the content in the clipboard matches the one passed into the hook? Is there a use case in the app where this can happen?

Copy link
MemberAuthor

@ParkreinerParkreinerJan 30, 2024
edited
Loading

Choose a reason for hiding this comment

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

So, this is splitting semantic hairs, but I guess the question boils down to, "What do we wantisCopied to represent?

  • Do we want it to indicate that we've just finished handling a copy operation, and this value represents how long we want to tell the user that the text is copied?
  • Or do we want this property to act as a source of truth, whereisCopied answers the question, "Each time the component renders, is the text we provided into the hook copied into the clipboard?"
    • If we don't want to do that, maybe that's a sign we should rename the property, but because the clipboard is one of the most mutable values in web development, the only way to have 100% confidence to that question is by checking the clipboard

That mismatch between the property name and actual functionality is what led me to consider a more synchronization-based solution, but maybe this did end up putting me on a weird, wild goose chase


// Comments for this function mirror the ones for readFromClipboard
asyncfunctionwriteToClipboard(textToCopy:string):Promise<Result<void>>{
if(!document.hasFocus()){
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm... why is this necessary?

Thinking about the most common use case, like the user clicking the button and the value being copied, I don't see how this could happen if the document is not in focus 🤔

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I had a comment inreadToClipboard, but it's mainly to suppress errors when trying to do stuff in development mode

Copy link
Collaborator

Choose a reason for hiding this comment

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

Do you think is there a way to improve readability without adding a comment mentioning another comment? Thinking on a named variable or function likeisDevMode?

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

Yeah, now that you mention it, I can use an assertion function. I'll get that swapped in

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it's always good to share screenshots and demos when making UI changes or features. Some design improvements I see we can make:
Screenshot 2024-01-29 at 09 07 22

  • The space between the title, description text, and code example looks strange
  • I would make the "Go to workspaces" link a normal link. I think it's not that important to be considered a secondary action like a button.
  • The code example looks bigger than normal input sizes to me... I think it would be nice to have it the same height.

Copy link
Collaborator

@BrunoQuaresmaBrunoQuaresma left a comment

Choose a reason for hiding this comment

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

I'm a little concerned about the added complexity and some things I didn't understand, but after getting some explanation I can quickly come back to this PR and review it 👍

@Parkreiner
Copy link
MemberAuthor

@bpmct@BrunoQuaresma So, Safari support is something I forgot to test for, and the more I look into things, it looks like their handling of the clipboard/navigator APIs is a little wonkier than most browsers. I could see this becoming a rabbit hole, and I think making more sweeping changes with Backstage launch coming up was a mistake

Now that you mention, Ben, I also agree that reducing complexity is even more important in core user flows

This is what I'm going to do:

  1. Revert to the old clipboard logic, but bring in the new bug-fixes
  2. Apply Bruno's suggestions, and fix up the old styling even more
bpmct reacted with thumbs up emoji

@Parkreiner
Copy link
MemberAuthor

@BrunoQuaresma
Before:
Screenshot 2024-01-29 at 9 34 34 AM

After:
Screenshot 2024-01-29 at 9 33 29 AM

BrunoQuaresma reacted with heart emoji

@BrunoQuaresma
Copy link
Collaborator

@Parkreiner I liked the design changes 👍

Wondering if we should use some package for the clipboard that would take care of the complexity for us. 33K starts on GitHubhttps://github.com/zenorocha/clipboard.js

Copy link
Collaborator

@BrunoQuaresmaBrunoQuaresma left a comment

Choose a reason for hiding this comment

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

I'm going to leave the final decision to you 🤗 so we don't block work for Backstage integration.

@Parkreiner
Copy link
MemberAuthor

@BrunoQuaresma Hopefully my tone didn't come across as bad in my responses, but I want to clear: I really appreciate your questions, and the pushback I've gotten. You're making me double-check my own assumptions, and pushing me to make the code as good as it can be

BrunoQuaresma reacted with thumbs up emoji

@BrunoQuaresma
Copy link
Collaborator

@Parkreiner 100%

@Parkreiner
Copy link
MemberAuthor

Wondering if we should use some package for the clipboard that would take care of the complexity for us. 33K starts on GitHubhttps://github.com/zenorocha/clipboard.js

@BrunoQuaresma Yeah, I was going to ask about that at tomorrow's FE Variety before I had to change my flight plans. I feel like the stance we've taken before is "don't bring in a package if it's easy enough to do things yourself", but just because it feels like clipboards are so surprisingly complicated, maybe bringing something in would be for the best

@ParkreinerParkreiner changed the titlefix: improve URL syncs and styling for Auth Token pagefix: improve click UX and styling for Auth Token pageFeb 1, 2024
@ParkreinerParkreiner merged commitb0a855c intomainFeb 1, 2024
@ParkreinerParkreiner deleted the mes/clipboard-fix branchFebruary 1, 2024 02:25
@github-actionsgithub-actionsbot locked and limited conversation to collaboratorsFeb 1, 2024
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@BrunoQuaresmaBrunoQuaresmaBrunoQuaresma approved these changes

Assignees

@ParkreinerParkreiner

Labels
None yet
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

3 participants
@Parkreiner@bpmct@BrunoQuaresma

[8]ページ先頭

©2009-2025 Movatter.jp