-
Notifications
You must be signed in to change notification settings - Fork 3
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: In-browser element inspector for browser recording #502
base: wip/browser-recording
Are you sure you want to change the base?
feat: In-browser element inspector for browser recording #502
Conversation
5685cdd
to
3ba756c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-review
selectTool: (tool: Tool | null) => void | ||
} | ||
|
||
export const useInBrowserUIStore = create<InBrowserUIStore>((set) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to record events if the user is using some tool, so we need some way of accessing the react state from the outside. I would've preferred to use jotai because it's much simpler, but I also didn't want to pull in another dependency. So zustand it is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was split up into individual files. Pretty much every new file in the BrowserEventLog
is just a component extracted as-is from this file. The notable exceptions are the Selector
and PageNavigationDescription
components.
children: ReactNode | ||
} | ||
|
||
export function RecordingContext({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this context to keep track off whether we are in the recorder view or not. It's currently used to enable/disable interactivity in the Selector
and PageNavigationDescription
components. Since the value is constant, it will never trigger any re-renders.
const isRecording = useIsRecording() | ||
|
||
const handleMouseEnter = () => { | ||
if (isRecording) { | ||
window.studio.browserRemote.highlightElement(selector) | ||
} | ||
} | ||
|
||
const handleMouseLeave = () => { | ||
if (isRecording) { | ||
window.studio.browserRemote.highlightElement(null) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic has been added since the component was split from BrowserEventLog
.
const Navigation = forwardRef<HTMLElement, NavigationProps>(function Navigation( | ||
{ url }, | ||
ref | ||
) { | ||
const isRecording = useIsRecording() | ||
|
||
const handleClick = (ev: MouseEvent<HTMLAnchorElement>) => { | ||
ev.preventDefault() | ||
|
||
window.studio.browserRemote.navigateTo(url) | ||
} | ||
|
||
const element = <Strong ref={ref}>{url}</Strong> | ||
|
||
if (!isRecording) { | ||
return element | ||
} | ||
|
||
return ( | ||
<Link | ||
css={css` | ||
cursor: pointer; | ||
|
||
&:hover { | ||
text-decoration: underline; | ||
} | ||
`} | ||
onClick={handleClick} | ||
> | ||
{element} | ||
</Link> | ||
) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic has been added since it was split from BrowserEventLog
.
"@radix-ui/react-toggle-group": "^1.1.2", | ||
"@radix-ui/react-tooltip": "^1.1.8", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot use @radix-ui/theme
in the browser extension. We are using a shadow DOM to isolate our styling from the recorded page, but the <Theme />
component mounts its styles in document.head
. This means that the theme styles are applied to the recorded page, and not to our shadow DOM. As far as I can tell, there's no way of specifying where the styles should be mounted.
@@ -73,6 +73,7 @@ | |||
"@dnd-kit/core": "^6.1.0", | |||
"@dnd-kit/modifiers": "^7.0.0", | |||
"@dnd-kit/sortable": "^8.0.0", | |||
"@emotion/cache": "^11.14.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to configure emotion to inject the style elements inside our shadow root, and that requires us to configure a custom cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description
This PR adds support for inspecting DOM elements and their selectors while recording.
How to Test
Checklist
npm run lint
) and all checks pass.npm test
) and all tests pass.Screenshots (if appropriate):
Screen.Recording.2025-02-19.at.13.44.09.mov
Related PR(s)/Issue(s)