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

* wip: commit progress for clipboard update

* wip: push more progress

* chore: finish initial version of useClipboard revamp

* refactor: update API query to use newer RQ patterns

* fix: update importers of useClipboard

* fix: increase clickable area of CodeExample

* fix: update styles for CliAuthPageView

* fix: resolve issue with ref re-routing

* docs: update comments for clarity

* wip: commit progress on clipboard tests

* chore: add extra test case for referential stability

* wip: disable test stub to avoid breaking CI

* wip: add test case for tab-switching

* feat: finish changes

* fix: improve styling for strong text

* fix: make sure period doesn't break onto separate line

* fix: make center styling more friendly to screen readers

* refactor: clean up mocking implementation

* fix: resolve security concern for clipboard text

* fix: update CodeExample to obscure text when appropriate

* fix: apply secret changes to relevant code examples

* refactor: simplify code for obfuscating text

* fix: partially revert clipboard changes

* fix: clean up page styling further

* fix: remove duplicate property identifier

* refactor: rename variables for clarity

* fix: simplify/revert CopyButton component design

* fix: update how dummy input is hidden from page

* fix: remove unused onClick handler prop

* fix: resolve unused import

* fix: opt code examples out of secret behavior
This commit is contained in:
Michael Smith
2024-01-31 21:25:30 -05:00
committed by GitHub
parent c7f51a9d70
commit b0a855caa4
14 changed files with 217 additions and 83 deletions
@@ -1,7 +1,8 @@
import { type FC } from "react";
import { type FC, type KeyboardEvent, type MouseEvent, useRef } from "react";
import { type Interpolation, type Theme } from "@emotion/react";
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
import { CopyButton } from "../CopyButton/CopyButton";
import { visuallyHidden } from "@mui/utils";
export interface CodeExampleProps {
code: string;
@@ -14,19 +15,72 @@ export interface CodeExampleProps {
*/
export const CodeExample: FC<CodeExampleProps> = ({
code,
secret,
className,
// Defaulting to true to be on the safe side; you should have to opt out of
// the secure option, not remember to opt in
secret = true,
}) => {
const buttonRef = useRef<HTMLButtonElement>(null);
const triggerButton = (event: KeyboardEvent | MouseEvent) => {
if (event.target !== buttonRef.current) {
buttonRef.current?.click();
}
};
return (
<div css={styles.container} className={className}>
<code css={[styles.code, secret && styles.secret]}>{code}</code>
<CopyButton text={code} />
/* eslint-disable-next-line jsx-a11y/no-static-element-interactions --
Expanding clickable area of CodeExample for better ergonomics, but don't
want to change the semantics of the HTML elements being rendered
*/
<div
css={styles.container}
className={className}
onClick={triggerButton}
onKeyDown={(event) => {
if (event.key === "Enter") {
triggerButton(event);
}
}}
onKeyUp={(event) => {
if (event.key === " ") {
triggerButton(event);
}
}}
>
<code css={[styles.code, secret && styles.secret]}>
{secret ? (
<>
{/*
* Obfuscating text even though we have the characters replaced with
* discs in the CSS for two reasons:
* 1. The CSS property is non-standard and won't work everywhere;
* MDN warns you not to rely on it alone in production
* 2. Even with it turned on and supported, the plaintext is still
* readily available in the HTML itself
*/}
<span aria-hidden>{obfuscateText(code)}</span>
<span css={{ ...visuallyHidden }}>
Encrypted text. Please access via the copy button.
</span>
</>
) : (
<>{code}</>
)}
</code>
<CopyButton ref={buttonRef} text={code} />
</div>
);
};
function obfuscateText(text: string): string {
return new Array(text.length).fill("*").join("");
}
const styles = {
container: (theme) => ({
cursor: "pointer",
display: "flex",
flexDirection: "row",
alignItems: "center",
@@ -37,6 +91,10 @@ const styles = {
padding: 8,
lineHeight: "150%",
border: `1px solid ${theme.experimental.l1.outline}`,
"&:hover": {
backgroundColor: theme.experimental.l2.hover.background,
},
}),
code: {