Add RoomLayout, RoomContext, and InvitePopover

This commit is contained in:
Robert Long 2020-08-25 10:21:04 -07:00
Родитель 581481b386
Коммит 9fe1cff579
14 изменённых файлов: 208 добавлений и 10 удалений

Просмотреть файл

@ -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",

43
src/react-components/layout/RoomLayout.js поставляемый Normal file
Просмотреть файл

@ -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;
}

Просмотреть файл

21
src/react-components/popover/Popover.js поставляемый
Просмотреть файл

@ -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"
};

42
src/react-components/room/InvitePopover.js поставляемый Normal file
Просмотреть файл

@ -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"
};

7
src/react-components/room/RoomContext.js поставляемый Normal file
Просмотреть файл

@ -0,0 +1,7 @@
import { createContext } from "react";
export const RoomContext = createContext({
url: undefined,
code: undefined,
embed: undefined
});