1
0
mirror of https://github.com/excalidraw/excalidraw.git synced 2024-11-02 03:25:53 +01:00

feat: generic button export (#6092)

Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
Barnabás Molnár 2023-01-12 13:06:00 +01:00 committed by GitHub
parent 328ff6c32d
commit 699897f71b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 90 additions and 38 deletions

@ -0,0 +1,8 @@
@import "../css/theme";
.excalidraw {
.excalidraw-button {
@include outlineButtonStyles;
overflow: hidden;
}
}

35
src/components/Button.tsx Normal file

@ -0,0 +1,35 @@
import "./Button.scss";
interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
type?: "button" | "submit" | "reset";
onSelect: () => any;
children: React.ReactNode;
className?: string;
}
/**
* A generic button component that follows Excalidraw's design system.
* Style can be customised using `className` or `style` prop.
* Accepts all props that a regular `button` element accepts.
*/
export const Button = ({
type = "button",
onSelect,
children,
className = "",
...rest
}: ButtonProps) => {
return (
<button
onClick={(event) => {
onSelect();
rest.onClick?.(event);
}}
type={type}
className={`excalidraw-button ${className}`}
{...rest}
>
{children}
</button>
);
};

@ -2,29 +2,22 @@
.excalidraw { .excalidraw {
.collab-button { .collab-button {
@include outlineButtonStyles; --button-bg: var(--color-primary);
width: var(--lg-button-size); --button-color: white;
height: var(--lg-button-size); --button-border: var(--color-primary);
--button-width: var(--lg-button-size);
--button-height: var(--lg-button-size);
--button-hover-bg: var(--color-primary-darker);
--button-hover-border: var(--color-primary-darker);
--button-active-bg: var(--color-primary-darker);
svg {
width: var(--lg-icon-size);
height: var(--lg-icon-size);
}
background-color: var(--color-primary);
border-color: var(--color-primary);
color: white;
flex-shrink: 0; flex-shrink: 0;
&:hover { // double .active to force specificity
background-color: var(--color-primary-darker); &.active.active {
border-color: var(--color-primary-darker);
}
&:active {
background-color: var(--color-primary-darker);
}
&.active {
background-color: #0fb884; background-color: #0fb884;
border-color: #0fb884; border-color: #0fb884;

@ -3,6 +3,7 @@ import { UsersIcon } from "./icons";
import "./CollabButton.scss"; import "./CollabButton.scss";
import clsx from "clsx"; import clsx from "clsx";
import { Button } from "./Button";
const CollabButton = ({ const CollabButton = ({
isCollaborating, isCollaborating,
@ -14,10 +15,10 @@ const CollabButton = ({
onClick: () => void; onClick: () => void;
}) => { }) => {
return ( return (
<button <Button
className={clsx("collab-button", { active: isCollaborating })} className={clsx("collab-button", { active: isCollaborating })}
type="button" type="button"
onClick={onClick} onSelect={onClick}
style={{ position: "relative" }} style={{ position: "relative" }}
title={t("labels.liveCollaboration")} title={t("labels.liveCollaboration")}
> >
@ -25,7 +26,7 @@ const CollabButton = ({
{collaboratorCount > 0 && ( {collaboratorCount > 0 && (
<div className="CollabButton-collaborators">{collaboratorCount}</div> <div className="CollabButton-collaborators">{collaboratorCount}</div>
)} )}
</button> </Button>
); );
}; };

@ -73,7 +73,7 @@
} }
&:hover { &:hover {
background-color: var(--button-hover); background-color: var(--button-hover-bg);
text-decoration: none; text-decoration: none;
} }

@ -408,7 +408,7 @@
pointer-events: all; pointer-events: all;
&:hover { &:hover {
background-color: var(--button-hover); background-color: var(--button-hover-bg);
} }
&:active { &:active {

@ -35,7 +35,7 @@
--shadow-island: 0px 7px 14px rgba(0, 0, 0, 0.05), --shadow-island: 0px 7px 14px rgba(0, 0, 0, 0.05),
0px 0px 3.12708px rgba(0, 0, 0, 0.0798), 0px 0px 3.12708px rgba(0, 0, 0, 0.0798),
0px 0px 0.931014px rgba(0, 0, 0, 0.1702); 0px 0px 0.931014px rgba(0, 0, 0, 0.1702);
--button-hover: var(--color-gray-10); --button-hover-bg: var(--color-gray-10);
--default-border-color: var(--color-gray-30); --default-border-color: var(--color-gray-30);
--default-button-size: 2rem; --default-button-size: 2rem;
@ -135,7 +135,7 @@
--popup-text-inverted-color: #2c2c2c; --popup-text-inverted-color: #2c2c2c;
--select-highlight-color: #{$oc-blue-4}; --select-highlight-color: #{$oc-blue-4};
--text-primary-color: var(--color-gray-40); --text-primary-color: var(--color-gray-40);
--button-hover: var(--color-gray-80); --button-hover-bg: var(--color-gray-80);
--default-border-color: var(--color-gray-80); --default-border-color: var(--color-gray-80);
--shadow-island: 0px 13px 33px rgba(0, 0, 0, 0.07), --shadow-island: 0px 13px 33px rgba(0, 0, 0, 0.07),
0px 4.13px 9.94853px rgba(0, 0, 0, 0.0456112), 0px 4.13px 9.94853px rgba(0, 0, 0, 0.0456112),

@ -39,11 +39,11 @@
.ToolIcon__icon { .ToolIcon__icon {
&:hover { &:hover {
background: var(--button-hover); background: var(--button-hover-bg);
} }
&:active { &:active {
background: var(--button-hover); background: var(--button-hover-bg);
border: 1px solid var(--color-primary-darkest); border: 1px solid var(--color-primary-darkest);
} }
} }
@ -54,24 +54,25 @@
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 0.625rem; padding: 0.625rem;
width: var(--default-button-size); width: var(--button-width, var(--default-button-size));
height: var(--default-button-size); height: var(--button-height, var(--default-button-size));
box-sizing: border-box; box-sizing: border-box;
border-width: 1px; border-width: 1px;
border-style: solid; border-style: solid;
border-color: var(--default-border-color); border-color: var(--button-border, var(--default-border-color));
border-radius: var(--border-radius-lg); border-radius: var(--border-radius-lg);
cursor: pointer; cursor: pointer;
background-color: transparent; background-color: var(--button-bg, var(--island-bg-color));
color: var(--text-primary-color); color: var(--button-color, var(--text-primary-color));
&:hover { &:hover {
background-color: var(--button-hover); background-color: var(--button-hover-bg);
border-color: var(--button-hover-border, var(--default-border-color));
} }
&:active { &:active {
background-color: var(--button-hover); background-color: var(--button-active-bg);
border-color: var(--color-primary-darkest); border-color: var(--button-active-border, var(--color-primary-darkest));
} }
&.active { &.active {
@ -83,7 +84,10 @@
} }
svg { svg {
color: var(--color-primary-darker); color: var(--button-color, var(--color-primary-darker));
width: var(--button-width, var(--lg-icon-size));
height: var(--button-height, var(--lg-icon-size));
} }
} }
} }

@ -1,5 +1,7 @@
import { ExcalidrawImperativeAPI } from "../../../types"; import { ExcalidrawImperativeAPI } from "../../../types";
import { MIME_TYPES } from "../entry"; import { MIME_TYPES } from "../entry";
import { Button } from "../../../components/Button";
const COMMENT_SVG = ( const COMMENT_SVG = (
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -23,6 +25,14 @@ const CustomFooter = ({
}) => { }) => {
return ( return (
<> <>
<Button
onSelect={() => alert("General Kenobi!")}
className="you are a bold one"
style={{ marginLeft: "1rem" }}
title="Hello there!"
>
{COMMENT_SVG}
</Button>
<button <button
className="custom-element" className="custom-element"
onClick={() => { onClick={() => {

@ -239,6 +239,7 @@ export {
} from "../../utils"; } from "../../utils";
export { Sidebar } from "../../components/Sidebar/Sidebar"; export { Sidebar } from "../../components/Sidebar/Sidebar";
export { Button } from "../../components/Button";
export { Footer }; export { Footer };
export { MainMenu }; export { MainMenu };
export { useDevice } from "../../components/App"; export { useDevice } from "../../components/App";