diff --git a/src/Popover.jsx b/src/Popover.jsx
index 7729fc0..fe32fe6 100644
--- a/src/Popover.jsx
+++ b/src/Popover.jsx
@@ -3,11 +3,11 @@ import { DismissButton, useOverlay } from "@react-aria/overlays";
import { FocusScope } from "@react-aria/focus";
import classNames from "classnames";
import styles from "./Popover.module.css";
+import { useObjectRef } from "@react-aria/utils";
export const Popover = forwardRef(
({ isOpen = true, onClose, className, children, ...rest }, ref) => {
- const fallbackRef = useRef();
- const popoverRef = ref || fallbackRef;
+ const popoverRef = useObjectRef(ref);
const { overlayProps } = useOverlay(
{
diff --git a/src/Room.jsx b/src/Room.jsx
index ccd064b..6738718 100644
--- a/src/Room.jsx
+++ b/src/Room.jsx
@@ -51,6 +51,7 @@ import { GridLayoutMenu } from "./GridLayoutMenu";
import { UserMenu } from "./UserMenu";
import classNames from "classnames";
import { Avatar } from "./Avatar";
+import { UserMenuContainer } from "./UserMenuContainer";
const canScreenshare = "getDisplayMedia" in navigator.mediaDevices;
// There is currently a bug in Safari our our code with cloning and sending MediaStreams
@@ -309,7 +310,7 @@ function RoomSetupView({
@@ -470,7 +471,7 @@ function InRoomView({
- {!isGuest && }
+ {!isGuest && }
{items.length === 0 ? (
diff --git a/src/Tooltip.jsx b/src/Tooltip.jsx
index fdc0798..e9d3596 100644
--- a/src/Tooltip.jsx
+++ b/src/Tooltip.jsx
@@ -1,7 +1,7 @@
-import React, { forwardRef, useRef } from "react";
+import React, { forwardRef } from "react";
import { useTooltipTriggerState } from "@react-stately/tooltip";
import { useTooltipTrigger, useTooltip } from "@react-aria/tooltip";
-import { mergeProps } from "@react-aria/utils";
+import { mergeProps, useObjectRef } from "@react-aria/utils";
import styles from "./Tooltip.module.css";
import classNames from "classnames";
@@ -20,8 +20,7 @@ export function Tooltip({ position, state, ...props }) {
export const TooltipTrigger = forwardRef(({ children, ...rest }, ref) => {
const tooltipState = useTooltipTriggerState(rest);
- const fallbackRef = useRef();
- const triggerRef = ref || fallbackRef;
+ const triggerRef = useObjectRef(ref);
const { triggerProps, tooltipProps } = useTooltipTrigger(
rest,
tooltipState,
diff --git a/src/UserMenu.jsx b/src/UserMenu.jsx
index a6d5d07..d1d9a5a 100644
--- a/src/UserMenu.jsx
+++ b/src/UserMenu.jsx
@@ -1,58 +1,34 @@
-import React, { useCallback, useMemo } from "react";
+import React, { useMemo } from "react";
+import { Item } from "@react-stately/collections";
import { Button, LinkButton } from "./button";
import { PopoverMenuTrigger } from "./PopoverMenu";
+import { Menu } from "./Menu";
+import { Tooltip, TooltipTrigger } from "./Tooltip";
+import { Avatar } from "./Avatar";
import { ReactComponent as UserIcon } from "./icons/User.svg";
import { ReactComponent as LoginIcon } from "./icons/Login.svg";
import { ReactComponent as LogoutIcon } from "./icons/Logout.svg";
import styles from "./UserMenu.module.css";
-import { Item } from "@react-stately/collections";
-import { Menu } from "./Menu";
-import { useHistory, useLocation } from "react-router-dom";
-import { useClient, useProfile } from "./ConferenceCallManagerHooks";
-import { useModalTriggerState } from "./Modal";
-import { ProfileModal } from "./ProfileModal";
-import { Tooltip, TooltipTrigger } from "./Tooltip";
-import { Avatar } from "./Avatar";
+import { useLocation } from "react-router-dom";
-export function UserMenu({ disableLogout }) {
+export function UserMenu({
+ disableLogout,
+ isAuthenticated,
+ isPasswordlessUser,
+ displayName,
+ avatarUrl,
+ onAction,
+}) {
const location = useLocation();
- const history = useHistory();
- const {
- isAuthenticated,
- isGuest,
- isPasswordlessUser,
- logout,
- userName,
- client,
- } = useClient();
- const { displayName, avatarUrl } = useProfile(client);
- const { modalState, modalProps } = useModalTriggerState();
-
- const onAction = useCallback(
- (value) => {
- switch (value) {
- case "user":
- modalState.open();
- break;
- case "logout":
- logout();
- break;
- case "login":
- history.push("/login", { state: { from: location } });
- break;
- }
- },
- [history, location, logout, modalState]
- );
const items = useMemo(() => {
const arr = [];
- if (isAuthenticated && !isGuest) {
+ if (isAuthenticated) {
arr.push({
key: "user",
icon: UserIcon,
- label: displayName || userName,
+ label: displayName,
});
if (isPasswordlessUser) {
@@ -73,9 +49,9 @@ export function UserMenu({ disableLogout }) {
}
return arr;
- }, [isAuthenticated, isGuest, userName, displayName]);
+ }, [isAuthenticated, isPasswordlessUser, displayName, disableLogout]);
- if (isGuest || !isAuthenticated) {
+ if (!isAuthenticated) {
return (
Log in
@@ -84,46 +60,36 @@ export function UserMenu({ disableLogout }) {
}
return (
- <>
-
-
-
- {(props) => (
-
- Profile
-
+
+
+
+
{(props) => (
-
+
+ Profile
+
)}
-
- {modalState.isOpen && (
-
+
+ {(props) => (
+
)}
- >
+
);
}
diff --git a/src/UserMenu.module.css b/src/UserMenu.module.css
index 60597b4..8cda2eb 100644
--- a/src/UserMenu.module.css
+++ b/src/UserMenu.module.css
@@ -1,3 +1,17 @@
.userButton svg * {
fill: var(--textColor1);
}
+
+.avatar {
+ width: 24px;
+ height: 24px;
+ font-size: 12px;
+}
+
+@media (min-width: 800px) {
+ .avatar {
+ width: 32px;
+ height: 32px;
+ font-size: 15px;
+ }
+}
diff --git a/src/UserMenuContainer.jsx b/src/UserMenuContainer.jsx
new file mode 100644
index 0000000..d9f2f5c
--- /dev/null
+++ b/src/UserMenuContainer.jsx
@@ -0,0 +1,62 @@
+import React, { useCallback } from "react";
+import { useHistory, useLocation } from "react-router-dom";
+import { useClient, useProfile } from "./ConferenceCallManagerHooks";
+import { useModalTriggerState } from "./Modal";
+import { ProfileModal } from "./ProfileModal";
+import { UserMenu } from "./UserMenu";
+
+export function UserMenuContainer({ disableLogout }) {
+ const location = useLocation();
+ const history = useHistory();
+ const {
+ isAuthenticated,
+ isGuest,
+ isPasswordlessUser,
+ logout,
+ userName,
+ client,
+ } = useClient();
+ const { displayName, avatarUrl } = useProfile(client);
+ const { modalState, modalProps } = useModalTriggerState();
+
+ const onAction = useCallback(
+ (value) => {
+ switch (value) {
+ case "user":
+ modalState.open();
+ break;
+ case "logout":
+ logout();
+ break;
+ case "login":
+ history.push("/login", { state: { from: location } });
+ break;
+ }
+ },
+ [history, location, logout, modalState]
+ );
+
+ return (
+ <>
+
+ {modalState.isOpen && (
+
+ )}
+ >
+ );
+}
diff --git a/src/button/Button.jsx b/src/button/Button.jsx
index 434d4fd..a98fbb6 100644
--- a/src/button/Button.jsx
+++ b/src/button/Button.jsx
@@ -62,7 +62,7 @@ export const Button = forwardRef(
[styles.off]: off,
}
)}
- {...filteredButtonProps}
+ {...mergeProps(rest, filteredButtonProps)}
ref={buttonRef}
>
{children}
diff --git a/src/usePageFocusStyle.js b/src/usePageFocusStyle.js
new file mode 100644
index 0000000..c7ec75f
--- /dev/null
+++ b/src/usePageFocusStyle.js
@@ -0,0 +1,22 @@
+import { useEffect } from "react";
+import { useFocusVisible } from "@react-aria/interactions";
+import styles from "./usePageFocusStyle.module.css";
+
+export function usePageFocusStyle() {
+ const { isFocusVisible } = useFocusVisible();
+
+ useEffect(() => {
+ const classList = document.body.classList;
+ const hasClass = classList.contains(styles.hideFocus);
+
+ if (isFocusVisible && hasClass) {
+ classList.remove(styles.hideFocus);
+ } else if (!isFocusVisible && !hasClass) {
+ classList.add(styles.hideFocus);
+ }
+
+ return () => {
+ classList.remove(styles.hideFocus);
+ };
+ }, [isFocusVisible]);
+}
diff --git a/src/App.module.css b/src/usePageFocusStyle.module.css
similarity index 100%
rename from src/App.module.css
rename to src/usePageFocusStyle.module.css