Skip to content

Commit 0fa3c9a

Browse files
authored
Add visibility badge to header (#10542)
When clicked, this badge opens the share modal dialog
1 parent f620e9e commit 0fa3c9a

File tree

3 files changed

+80
-12
lines changed

3 files changed

+80
-12
lines changed

packages/replay-next/components/Icon.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ export type IconType =
4545
| "folder-open"
4646
| "hide"
4747
| "inspect"
48-
| "invisible"
4948
| "invoke-getter"
5049
| "log-point-panel-arrow-above"
5150
| "log-point-panel-arrow-below"
@@ -91,7 +90,9 @@ export type IconType =
9190
| "view-component-source"
9291
| "view-function-source"
9392
| "view-html-element"
94-
| "visible"
93+
| "visibility-private"
94+
| "visibility-public"
95+
| "visibility-team"
9596
| "warning"
9697
| "whole-word"
9798
| "regex";
@@ -305,10 +306,6 @@ export default function Icon({
305306
</>
306307
);
307308
break;
308-
case "invisible":
309-
path =
310-
"M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46C3.08 8.3 1.78 10.02 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z";
311-
break;
312309
case "invoke-getter":
313310
path = (
314311
<>
@@ -680,9 +677,29 @@ export default function Icon({
680677
path =
681678
"M5 15H3v4c0 1.1.9 2 2 2h4v-2H5v-4zM5 5h4V3H5c-1.1 0-2 .9-2 2v4h2V5zm14-2h-4v2h4v4h2V5c0-1.1-.9-2-2-2zm0 16h-4v2h4c1.1 0 2-.9 2-2v-4h-2v4zM12 9c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z";
682679
break;
683-
case "visible":
680+
case "visibility-private":
684681
path =
685-
"M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z";
682+
"M18 8h-1V6c0-2.76-2.24-5-5-5S7 3.24 7 6v2H6c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V10c0-1.1-.9-2-2-2zm-6 9c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2zm3.1-9H8.9V6c0-1.71 1.39-3.1 3.1-3.1 1.71 0 3.1 1.39 3.1 3.1v2z";
683+
break;
684+
case "visibility-public":
685+
path =
686+
"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z";
687+
break;
688+
case "visibility-team":
689+
path = (
690+
<g>
691+
<path
692+
d="M16.67,13.13C18.04,14.06,19,15.32,19,17v3h4v-3 C23,14.82,19.43,13.53,16.67,13.13z"
693+
fillRule="evenodd"
694+
/>
695+
<circle cx="9" cy="8" fillRule="evenodd" r="4" />
696+
<path
697+
d="M15,12c2.21,0,4-1.79,4-4c0-2.21-1.79-4-4-4c-0.47,0-0.91,0.1-1.33,0.24 C14.5,5.27,15,6.58,15,8s-0.5,2.73-1.33,3.76C14.09,11.9,14.53,12,15,12z"
698+
fillRule="evenodd"
699+
/>
700+
<path d="M9,13c-2.67,0-8,1.34-8,4v3h16v-3C17,14.34,11.67,13,9,13z" fillRule="evenodd" />
701+
</g>
702+
);
686703
break;
687704
case "warning":
688705
path = "M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z";

src/ui/components/Header/Header.module.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,26 @@
5757
transform: rotate(180deg);
5858
margin: 2px 2px 0 6px;
5959
}
60+
61+
.VisibilityIcon {
62+
width: 1rem;
63+
height: 1rem;
64+
}
65+
66+
.VisibilityIconAndText {
67+
flex-shrink: 0;
68+
display: flex;
69+
flex-direction: row;
70+
align-items: center;
71+
gap: 1ch;
72+
font-size: var(--font-size-regular);
73+
background-color: var(--body-bgcolor);
74+
border-radius: 1rem;
75+
overflow: hidden;
76+
padding: 0.25rem 0.5rem;
77+
cursor: pointer;
78+
}
79+
80+
.VisibilityIconAndText:hover {
81+
background-color: var(--title-hover-bgcolor);
82+
}

src/ui/components/Header/Header.tsx

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ import classNames from "classnames";
44
import { useRouter } from "next/router";
55
import { ClipboardEvent, KeyboardEvent, useLayoutEffect, useRef, useState } from "react";
66

7+
import Icon, { IconType } from "replay-next/components/Icon";
8+
import { useNag } from "replay-next/src/hooks/useNag";
79
import { RecordingTarget } from "replay-next/src/suspense/BuildIdCache";
8-
import { Recording } from "shared/graphql/types";
10+
import { Nag, Recording } from "shared/graphql/types";
911
import { selectAll } from "shared/utils/selection";
10-
import { getAccessToken, getRecordingTarget } from "ui/actions/app";
12+
import { getAccessToken, getRecordingTarget, setModal } from "ui/actions/app";
1113
import Avatar from "ui/components/Avatar";
1214
import UserOptions from "ui/components/Header/UserOptions";
1315
import ViewToggle, { shouldShowDevToolsNag } from "ui/components/Header/ViewToggle";
1416
import IconWithTooltip from "ui/components/shared/IconWithTooltip";
1517
import hooks from "ui/hooks";
1618
import { useGetActiveSessions } from "ui/hooks/sessions";
1719
import { getViewMode } from "ui/reducers/layout";
18-
import { useAppSelector } from "ui/setup/hooks";
20+
import { useAppDispatch, useAppSelector } from "ui/setup/hooks";
1921
import { trackEvent } from "ui/utils/telemetry";
2022

2123
import { isTestSuiteReplay } from "../TestSuite/utils/isTestSuiteReplay";
@@ -169,9 +171,13 @@ export default function Header() {
169171
const recordingTarget = useAppSelector(getRecordingTarget);
170172
const isAuthenticated = !!useAppSelector(getAccessToken);
171173
const recordingId = hooks.useGetRecordingId();
172-
const { recording, loading } = hooks.useGetRecording(recordingId);
174+
const { loading, recording } = hooks.useGetRecording(recordingId);
173175
const backIcon = <div className={classNames(styles.BackButton, "img", "arrowhead-right")} />;
174176

177+
const dispatch = useAppDispatch();
178+
179+
const [, dismissShareNag] = useNag(Nag.SHARE); // Properly call useNag and destructure dismissShareNag
180+
175181
if (loading) {
176182
return <div className={styles.Header}></div>;
177183
}
@@ -197,6 +203,25 @@ export default function Header() {
197203
}
198204
}
199205

206+
let iconType: IconType;
207+
let visibilityLabel: string;
208+
if (!recording.private) {
209+
iconType = "visibility-public";
210+
visibilityLabel = "Public";
211+
} else if (recording.workspace) {
212+
iconType = "visibility-team";
213+
visibilityLabel = "Team";
214+
} else {
215+
iconType = "visibility-private";
216+
visibilityLabel = "Private";
217+
}
218+
219+
const onClick = () => {
220+
trackEvent("header.open_share");
221+
dismissShareNag();
222+
dispatch(setModal("sharing", { recordingId: recordingId! }));
223+
};
224+
200225
return (
201226
<div className={styles.Header}>
202227
<div className="relative flex flex-grow flex-row items-center overflow-hidden">
@@ -210,6 +235,9 @@ export default function Header() {
210235
) : (
211236
<div className={styles.ReadOnlyTitle}>Recordings</div>
212237
)}
238+
<button className={styles.VisibilityIconAndText} onClick={onClick}>
239+
<Icon className={styles.VisibilityIcon} type={iconType} /> {visibilityLabel}
240+
</button>
213241
<div className="flex-grow">&nbsp;</div>
214242
</div>
215243
<Links recordingTarget={recordingTarget} />

0 commit comments

Comments
 (0)