mirror of
https://github.com/excalidraw/excalidraw.git
synced 2026-08-30 16:55:16 +08:00
feat(packages/excalidraw): support ViewportStatusFrame label onClick (#11838)
This commit is contained in:
@@ -2355,6 +2355,8 @@ class App extends React.Component<AppProps, AppState> {
|
||||
"excalidraw--allow-browser-zoom":
|
||||
!this.isInteractionEnabled() && this.isBrowserZoomEnabled(),
|
||||
"excalidraw--ui-hidden": !this.isDefaultUIEnabled(),
|
||||
"excalidraw--viewport-status-label":
|
||||
!!this.props.viewportStatusFrame?.label,
|
||||
})}
|
||||
style={{
|
||||
["--ui-pointerEvents" as any]: shouldBlockPointerEvents
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
inset: 0;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
border: 2px solid;
|
||||
border: 4px solid;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@@ -18,20 +18,46 @@
|
||||
|
||||
background-color: var(--color-primary-hover);
|
||||
color: var(--color-primary-light);
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 0.5rem;
|
||||
font-size: 0.75rem;
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewport-status-frame__badge--clickable {
|
||||
cursor: pointer;
|
||||
|
||||
&:active {
|
||||
transform: translateX(-50%) scale(0.96);
|
||||
}
|
||||
}
|
||||
|
||||
.viewport-status-frame__badge-action {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
padding: 0;
|
||||
background: transparent;
|
||||
cursor: inherit;
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: -2px;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.viewport-status-frame__badge-label {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
padding: 0.25rem 0.5rem;
|
||||
white-space: pre-wrap;
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.viewport-status-frame__badge-icon {
|
||||
@@ -48,6 +74,8 @@
|
||||
all: unset;
|
||||
cursor: pointer;
|
||||
border-radius: 0.25rem;
|
||||
margin-right: 0.5rem;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-primary-darker);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { useId } from "react";
|
||||
|
||||
import clsx from "clsx";
|
||||
|
||||
import { t } from "../../i18n";
|
||||
import { CloseIcon } from "../icons";
|
||||
|
||||
@@ -11,6 +15,15 @@ interface ViewportStatusFrameProps {
|
||||
|
||||
const ViewportStatusFrame = ({ status }: ViewportStatusFrameProps) => {
|
||||
const { border, label } = status;
|
||||
const labelId = useId();
|
||||
const labelContent = label && (
|
||||
<>
|
||||
{label.icon && (
|
||||
<span className="viewport-status-frame__badge-icon">{label.icon}</span>
|
||||
)}
|
||||
{label.label}
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -22,20 +35,28 @@ const ViewportStatusFrame = ({ status }: ViewportStatusFrameProps) => {
|
||||
)}
|
||||
{label && (
|
||||
<div
|
||||
className="viewport-status-frame__badge"
|
||||
className={clsx("viewport-status-frame__badge", {
|
||||
"viewport-status-frame__badge--clickable": label.onClick,
|
||||
})}
|
||||
role="status"
|
||||
style={{
|
||||
backgroundColor: label.background || border || undefined,
|
||||
color: label.color,
|
||||
}}
|
||||
>
|
||||
<div className="viewport-status-frame__badge-label">
|
||||
{label.icon && (
|
||||
<span className="viewport-status-frame__badge-icon">
|
||||
{label.icon}
|
||||
</span>
|
||||
)}
|
||||
{label.label}
|
||||
{label.onClick && (
|
||||
<button
|
||||
type="button"
|
||||
className="viewport-status-frame__badge-action"
|
||||
aria-labelledby={labelId}
|
||||
onClick={label.onClick}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="viewport-status-frame__badge-label"
|
||||
id={label.onClick ? labelId : undefined}
|
||||
>
|
||||
{labelContent}
|
||||
</div>
|
||||
{label.onClose && (
|
||||
<button
|
||||
|
||||
@@ -39,6 +39,12 @@ body.excalidraw-cursor-resize * {
|
||||
.excalidraw {
|
||||
--ui-font: Assistant, system-ui, BlinkMacSystemFont, -apple-system, Segoe UI,
|
||||
Roboto, Helvetica, Arial, sans-serif;
|
||||
--viewport-status-label-offset: 0px;
|
||||
|
||||
&.excalidraw--viewport-status-label {
|
||||
--viewport-status-label-offset: 0.75rem;
|
||||
}
|
||||
|
||||
font-family: var(--ui-font);
|
||||
|
||||
position: relative;
|
||||
@@ -510,7 +516,7 @@ body.excalidraw-cursor-resize * {
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 30px;
|
||||
bottom: calc(30px + var(--viewport-status-label-offset));
|
||||
transform: translateX(-50%);
|
||||
pointer-events: var(--ui-pointerEvents);
|
||||
font-family: inherit;
|
||||
@@ -527,7 +533,7 @@ body.excalidraw-cursor-resize * {
|
||||
.floating-status-stack {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 30px;
|
||||
bottom: calc(30px + var(--viewport-status-label-offset));
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -585,12 +591,12 @@ body.excalidraw-cursor-resize * {
|
||||
}
|
||||
|
||||
.floating-status-stack {
|
||||
bottom: calc(30px + var(--sab, 0));
|
||||
bottom: calc(30px + var(--viewport-status-label-offset) + var(--sab, 0));
|
||||
z-index: var(--zIndex-ui-bottom);
|
||||
}
|
||||
|
||||
.scroll-back-to-content {
|
||||
bottom: calc(100px + var(--sab, 0));
|
||||
bottom: calc(100px + var(--viewport-status-label-offset) + var(--sab, 0));
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -645,6 +645,8 @@ export type ViewportStatusFrame = {
|
||||
background?: string;
|
||||
/** badge text color; defaults to var(--color-primary-light) */
|
||||
color?: string;
|
||||
/** makes the badge label interactive */
|
||||
onClick?: () => void;
|
||||
/** renders a close button when set */
|
||||
onClose?: () => void;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user