зеркало из https://github.com/mozilla/hubs.git
Add RoomLayout, RoomContext, and InvitePopover
This commit is contained in:
Родитель
581481b386
Коммит
9fe1cff579
|
@ -32,7 +32,12 @@ module.exports = {
|
|||
options: {
|
||||
titleProp: true,
|
||||
replaceAttrValues: { "#000": "{props.color}" },
|
||||
template: require("../src/react-components/icons/IconTemplate")
|
||||
template: require("../src/react-components/icons/IconTemplate"),
|
||||
svgoConfig: {
|
||||
plugins: {
|
||||
removeViewBox: false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"url-loader"
|
||||
|
|
|
@ -10,7 +10,7 @@ import { ReactComponent as LeaveIcon } from "../icons/Leave.svg";
|
|||
import { ReactComponent as MoreIcon } from "../icons/More.svg";
|
||||
import { ToolbarButton, presets } from "./ToolbarButton";
|
||||
import styleUtils from "../styles/style-utils.scss";
|
||||
import { Toolbar } from "./Toolbar";
|
||||
import { Toolbar } from "../layout/Toolbar";
|
||||
|
||||
export default {
|
||||
title: "Toolbar",
|
|
@ -0,0 +1,43 @@
|
|||
import React from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import classNames from "classnames";
|
||||
import styles from "./RoomLayout.scss";
|
||||
import { Toolbar } from "./Toolbar";
|
||||
|
||||
export function RoomLayout({
|
||||
className,
|
||||
viewportCanvasRef,
|
||||
viewportClassName,
|
||||
sidebar,
|
||||
sidebarClassName,
|
||||
toolbarLeft,
|
||||
toolbarCenter,
|
||||
toolbarRight,
|
||||
toolbarClassName,
|
||||
...rest
|
||||
}) {
|
||||
return (
|
||||
<div className={classNames(styles.roomLayout, className)} {...rest}>
|
||||
<canvas className={classNames(styles.main, styles.viewport, viewportClassName)} ref={viewportCanvasRef} />
|
||||
<Toolbar
|
||||
className={classNames(styles.main, styles.toolbar, toolbarClassName)}
|
||||
left={toolbarLeft}
|
||||
center={toolbarCenter}
|
||||
right={toolbarRight}
|
||||
/>
|
||||
{sidebar && <div className={classNames(styles.sidebar, sidebarClassName)}>{sidebar}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
RoomLayout.propTypes = {
|
||||
className: PropTypes.string,
|
||||
viewportCanvasRef: PropTypes.object,
|
||||
viewportClassName: PropTypes.string,
|
||||
sidebar: PropTypes.node,
|
||||
sidebarClassName: PropTypes.string,
|
||||
toolbarLeft: PropTypes.node,
|
||||
toolbarCenter: PropTypes.node,
|
||||
toolbarRight: PropTypes.node,
|
||||
toolbarClassName: PropTypes.string
|
||||
};
|
|
@ -0,0 +1,33 @@
|
|||
@use "../styles/theme.scss";
|
||||
|
||||
:local(.room-layout) {
|
||||
display: grid;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
grid-template-columns:
|
||||
[main] auto
|
||||
[sidebar] minmax(auto, min-content);
|
||||
|
||||
grid-template-rows:
|
||||
[viewport] auto
|
||||
[toolbar] min-content;
|
||||
|
||||
background-color: theme.$grey;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
:local(.main) {
|
||||
grid-column-start: main;
|
||||
}
|
||||
|
||||
:local(.sidebar) {
|
||||
grid-column-start: sidebar;
|
||||
}
|
||||
|
||||
:local(.viewport) {
|
||||
grid-row-start: viewport;
|
||||
}
|
||||
|
||||
:local(.toolbar) {
|
||||
grid-row-start: toolbar;
|
||||
}
|
|
@ -10,7 +10,15 @@ import classNames from "classnames";
|
|||
import { ReactComponent as CloseIcon } from "../icons/Close.svg";
|
||||
import { ReactComponent as PopoverArrow } from "./PopoverArrow.svg";
|
||||
|
||||
export function Popover({ content: Content, children, title, placement, initiallyVisible }) {
|
||||
export function Popover({
|
||||
content: Content,
|
||||
children,
|
||||
title,
|
||||
placement,
|
||||
offsetSkidding,
|
||||
offsetDistance,
|
||||
initiallyVisible
|
||||
}) {
|
||||
const [visible, setVisible] = useState(initiallyVisible);
|
||||
const [referenceElement, setReferenceElement] = useState(null);
|
||||
const [popperElement, setPopperElement] = useState(null);
|
||||
|
@ -20,7 +28,10 @@ export function Popover({ content: Content, children, title, placement, initiall
|
|||
attributes
|
||||
} = usePopper(referenceElement, popperElement, {
|
||||
placement,
|
||||
modifiers: [{ name: "arrow", options: { element: arrowElement } }, { name: "offset", options: { offset: [0, 16] } }]
|
||||
modifiers: [
|
||||
{ name: "arrow", options: { element: arrowElement } }, // https://popper.js.org/docs/v2/modifiers/arrow/
|
||||
{ name: "offset", options: { offset: [offsetSkidding, offsetDistance] } } // https://popper.js.org/docs/v2/modifiers/offset/
|
||||
]
|
||||
});
|
||||
const breakpoint = useCssBreakpoints();
|
||||
const fullscreen = breakpoint === "sm";
|
||||
|
@ -83,7 +94,7 @@ export function Popover({ content: Content, children, title, placement, initiall
|
|||
>
|
||||
<div className={styles.header}>
|
||||
<button onClick={closePopover}>
|
||||
<CloseIcon />
|
||||
<CloseIcon width={16} height={16} />
|
||||
</button>
|
||||
<h5>{title}</h5>
|
||||
</div>
|
||||
|
@ -112,5 +123,7 @@ Popover.propTypes = {
|
|||
|
||||
Popover.defaultProps = {
|
||||
initiallyVisible: false,
|
||||
placement: "auto"
|
||||
placement: "auto",
|
||||
offsetSkidding: 0,
|
||||
offsetDistance: 8
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from "react";
|
||||
import { Popover } from "./Popover";
|
||||
import { ToolbarButton } from "../toolbar/ToolbarButton";
|
||||
import { ToolbarButton } from "../input/ToolbarButton";
|
||||
import { ReactComponent as InviteIcon } from "../icons/Invite.svg";
|
||||
|
||||
export default {
|
||||
|
@ -37,7 +37,7 @@ const containerStyles = {
|
|||
padding: "200px"
|
||||
};
|
||||
|
||||
export const Base = args => (
|
||||
export const All = args => (
|
||||
<div style={containerStyles}>
|
||||
<Popover title="Invite" content={<div style={{ padding: "8px" }}>Content</div>} initiallyVisible {...args}>
|
||||
{({ togglePopover, popoverVisible, triggerRef }) => (
|
||||
|
@ -53,10 +53,10 @@ export const Base = args => (
|
|||
</div>
|
||||
);
|
||||
|
||||
Base.parameters = {
|
||||
All.parameters = {
|
||||
layout: "fullscreen"
|
||||
};
|
||||
|
||||
Base.args = {
|
||||
All.args = {
|
||||
placement: "auto"
|
||||
};
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
import React, { useCallback, useContext } from "react";
|
||||
import styles from "./InvitePopover.scss";
|
||||
import { TextInputField } from "../input/TextInputField";
|
||||
import { Button } from "../input/Button";
|
||||
import { RoomContext } from "./RoomContext";
|
||||
|
||||
export function InvitePopover() {
|
||||
const { url, code, embed } = useContext(RoomContext);
|
||||
const copyToClipboard = useCallback(e => console.log(e.target.value));
|
||||
|
||||
return (
|
||||
<div className={styles.invitePopover}>
|
||||
<TextInputField
|
||||
label="Room Link"
|
||||
value={url}
|
||||
afterInput={
|
||||
<Button preset="green" value={url} onClick={copyToClipboard}>
|
||||
Copy
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<TextInputField
|
||||
label="Room Code"
|
||||
value={code}
|
||||
afterInput={
|
||||
<Button preset="blue" value={url} onClick={copyToClipboard}>
|
||||
Copy
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
<TextInputField
|
||||
label="Embed Code"
|
||||
value={embed}
|
||||
afterInput={
|
||||
<Button preset="purple" value={url} onClick={copyToClipboard}>
|
||||
Copy
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
@use "../styles/theme.scss";
|
||||
|
||||
:local(.invite-popover) {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
padding: 16px;
|
||||
width: 100%;
|
||||
|
||||
@media(min-width: theme.$breakpoint-md) {
|
||||
padding: 8px 16px 24px 16px;
|
||||
width: 272px;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import React from "react";
|
||||
import { Popover } from "../popover/Popover";
|
||||
import { ToolbarButton } from "../input/ToolbarButton";
|
||||
import { RoomLayout } from "../layout/RoomLayout";
|
||||
import { ReactComponent as InviteIcon } from "../icons/Invite.svg";
|
||||
import { InvitePopover } from "./InvitePopover";
|
||||
import { RoomContext } from "./RoomContext";
|
||||
|
||||
export default {
|
||||
title: "InvitePopover"
|
||||
};
|
||||
|
||||
const roomContextMock = {
|
||||
url: "hubs.link/oggNnrN",
|
||||
code: "478816",
|
||||
embed:
|
||||
'<iframe src="https://hubs.mozilla.com/oggNnrN/handsome-famous-park?embed_token=5555555555555555555555555" style="width: 1024px; height: 768px;" allow="microphone; camera; vr; speaker;"></iframe>'
|
||||
};
|
||||
|
||||
export const Base = () => (
|
||||
<RoomContext.Provider value={roomContextMock}>
|
||||
<RoomLayout
|
||||
toolbarCenter={
|
||||
<Popover title="Invite" content={InvitePopover} placement="top" offsetDistance={28} initiallyVisible>
|
||||
{({ togglePopover, popoverVisible, triggerRef }) => (
|
||||
<ToolbarButton
|
||||
ref={triggerRef}
|
||||
icon={<InviteIcon />}
|
||||
selected={popoverVisible}
|
||||
onClick={togglePopover}
|
||||
label="Invite"
|
||||
/>
|
||||
)}
|
||||
</Popover>
|
||||
}
|
||||
/>
|
||||
</RoomContext.Provider>
|
||||
);
|
||||
|
||||
Base.parameters = {
|
||||
layout: "fullscreen"
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
import { createContext } from "react";
|
||||
|
||||
export const RoomContext = createContext({
|
||||
url: undefined,
|
||||
code: undefined,
|
||||
embed: undefined
|
||||
});
|
Загрузка…
Ссылка в новой задаче