Refactor buttons
This commit is contained in:
parent
db1fb064ca
commit
4cb144809f
19 changed files with 313 additions and 622 deletions
101
src/button/Button.jsx
Normal file
101
src/button/Button.jsx
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
import React, { forwardRef } from "react";
|
||||
import classNames from "classnames";
|
||||
import styles from "./Button.module.css";
|
||||
import { ReactComponent as MicIcon } from "../icons/Mic.svg";
|
||||
import { ReactComponent as MuteMicIcon } from "../icons/MuteMic.svg";
|
||||
import { ReactComponent as VideoIcon } from "../icons/Video.svg";
|
||||
import { ReactComponent as DisableVideoIcon } from "../icons/DisableVideo.svg";
|
||||
import { ReactComponent as HangupIcon } from "../icons/Hangup.svg";
|
||||
import { ReactComponent as ScreenshareIcon } from "../icons/Screenshare.svg";
|
||||
import { useButton } from "@react-aria/button";
|
||||
import { useObjectRef } from "@react-aria/utils";
|
||||
|
||||
const variantToClassName = {
|
||||
default: [styles.button],
|
||||
toolbar: [styles.toolbarButton],
|
||||
icon: [styles.iconButton],
|
||||
copy: [styles.copyButton],
|
||||
};
|
||||
|
||||
export const Button = forwardRef(
|
||||
({ variant = "default", on, off, className, children, ...rest }, ref) => {
|
||||
const buttonRef = useObjectRef(ref);
|
||||
const { buttonProps } = useButton(rest, buttonRef);
|
||||
|
||||
// TODO: react-aria's useButton hook prevents form submission via keyboard
|
||||
// Remove the hack below after this is merged https://github.com/adobe/react-spectrum/pull/904
|
||||
let filteredButtonProps = buttonProps;
|
||||
|
||||
if (rest.type === "submit" && !rest.onPress) {
|
||||
const { onKeyDown, onKeyUp, ...filtered } = buttonProps;
|
||||
filteredButtonProps = filtered;
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
className={classNames(variantToClassName[variant], className, {
|
||||
[styles.on]: on,
|
||||
[styles.off]: off,
|
||||
})}
|
||||
{...filteredButtonProps}
|
||||
ref={buttonRef}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export function ButtonTooltip({ className, children }) {
|
||||
return (
|
||||
<div className={classNames(styles.buttonTooltip, className)}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function MicButton({ muted, ...rest }) {
|
||||
return (
|
||||
<Button variant="toolbar" {...rest} off={muted}>
|
||||
<ButtonTooltip>
|
||||
{muted ? "Unmute microphone" : "Mute microphone"}
|
||||
</ButtonTooltip>
|
||||
{muted ? <MuteMicIcon /> : <MicIcon />}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export function VideoButton({ muted, ...rest }) {
|
||||
return (
|
||||
<Button variant="toolbar" {...rest} off={muted}>
|
||||
<ButtonTooltip>
|
||||
{muted ? "Turn on camera" : "Turn off camera"}
|
||||
</ButtonTooltip>
|
||||
{muted ? <DisableVideoIcon /> : <VideoIcon />}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export function ScreenshareButton({ enabled, className, ...rest }) {
|
||||
return (
|
||||
<Button variant="toolbar" {...rest} on={enabled}>
|
||||
<ButtonTooltip>
|
||||
{enabled ? "Stop sharing screen" : "Share screen"}
|
||||
</ButtonTooltip>
|
||||
<ScreenshareIcon />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
|
||||
export function HangupButton({ className, ...rest }) {
|
||||
return (
|
||||
<Button
|
||||
variant="toolbar"
|
||||
className={classNames(styles.hangupButton, className)}
|
||||
{...rest}
|
||||
>
|
||||
<ButtonTooltip>Leave</ButtonTooltip>
|
||||
<HangupIcon />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
155
src/button/Button.module.css
Normal file
155
src/button/Button.module.css
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
Copyright 2021 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
.button,
|
||||
.toolbarButton,
|
||||
.iconButton {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button {
|
||||
color: #fff;
|
||||
background-color: var(--primaryColor);
|
||||
padding: 7px 15px;
|
||||
border-radius: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.toolbarButton {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50px;
|
||||
background-color: #394049;
|
||||
}
|
||||
|
||||
.toolbarButton:hover {
|
||||
background-color: #8d97a5;
|
||||
}
|
||||
|
||||
.toolbarButton.on,
|
||||
.toolbarButton.off {
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.iconButton svg * {
|
||||
fill: #8e99a4;
|
||||
}
|
||||
|
||||
.iconButton:hover svg * {
|
||||
fill: #8d97a5;
|
||||
}
|
||||
|
||||
.iconButton:hover svg * {
|
||||
fill: #8d97a5;
|
||||
}
|
||||
|
||||
.iconButton.on svg * {
|
||||
fill: #0dbd8b;
|
||||
}
|
||||
|
||||
.hangupButton,
|
||||
.hangupButton:hover {
|
||||
background-color: #ff5b55;
|
||||
}
|
||||
|
||||
.toolbarButton.on svg * {
|
||||
fill: #0dbd8b;
|
||||
}
|
||||
|
||||
.toolbarButton.off svg * {
|
||||
fill: #21262c;
|
||||
}
|
||||
|
||||
.buttonTooltip {
|
||||
display: none;
|
||||
background-color: var(--bgColor2);
|
||||
position: absolute;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 8px 10px;
|
||||
color: var(--textColor1);
|
||||
border-radius: 8px;
|
||||
max-width: 135px;
|
||||
width: max-content;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.buttonTooltip.bottomRight {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.toolbarButton:hover .buttonTooltip {
|
||||
display: flex;
|
||||
bottom: calc(100% + 6px);
|
||||
}
|
||||
|
||||
.iconButton:hover .buttonTooltip {
|
||||
display: flex;
|
||||
top: calc(100% + 6px);
|
||||
}
|
||||
|
||||
.copyButton {
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
cursor: pointer;
|
||||
border: 2px solid #0dbd8b;
|
||||
border-radius: 8px;
|
||||
color: #0dbd8b;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
transition: border-color 250ms, background-color 250ms;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.copyButton span {
|
||||
font-weight: 600;
|
||||
font-size: 15px;
|
||||
margin-right: 10px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.copyButton svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.copyButton:not(.on) svg * {
|
||||
fill: #0dbd8b;
|
||||
}
|
||||
|
||||
.copyButton.on {
|
||||
border-color: transparent;
|
||||
background-color: #0dbd8b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.copyButton.on svg * {
|
||||
stroke: white;
|
||||
}
|
||||
25
src/button/CopyButton.jsx
Normal file
25
src/button/CopyButton.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import React from "react";
|
||||
import useClipboard from "react-use-clipboard";
|
||||
import { ReactComponent as CheckIcon } from "../icons/Check.svg";
|
||||
import { ReactComponent as CopyIcon } from "../icons/Copy.svg";
|
||||
import { Button } from "./Button";
|
||||
|
||||
export function CopyButton({ value, children, ...rest }) {
|
||||
const [isCopied, setCopied] = useClipboard(value, { successDuration: 3000 });
|
||||
|
||||
return (
|
||||
<Button {...rest} variant="copy" on={isCopied} onPress={setCopied}>
|
||||
{isCopied ? (
|
||||
<>
|
||||
<span>Copied!</span>
|
||||
<CheckIcon />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>{children || value}</span>
|
||||
<CopyIcon />
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
2
src/button/index.js
Normal file
2
src/button/index.js
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
export * from "./Button";
|
||||
export * from "./CopyButton";
|
||||
Loading…
Add table
Add a link
Reference in a new issue