Skip to content

Commit

Permalink
feat: inspector open / close improvements (#19922)
Browse files Browse the repository at this point in the history
* feat: inspector open / close improvements

* reorder hook to fix rendering issue
  • Loading branch information
daibhin authored Jan 23, 2024
1 parent a93d86f commit 3c8627a
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 104 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@import '../../../styles/mixins';

.SessionRecordingPlayer {
--inspector-width: 16rem;
--inspector-min-width: 24rem;

position: relative;
display: flex;
Expand Down Expand Up @@ -29,6 +29,7 @@

.SessionRecordingPlayer__main {
flex: 1;
padding-right: 2.5rem;
}

&--fullscreen {
Expand All @@ -49,7 +50,6 @@

.SessionRecordingPlayer__main,
.SessionRecordingPlayer__inspector {
position: relative;
display: flex;
flex-direction: column;
overflow: hidden;
Expand All @@ -62,13 +62,17 @@
}

.SessionRecordingPlayer__inspector {
position: absolute;
top: 0;
right: 0;
bottom: 0;
z-index: 10;
flex-shrink: 0;
min-width: var(--inspector-width);
max-width: 65%;
min-width: var(--inspector-min-width);
max-width: 95%;

&--collapsed {
--inspector-width: 2.5rem;
--inspector-min-width: 2.5rem;
}

.PlayerInspectorPreview {
Expand All @@ -80,26 +84,14 @@
}
}

&--inspector-focus {
.SessionRecordingPlayer__inspector .PlayerInspectorPreview {
pointer-events: none;
opacity: 0;
}
}

&--widescreen {
.SessionRecordingPlayer__main {
padding-right: 0;
}

.SessionRecordingPlayer__inspector {
--inspector-width: 24rem;

position: relative;

.PlayerInspectorPreview {
display: none;
}
max-width: 75%;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { HotkeysInterface, useKeyboardHotkeys } from 'lib/hooks/useKeyboardHotke
import { usePageVisibility } from 'lib/hooks/usePageVisibility'
import { useResizeBreakpoints } from 'lib/hooks/useResizeObserver'
import { LemonDivider } from 'lib/lemon-ui/LemonDivider'
import { useMemo, useRef, useState } from 'react'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useNotebookDrag } from 'scenes/notebooks/AddToNotebook/DraggableToNotebook'
import { PlayerController } from 'scenes/session-recordings/player/controller/PlayerController'
import { PlayerInspector } from 'scenes/session-recordings/player/inspector/PlayerInspector'
Expand Down Expand Up @@ -139,10 +139,18 @@ export function SessionRecordingPlayer(props: SessionRecordingPlayerProps): JSX.
}
)

const [inspectorFocus, setInspectorFocus] = useState(false)
const isWidescreen = !isFullScreen && size === 'medium'

const [inspectorExpanded, setInspectorExpanded] = useState(isWidescreen)

const { draggable, elementProps } = useNotebookDrag({ href: urls.replaySingle(sessionRecordingId) })

useEffect(() => {
if (isWidescreen) {
setInspectorExpanded(true)
}
}, [isWidescreen])

if (isNotFound) {
return (
<div className="text-center">
Expand All @@ -151,8 +159,6 @@ export function SessionRecordingPlayer(props: SessionRecordingPlayerProps): JSX.
)
}

const isWidescreen = !isFullScreen && size === 'medium'

return (
<BindLogic logic={sessionRecordingPlayerLogic} props={logicProps}>
<div
Expand All @@ -161,7 +167,7 @@ export function SessionRecordingPlayer(props: SessionRecordingPlayerProps): JSX.
'SessionRecordingPlayer--fullscreen': isFullScreen,
'SessionRecordingPlayer--no-border': noBorder,
'SessionRecordingPlayer--widescreen': isWidescreen,
'SessionRecordingPlayer--inspector-focus': inspectorFocus || isWidescreen,
'SessionRecordingPlayer--inspector-focus': inspectorExpanded || isWidescreen,
'SessionRecordingPlayer--inspector-hidden': noInspector || size === 'tiny',
'SessionRecordingPlayer--buffering': isBuffering,
})}
Expand All @@ -172,7 +178,14 @@ export function SessionRecordingPlayer(props: SessionRecordingPlayerProps): JSX.
<SessionRecordingPlayerExplorer {...explorerMode} onClose={() => closeExplorer()} />
) : (
<>
<div className="SessionRecordingPlayer__main">
<div
className="SessionRecordingPlayer__main"
onClick={() => {
if (!isWidescreen) {
setInspectorExpanded(false)
}
}}
>
{(!noMeta || isFullScreen) && size !== 'tiny' ? <PlayerMeta /> : null}

<div className="SessionRecordingPlayer__body" draggable={draggable} {...elementProps}>
Expand All @@ -184,9 +197,8 @@ export function SessionRecordingPlayer(props: SessionRecordingPlayerProps): JSX.
</div>
{!noInspector && (
<PlayerInspector
inspectorFocus={inspectorFocus}
setInspectorFocus={setInspectorFocus}
isWidescreen={isWidescreen}
inspectorExpanded={inspectorExpanded}
setInspectorExpanded={setInspectorExpanded}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import { PlayerInspectorList } from './PlayerInspectorList'
import { PlayerInspectorPreview } from './PlayerInspectorPreview'

export function PlayerInspector({
inspectorFocus,
isWidescreen,
setInspectorFocus,
inspectorExpanded,
setInspectorExpanded,
}: {
inspectorFocus: boolean
isWidescreen: boolean
setInspectorFocus: (focus: boolean) => void
inspectorExpanded: boolean
setInspectorExpanded: (focus: boolean) => void
}): JSX.Element {
const ref = useRef<HTMLDivElement>(null)

Expand All @@ -25,33 +23,31 @@ export function PlayerInspector({
persistent: true,
closeThreshold: 100,
placement: 'left',
onToggleClosed: (shouldBeClosed) => setInspectorFocus(!shouldBeClosed),
onToggleClosed: (shouldBeClosed) => setInspectorExpanded(!shouldBeClosed),
}

const { desiredWidth } = useValues(resizerLogic(resizerLogicProps))

const isOpen = inspectorFocus || isWidescreen

return (
<div
className={clsx(
'SessionRecordingPlayer__inspector',
!inspectorFocus && 'SessionRecordingPlayer__inspector--collapsed'
!inspectorExpanded && 'SessionRecordingPlayer__inspector--collapsed'
)}
ref={ref}
// eslint-disable-next-line react/forbid-dom-props
style={{
width: isOpen ? desiredWidth ?? 'var(--inspector-width)' : undefined,
width: inspectorExpanded ? desiredWidth ?? 'var(--inspector-width)' : undefined,
}}
>
<Resizer logicKey="player-inspector" placement="left" containerRef={ref} closeThreshold={100} />
{isOpen ? (
{inspectorExpanded ? (
<>
<PlayerInspectorControls />
<PlayerInspectorControls onClose={() => setInspectorExpanded(false)} />
<PlayerInspectorList />
</>
) : (
<PlayerInspectorPreview onClick={() => setInspectorFocus(true)} />
<PlayerInspectorPreview onClick={() => setInspectorExpanded(true)} />
)}
</div>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { IconX } from '@posthog/icons'
import { LemonButton, LemonCheckbox, LemonInput, LemonSelect, Tooltip } from '@posthog/lemon-ui'
import { useActions, useValues } from 'kea'
import {
Expand Down Expand Up @@ -27,7 +28,7 @@ const TabToIcon = {
[SessionRecordingPlayerTab.NETWORK]: IconGauge,
}

export function PlayerInspectorControls(): JSX.Element {
export function PlayerInspectorControls({ onClose }: { onClose: () => void }): JSX.Element {
const { logicProps } = useValues(sessionRecordingPlayerLogic)
const inspectorLogic = playerInspectorLogic(logicProps)
const { windowIdFilter, tab, syncScrollingPaused, tabsState, windowIds, showMatchingEventsFilter } =
Expand All @@ -53,7 +54,7 @@ export function PlayerInspectorControls(): JSX.Element {

return (
<div className="bg-side p-2 space-y-2 border-b">
<div className="flex justify-between gap-2 flex-wrap">
<div className="flex justify-between gap-2 flex-nowrap">
<div className="flex flex-1 items-center gap-1">
{tabs.map((tabId) => {
const TabIcon = TabToIcon[tabId]
Expand All @@ -79,73 +80,73 @@ export function PlayerInspectorControls(): JSX.Element {
)
})}
</div>
<LemonButton size="small" icon={<IconX />} onClick={onClose} />
</div>

<div className="flex items-center gap-2 flex-1">
<LemonInput
className="min-w-[10rem]"
<div className="flex items-center gap-1 flex-wrap font-medium text-primary-alt" data-attr="mini-filters">
{miniFilters.map((filter) => (
<LemonButton
key={filter.key}
size="small"
onChange={(e) => setSearchQuery(e)}
placeholder="Search..."
type="search"
value={searchQuery}
fullWidth
suffix={
<Tooltip title={<InspectorSearchInfo />}>
<IconInfo />
</Tooltip>
}
/>
</div>
{windowIds.length > 1 ? (
<div className="flex items-center gap-2 flex-wrap">
<LemonSelect
noPadding
active={filter.enabled}
onClick={() => {
// "alone" should always be a select-to-true action
setMiniFilter(filter.key, filter.alone || !filter.enabled)
}}
tooltip={filter.tooltip}
>
<span className="p-1 text-xs">{filter.name}</span>
</LemonButton>
))}
</div>

<div className="flex items-center gap-8 justify-between">
<div className="flex items-center gap-2 flex-1">
<div className="flex flex-1">
<LemonInput
size="small"
data-attr="player-window-select"
value={windowIdFilter}
onChange={(val) => setWindowIdFilter(val || null)}
options={[
{
value: null,
label: 'All windows',
icon: <IconWindow size="small" value="A" className="text-muted" />,
},
...windowIds.map((windowId, index) => ({
value: windowId,
label: `Window ${index + 1}`,
icon: <IconWindow size="small" value={index + 1} className="text-muted" />,
})),
]}
onChange={(e) => setSearchQuery(e)}
placeholder="Search..."
type="search"
value={searchQuery}
fullWidth
suffix={
<Tooltip title={<InspectorSearchInfo />}>
<IconInfo />
</Tooltip>
}
/>
<Tooltip
title="Each recording window translates to a distinct browser tab or window."
className="text-base text-muted-alt"
>
<IconInfo />
</Tooltip>
</div>
) : null}
</div>

<div className="flex items-center gap-2 justify-between">
<div
className="flex items-center gap-1 flex-wrap font-medium text-primary-alt"
data-attr="mini-filters"
>
{miniFilters.map((filter) => (
<LemonButton
key={filter.key}
size="small"
noPadding
active={filter.enabled}
onClick={() => {
// "alone" should always be a select-to-true action
setMiniFilter(filter.key, filter.alone || !filter.enabled)
}}
tooltip={filter.tooltip}
>
<span className="p-1 text-xs">{filter.name}</span>
</LemonButton>
))}
{windowIds.length > 1 ? (
<div className="flex items-center gap-2 flex-wrap">
<LemonSelect
size="small"
data-attr="player-window-select"
value={windowIdFilter}
onChange={(val) => setWindowIdFilter(val || null)}
options={[
{
value: null,
label: 'All windows',
icon: <IconWindow size="small" value="A" className="text-muted" />,
},
...windowIds.map((windowId, index) => ({
value: windowId,
label: `Window ${index + 1}`,
icon: <IconWindow size="small" value={index + 1} className="text-muted" />,
})),
]}
/>
<Tooltip
title="Each recording window translates to a distinct browser tab or window."
className="text-base text-muted-alt"
>
<IconInfo />
</Tooltip>
</div>
) : null}
</div>

<div className="flex items-center gap-1">
Expand Down

0 comments on commit 3c8627a

Please sign in to comment.