diff --git a/packages/html-reporter/src/links.tsx b/packages/html-reporter/src/links.tsx index 5f199568b5..0c66077f30 100644 --- a/packages/html-reporter/src/links.tsx +++ b/packages/html-reporter/src/links.tsx @@ -74,6 +74,7 @@ export const AttachmentLink: React.FunctionComponent<{ openInNewTab?: boolean, }> = ({ attachment, result, href, linkName, openInNewTab }) => { const isAnchored = useIsAnchored('attachment-' + result.attachments.indexOf(attachment)); + const searchParams = React.useContext(SearchParamsContext); return {attachment.contentType === kMissingContentType ? icons.warning() : icons.attachment()} {attachment.path && {linkName || attachment.name}} @@ -84,7 +85,7 @@ export const AttachmentLink: React.FunctionComponent<{ )} } loadChildren={attachment.body ? () => { return [{linkifyText(attachment.body!)}]; - } : undefined} depth={0} style={{ lineHeight: '32px' }} selected={isAnchored}>; + } : undefined} depth={0} style={{ lineHeight: '32px' }} selected={isAnchored} flash={isAnchored ? searchParams : undefined}>; }; export const SearchParamsContext = React.createContext(new URLSearchParams(window.location.hash.slice(1))); diff --git a/packages/html-reporter/src/treeItem.css b/packages/html-reporter/src/treeItem.css index f37a759c2d..2520ad826f 100644 --- a/packages/html-reporter/src/treeItem.css +++ b/packages/html-reporter/src/treeItem.css @@ -33,3 +33,11 @@ .tree-item-body { min-height: 18px; } + +.yellow-flash { + animation: yellowflash-bg 2s; +} +@keyframes yellowflash-bg { + from { background: var(--color-attention-subtle); } + to { background: transparent; } +} diff --git a/packages/html-reporter/src/treeItem.tsx b/packages/html-reporter/src/treeItem.tsx index 926a398a05..8fb0d6acda 100644 --- a/packages/html-reporter/src/treeItem.tsx +++ b/packages/html-reporter/src/treeItem.tsx @@ -19,6 +19,19 @@ import './treeItem.css'; import * as icons from './icons'; import { clsx } from '@web/uiUtils'; +// flash is retriggered whenever the value changes +function useFlash(flash: any | undefined) { + const [flashState, setFlashState] = React.useState(false); + React.useEffect(() => { + if (flash) { + setFlashState(true); + const timeout = setTimeout(() => setFlashState(false), 1000); + return () => clearTimeout(timeout); + } + }, [flash]); + return flashState; +} + export const TreeItem: React.FunctionComponent<{ title: JSX.Element, loadChildren?: () => JSX.Element[], @@ -27,9 +40,11 @@ export const TreeItem: React.FunctionComponent<{ depth: number, selected?: boolean, style?: React.CSSProperties, -}> = ({ title, loadChildren, onClick, expandByDefault, depth, selected, style }) => { + flash?: any +}> = ({ title, loadChildren, onClick, expandByDefault, depth, selected, style, flash }) => { + const addFlashClass = useFlash(flash); const [expanded, setExpanded] = React.useState(expandByDefault || false); - return + return { onClick?.(); setExpanded(!expanded); }} > {loadChildren && !!expanded && icons.downArrow()} {loadChildren && !expanded && icons.rightArrow()}