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:
parent
328ff6c32d
commit
699897f71b
8
src/components/Button.scss
Normal file
8
src/components/Button.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
@import "../css/theme";
|
||||||
|
|
||||||
|
.excalidraw {
|
||||||
|
.excalidraw-button {
|
||||||
|
@include outlineButtonStyles;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
}
|
35
src/components/Button.tsx
Normal file
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";
|
||||||
|
Loading…
Reference in New Issue
Block a user