Add IDs to UI components (#511)
* Add IDs to Menu and its sub-menus * Commit uncommitted * Added ID on Styles and Zoom menu * Added ID on Tools menu * Added ID on Context menu
This commit is contained in:
parent
5b521df51e
commit
dd1fb73876
24 changed files with 387 additions and 186 deletions
|
@ -163,44 +163,48 @@ const InnerMenu = React.memo(function InnerMenu({ onBlur }: InnerContextMenuProp
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
onBlur={onBlur}
|
onBlur={onBlur}
|
||||||
>
|
>
|
||||||
<MenuContent>
|
<MenuContent id="TD-ContextMenu">
|
||||||
{hasSelection ? (
|
{hasSelection ? (
|
||||||
<>
|
<>
|
||||||
<CMRowButton onClick={handleDuplicate} kbd="#D">
|
<CMRowButton onClick={handleDuplicate} kbd="#D" id="TD-ContextMenu-Duplicate">
|
||||||
Duplicate
|
Duplicate
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleFlipHorizontal} kbd="⇧H">
|
<CMRowButton
|
||||||
|
onClick={handleFlipHorizontal}
|
||||||
|
kbd="⇧H"
|
||||||
|
id="TD-ContextMenu-Flip_Horizontal"
|
||||||
|
>
|
||||||
Flip Horizontal
|
Flip Horizontal
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleFlipVertical} kbd="⇧V">
|
<CMRowButton onClick={handleFlipVertical} kbd="⇧V" id="TD-ContextMenu-Flip_Vertical">
|
||||||
Flip Vertical
|
Flip Vertical
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleLock} kbd="#⇧L">
|
<CMRowButton onClick={handleLock} kbd="#⇧L" id="TD-ContextMenu- Lock_Unlock">
|
||||||
Lock / Unlock
|
Lock / Unlock
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
{(hasTwoOrMore || hasGroupSelected) && <Divider />}
|
{(hasTwoOrMore || hasGroupSelected) && <Divider />}
|
||||||
{hasTwoOrMore && (
|
{hasTwoOrMore && (
|
||||||
<CMRowButton onClick={handleGroup} kbd="#G">
|
<CMRowButton onClick={handleGroup} kbd="#G" id="TD-ContextMenu-Group">
|
||||||
Group
|
Group
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
)}
|
)}
|
||||||
{hasGroupSelected && (
|
{hasGroupSelected && (
|
||||||
<CMRowButton onClick={handleGroup} kbd="#G">
|
<CMRowButton onClick={handleGroup} kbd="#G" id="TD-ContextMenu-Ungroup">
|
||||||
Ungroup
|
Ungroup
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
)}
|
)}
|
||||||
<Divider />
|
<Divider />
|
||||||
<ContextMenuSubMenu label="Move">
|
<ContextMenuSubMenu label="Move" id="TD-ContextMenu-Move">
|
||||||
<CMRowButton onClick={handleMoveToFront} kbd="⇧]">
|
<CMRowButton onClick={handleMoveToFront} kbd="⇧]" id="TD-ContextMenu-Move-To_Front">
|
||||||
To Front
|
To Front
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleMoveForward} kbd="]">
|
<CMRowButton onClick={handleMoveForward} kbd="]" id="TD-ContextMenu-Move-Forward">
|
||||||
Forward
|
Forward
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleMoveBackward} kbd="[">
|
<CMRowButton onClick={handleMoveBackward} kbd="[" id="TD-ContextMenu-Move-Backward">
|
||||||
Backward
|
Backward
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleMoveToBack} kbd="⇧[">
|
<CMRowButton onClick={handleMoveToBack} kbd="⇧[" id="TD-ContextMenu-Move-To_Back">
|
||||||
To Back
|
To Back
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
</ContextMenuSubMenu>
|
</ContextMenuSubMenu>
|
||||||
|
@ -211,53 +215,79 @@ const InnerMenu = React.memo(function InnerMenu({ onBlur }: InnerContextMenuProp
|
||||||
{app.callbacks.onExport ? (
|
{app.callbacks.onExport ? (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<ContextMenuSubMenu label="Export" size="small">
|
<ContextMenuSubMenu label="Export" size="small" id="TD-ContextMenu-Export">
|
||||||
<CMRowButton onClick={handleExportPNG}>PNG</CMRowButton>
|
<CMRowButton onClick={handleExportPNG} id="TD-ContextMenu-Export-PNG">
|
||||||
<CMRowButton onClick={handleExportJPG}>JPG</CMRowButton>
|
PNG
|
||||||
<CMRowButton onClick={handleExportWEBP}>WEBP</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleExportSVG}>SVG</CMRowButton>
|
<CMRowButton onClick={handleExportJPG} id="TD-ContextMenu-Export-JPG">
|
||||||
<CMRowButton onClick={handleExportJSON}>JSON</CMRowButton>
|
JPG
|
||||||
|
</CMRowButton>
|
||||||
|
<CMRowButton onClick={handleExportWEBP} id="TD-ContextMenu-Export-WEBP">
|
||||||
|
WEBP
|
||||||
|
</CMRowButton>
|
||||||
|
<CMRowButton onClick={handleExportSVG} id="TD-ContextMenu-Export-SVG">
|
||||||
|
SVG
|
||||||
|
</CMRowButton>
|
||||||
|
<CMRowButton onClick={handleExportJSON} id="TD-ContextMenu-Export-JSON">
|
||||||
|
JSON
|
||||||
|
</CMRowButton>
|
||||||
<Divider />
|
<Divider />
|
||||||
<CMRowButton onClick={handleCopySvg} kbd="#⇧C">
|
<CMRowButton
|
||||||
|
onClick={handleCopySvg}
|
||||||
|
kbd="#⇧C"
|
||||||
|
id="TD-ContextMenu-Export-Copy_as_SVG"
|
||||||
|
>
|
||||||
Copy as SVG
|
Copy as SVG
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
{isDebugMode && <CMRowButton onClick={handleCopyJson}>Copy as JSON</CMRowButton>}
|
{isDebugMode && (
|
||||||
|
<CMRowButton onClick={handleCopyJson} id="TD-ContextMenu-Export-Copy_as_JSON">
|
||||||
|
Copy as JSON
|
||||||
|
</CMRowButton>
|
||||||
|
)}
|
||||||
</ContextMenuSubMenu>
|
</ContextMenuSubMenu>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<CMRowButton onClick={handleCopySvg} kbd="#⇧C">
|
<CMRowButton
|
||||||
|
onClick={handleCopySvg}
|
||||||
|
kbd="#⇧C"
|
||||||
|
id="TD-ContextMenu-Export-Copy_as_SVG"
|
||||||
|
>
|
||||||
Copy as SVG
|
Copy as SVG
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
{isDebugMode && <CMRowButton onClick={handleCopyJson}>Copy as JSON</CMRowButton>}
|
{isDebugMode && (
|
||||||
|
<CMRowButton onClick={handleCopyJson} id="TD-ContextMenu-Export-Copy_as_JSON">
|
||||||
|
Copy as JSON
|
||||||
|
</CMRowButton>
|
||||||
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<Divider />
|
<Divider />
|
||||||
<CMRowButton onClick={handleCut} kbd="#X">
|
<CMRowButton onClick={handleCut} kbd="#X" id="TD-ContextMenu-Cut">
|
||||||
Cut
|
Cut
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleCopy} kbd="#C">
|
<CMRowButton onClick={handleCopy} kbd="#C" id="TD-ContextMenu-Copy">
|
||||||
Copy
|
Copy
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handlePaste} kbd="#V">
|
<CMRowButton onClick={handlePaste} kbd="#V" id="TD-ContextMenu-Paste">
|
||||||
Paste
|
Paste
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
<CMRowButton onClick={handleDelete} kbd="⌫">
|
<CMRowButton onClick={handleDelete} kbd="⌫" id="TD-ContextMenu-Delete">
|
||||||
Delete
|
Delete
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<CMRowButton onClick={handlePaste} kbd="#V">
|
<CMRowButton onClick={handlePaste} kbd="#V" id="TD-ContextMenu-Paste">
|
||||||
Paste
|
Paste
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleUndo} kbd="#Z">
|
<CMRowButton onClick={handleUndo} kbd="#Z" id="TD-ContextMenu-Undo">
|
||||||
Undo
|
Undo
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
<CMRowButton onClick={handleRedo} kbd="#⇧Z">
|
<CMRowButton onClick={handleRedo} kbd="#⇧Z" id="TD-ContextMenu-Redo">
|
||||||
Redo
|
Redo
|
||||||
</CMRowButton>
|
</CMRowButton>
|
||||||
</>
|
</>
|
||||||
|
@ -318,41 +348,60 @@ function AlignDistributeSubMenu({
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<span id="TD-ContextMenu-Align_Duplicate">
|
||||||
<RadixContextMenu.Root dir="ltr">
|
<RadixContextMenu.Root dir="ltr">
|
||||||
<CMTriggerButton isSubmenu>Align / Distribute</CMTriggerButton>
|
<CMTriggerButton isSubmenu>Align / Distribute</CMTriggerButton>
|
||||||
<RadixContextMenu.Content asChild sideOffset={2} alignOffset={-2}>
|
<RadixContextMenu.Content asChild sideOffset={2} alignOffset={-2}>
|
||||||
<StyledGridContent numberOfSelected={hasThreeOrMore ? 'threeOrMore' : 'twoOrMore'}>
|
<StyledGridContent numberOfSelected={hasThreeOrMore ? 'threeOrMore' : 'twoOrMore'}>
|
||||||
<CMIconButton onClick={alignLeft}>
|
<CMIconButton onClick={alignLeft} id="TD-ContextMenu-Align_Duplicate-AlignLeft">
|
||||||
<AlignLeftIcon />
|
<AlignLeftIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={alignCenterHorizontal}>
|
<CMIconButton
|
||||||
|
onClick={alignCenterHorizontal}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-AlignCenterHorizontal"
|
||||||
|
>
|
||||||
<AlignCenterHorizontallyIcon />
|
<AlignCenterHorizontallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={alignRight}>
|
<CMIconButton onClick={alignRight} id="TD-ContextMenu-Align_Duplicate-AlignRight">
|
||||||
<AlignRightIcon />
|
<AlignRightIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={stretchHorizontally}>
|
<CMIconButton
|
||||||
|
onClick={stretchHorizontally}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-StretchHorizontal"
|
||||||
|
>
|
||||||
<StretchHorizontallyIcon />
|
<StretchHorizontallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
{hasThreeOrMore && (
|
{hasThreeOrMore && (
|
||||||
<CMIconButton onClick={distributeHorizontally}>
|
<CMIconButton
|
||||||
|
onClick={distributeHorizontally}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-SpaceEvenlyHorizontal"
|
||||||
|
>
|
||||||
<SpaceEvenlyHorizontallyIcon />
|
<SpaceEvenlyHorizontallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
)}
|
)}
|
||||||
<CMIconButton onClick={alignTop}>
|
<CMIconButton onClick={alignTop} id="TD-ContextMenu-Align_Duplicate-AlignTop">
|
||||||
<AlignTopIcon />
|
<AlignTopIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={alignCenterVertical}>
|
<CMIconButton
|
||||||
|
onClick={alignCenterVertical}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-AlignCenterVertical"
|
||||||
|
>
|
||||||
<AlignCenterVerticallyIcon />
|
<AlignCenterVerticallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={alignBottom}>
|
<CMIconButton onClick={alignBottom} id="TD-ContextMenu-Align_Duplicate-AlignBottom">
|
||||||
<AlignBottomIcon />
|
<AlignBottomIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
<CMIconButton onClick={stretchVertically}>
|
<CMIconButton
|
||||||
|
onClick={stretchVertically}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-StretchVertical"
|
||||||
|
>
|
||||||
<StretchVerticallyIcon />
|
<StretchVerticallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
{hasThreeOrMore && (
|
{hasThreeOrMore && (
|
||||||
<CMIconButton onClick={distributeVertically}>
|
<CMIconButton
|
||||||
|
onClick={distributeVertically}
|
||||||
|
id="TD-ContextMenu-Align_Duplicate-SpaceEvenlyVertical"
|
||||||
|
>
|
||||||
<SpaceEvenlyVerticallyIcon />
|
<SpaceEvenlyVerticallyIcon />
|
||||||
</CMIconButton>
|
</CMIconButton>
|
||||||
)}
|
)}
|
||||||
|
@ -360,6 +409,7 @@ function AlignDistributeSubMenu({
|
||||||
</StyledGridContent>
|
</StyledGridContent>
|
||||||
</RadixContextMenu.Content>
|
</RadixContextMenu.Content>
|
||||||
</RadixContextMenu.Root>
|
</RadixContextMenu.Root>
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,14 +470,17 @@ export interface ContextMenuSubMenuProps {
|
||||||
label: string
|
label: string
|
||||||
size?: 'small'
|
size?: 'small'
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ContextMenuSubMenu({
|
export function ContextMenuSubMenu({
|
||||||
children,
|
children,
|
||||||
label,
|
label,
|
||||||
size,
|
size,
|
||||||
|
id,
|
||||||
}: ContextMenuSubMenuProps): JSX.Element {
|
}: ContextMenuSubMenuProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
<span id={id}>
|
||||||
<RadixContextMenu.Root dir="ltr">
|
<RadixContextMenu.Root dir="ltr">
|
||||||
<CMTriggerButton isSubmenu>{label}</CMTriggerButton>
|
<CMTriggerButton isSubmenu>{label}</CMTriggerButton>
|
||||||
<RadixContextMenu.Content dir="ltr" sideOffset={2} alignOffset={-2} asChild>
|
<RadixContextMenu.Content dir="ltr" sideOffset={2} alignOffset={-2} asChild>
|
||||||
|
@ -437,6 +490,7 @@ export function ContextMenuSubMenu({
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
</RadixContextMenu.Content>
|
</RadixContextMenu.Content>
|
||||||
</RadixContextMenu.Root>
|
</RadixContextMenu.Root>
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,9 +512,9 @@ function CMIconButton({ onSelect, ...rest }: ToolButtonProps): JSX.Element {
|
||||||
|
|
||||||
/* -------------------- RowButton ------------------- */
|
/* -------------------- RowButton ------------------- */
|
||||||
|
|
||||||
const CMRowButton = ({ ...rest }: RowButtonProps) => {
|
const CMRowButton = ({ id, ...rest }: RowButtonProps) => {
|
||||||
return (
|
return (
|
||||||
<RadixContextMenu.ContextMenuItem asChild>
|
<RadixContextMenu.ContextMenuItem asChild id={id}>
|
||||||
<RowButton {...rest} />
|
<RowButton {...rest} />
|
||||||
</RadixContextMenu.ContextMenuItem>
|
</RadixContextMenu.ContextMenuItem>
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,6 +10,7 @@ interface DMCheckboxItemProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
variant?: RowButtonProps['variant']
|
variant?: RowButtonProps['variant']
|
||||||
kbd?: string
|
kbd?: string
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DMCheckboxItem({
|
export function DMCheckboxItem({
|
||||||
|
@ -18,6 +19,7 @@ export function DMCheckboxItem({
|
||||||
variant,
|
variant,
|
||||||
onCheckedChange,
|
onCheckedChange,
|
||||||
kbd,
|
kbd,
|
||||||
|
id,
|
||||||
children,
|
children,
|
||||||
}: DMCheckboxItemProps): JSX.Element {
|
}: DMCheckboxItemProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
@ -28,6 +30,7 @@ export function DMCheckboxItem({
|
||||||
checked={checked}
|
checked={checked}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
asChild
|
asChild
|
||||||
|
id={id}
|
||||||
>
|
>
|
||||||
<RowButton kbd={kbd} variant={variant} hasIndicator>
|
<RowButton kbd={kbd} variant={variant} hasIndicator>
|
||||||
{children}
|
{children}
|
||||||
|
|
|
@ -9,6 +9,7 @@ export interface DMContentProps {
|
||||||
align?: 'start' | 'center' | 'end'
|
align?: 'start' | 'center' | 'end'
|
||||||
sideOffset?: number
|
sideOffset?: number
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DMContent({
|
export function DMContent({
|
||||||
|
@ -16,6 +17,7 @@ export function DMContent({
|
||||||
children,
|
children,
|
||||||
align,
|
align,
|
||||||
variant,
|
variant,
|
||||||
|
id,
|
||||||
}: DMContentProps): JSX.Element {
|
}: DMContentProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Content
|
<Content
|
||||||
|
@ -24,6 +26,7 @@ export function DMContent({
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
onEscapeKeyDown={stopPropagation}
|
onEscapeKeyDown={stopPropagation}
|
||||||
asChild
|
asChild
|
||||||
|
id={id}
|
||||||
>
|
>
|
||||||
<StyledContent variant={variant}>{children}</StyledContent>
|
<StyledContent variant={variant}>{children}</StyledContent>
|
||||||
</Content>
|
</Content>
|
||||||
|
|
|
@ -4,10 +4,11 @@ import { RowButton, RowButtonProps } from '~components/Primitives/RowButton'
|
||||||
|
|
||||||
export function DMItem({
|
export function DMItem({
|
||||||
onSelect,
|
onSelect,
|
||||||
|
id,
|
||||||
...rest
|
...rest
|
||||||
}: RowButtonProps & { onSelect?: (event: Event) => void }): JSX.Element {
|
}: RowButtonProps & { onSelect?: (event: Event) => void; id?: string }): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Item dir="ltr" asChild onSelect={onSelect}>
|
<Item dir="ltr" asChild onSelect={onSelect} id={id}>
|
||||||
<RowButton {...rest} />
|
<RowButton {...rest} />
|
||||||
</Item>
|
</Item>
|
||||||
)
|
)
|
||||||
|
|
|
@ -8,6 +8,7 @@ export interface DMSubMenuProps {
|
||||||
size?: 'small'
|
size?: 'small'
|
||||||
disabled?: boolean
|
disabled?: boolean
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DMSubMenu({
|
export function DMSubMenu({
|
||||||
|
@ -15,8 +16,10 @@ export function DMSubMenu({
|
||||||
size,
|
size,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
label,
|
label,
|
||||||
|
id,
|
||||||
}: DMSubMenuProps): JSX.Element {
|
}: DMSubMenuProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
<span id={id}>
|
||||||
<Root dir="ltr">
|
<Root dir="ltr">
|
||||||
<TriggerItem dir="ltr" asChild>
|
<TriggerItem dir="ltr" asChild>
|
||||||
<RowButton disabled={disabled} hasArrow>
|
<RowButton disabled={disabled} hasArrow>
|
||||||
|
@ -30,5 +33,6 @@ export function DMSubMenu({
|
||||||
</MenuContent>
|
</MenuContent>
|
||||||
</Content>
|
</Content>
|
||||||
</Root>
|
</Root>
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,11 +4,12 @@ import { ToolButton, ToolButtonProps } from '~components/Primitives/ToolButton'
|
||||||
|
|
||||||
interface DMTriggerIconProps extends ToolButtonProps {
|
interface DMTriggerIconProps extends ToolButtonProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DMTriggerIcon({ children, ...rest }: DMTriggerIconProps) {
|
export function DMTriggerIcon({ id, children, ...rest }: DMTriggerIconProps) {
|
||||||
return (
|
return (
|
||||||
<Trigger asChild>
|
<Trigger asChild id={id}>
|
||||||
<ToolButton {...rest}>{children}</ToolButton>
|
<ToolButton {...rest}>{children}</ToolButton>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
)
|
)
|
||||||
|
|
|
@ -17,6 +17,7 @@ export interface RowButtonProps {
|
||||||
isWarning?: boolean
|
isWarning?: boolean
|
||||||
hasIndicator?: boolean
|
hasIndicator?: boolean
|
||||||
hasArrow?: boolean
|
hasArrow?: boolean
|
||||||
|
id?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RowButton = React.forwardRef<HTMLButtonElement, RowButtonProps>(
|
export const RowButton = React.forwardRef<HTMLButtonElement, RowButtonProps>(
|
||||||
|
|
|
@ -14,6 +14,7 @@ export interface ToolButtonProps {
|
||||||
isToolLocked?: boolean
|
isToolLocked?: boolean
|
||||||
variant?: 'icon' | 'text' | 'circle' | 'primary'
|
variant?: 'icon' | 'text' | 'circle' | 'primary'
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
|
id?: string
|
||||||
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>
|
onKeyDown?: React.KeyboardEventHandler<HTMLButtonElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +31,7 @@ export const ToolButton = React.forwardRef<HTMLButtonElement, ToolButtonProps>(
|
||||||
isActive = false,
|
isActive = false,
|
||||||
isSponsor = false,
|
isSponsor = false,
|
||||||
onKeyDown,
|
onKeyDown,
|
||||||
|
id,
|
||||||
...rest
|
...rest
|
||||||
},
|
},
|
||||||
ref
|
ref
|
||||||
|
@ -46,6 +48,7 @@ export const ToolButton = React.forwardRef<HTMLButtonElement, ToolButtonProps>(
|
||||||
onDoubleClick={onDoubleClick}
|
onDoubleClick={onDoubleClick}
|
||||||
onKeyDown={onKeyDown}
|
onKeyDown={onKeyDown}
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
|
id={id}
|
||||||
{...rest}
|
{...rest}
|
||||||
>
|
>
|
||||||
<StyledToolButtonInner>{children}</StyledToolButtonInner>
|
<StyledToolButtonInner>{children}</StyledToolButtonInner>
|
||||||
|
|
|
@ -11,6 +11,7 @@ interface TooltipProps {
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
label: string
|
label: string
|
||||||
kbd?: string
|
kbd?: string
|
||||||
|
id?: string
|
||||||
side?: 'bottom' | 'left' | 'right' | 'top'
|
side?: 'bottom' | 'left' | 'right' | 'top'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,9 +19,11 @@ export function Tooltip({
|
||||||
children,
|
children,
|
||||||
label,
|
label,
|
||||||
kbd: kbdProp,
|
kbd: kbdProp,
|
||||||
|
id,
|
||||||
side = 'top',
|
side = 'top',
|
||||||
}: TooltipProps): JSX.Element {
|
}: TooltipProps): JSX.Element {
|
||||||
return (
|
return (
|
||||||
|
<span id={id}>
|
||||||
<RadixTooltip.Root>
|
<RadixTooltip.Root>
|
||||||
<RadixTooltip.Trigger dir="ltr" asChild={true}>
|
<RadixTooltip.Trigger dir="ltr" asChild={true}>
|
||||||
<span>{children}</span>
|
<span>{children}</span>
|
||||||
|
@ -31,6 +34,7 @@ export function Tooltip({
|
||||||
<StyledArrow />
|
<StyledArrow />
|
||||||
</StyledContent>
|
</StyledContent>
|
||||||
</RadixTooltip.Root>
|
</RadixTooltip.Root>
|
||||||
|
</span>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ export function ActionButton(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr" onOpenChange={handleMenuOpenChange}>
|
<DropdownMenu.Root dir="ltr" onOpenChange={handleMenuOpenChange}>
|
||||||
<DropdownMenu.Trigger dir="ltr" asChild>
|
<DropdownMenu.Trigger dir="ltr" asChild id="TD-Tools-Dots">
|
||||||
<ToolButton variant="circle">
|
<ToolButton variant="circle">
|
||||||
<DotsHorizontalIcon />
|
<DotsHorizontalIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
|
@ -189,22 +189,22 @@ export function ActionButton(): JSX.Element {
|
||||||
<>
|
<>
|
||||||
<ButtonsRow>
|
<ButtonsRow>
|
||||||
<ToolButton variant="icon" disabled={!hasSelection} onClick={handleDuplicate}>
|
<ToolButton variant="icon" disabled={!hasSelection} onClick={handleDuplicate}>
|
||||||
<Tooltip label="Duplicate" kbd={`#D`}>
|
<Tooltip label="Duplicate" kbd={`#D`} id="TD-Tools-Copy">
|
||||||
<CopyIcon />
|
<CopyIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleRotate}>
|
<ToolButton disabled={!hasSelection} onClick={handleRotate}>
|
||||||
<Tooltip label="Rotate">
|
<Tooltip label="Rotate" id="TD-Tools-Rotate">
|
||||||
<RotateCounterClockwiseIcon />
|
<RotateCounterClockwiseIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleToggleLocked}>
|
<ToolButton disabled={!hasSelection} onClick={handleToggleLocked}>
|
||||||
<Tooltip label="Toggle Locked" kbd={`#L`}>
|
<Tooltip label="Toggle Locked" kbd={`#L`} id="TD-Tools-Lock">
|
||||||
{isAllLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
{isAllLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleToggleAspectRatio}>
|
<ToolButton disabled={!hasSelection} onClick={handleToggleAspectRatio}>
|
||||||
<Tooltip label="Toggle Aspect Ratio Lock">
|
<Tooltip label="Toggle Aspect Ratio Lock" id="TD-Tools-AspectRatio">
|
||||||
{isAllAspectLocked ? <AspectRatioIcon /> : <BoxIcon />}
|
{isAllAspectLocked ? <AspectRatioIcon /> : <BoxIcon />}
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
|
@ -212,70 +212,94 @@ export function ActionButton(): JSX.Element {
|
||||||
disabled={!hasSelection || (!isAllGrouped && !hasMultipleSelection)}
|
disabled={!hasSelection || (!isAllGrouped && !hasMultipleSelection)}
|
||||||
onClick={handleGroup}
|
onClick={handleGroup}
|
||||||
>
|
>
|
||||||
<Tooltip label="Group" kbd={`#G`}>
|
<Tooltip label="Group" kbd={`#G`} id="TD-Tools-Group">
|
||||||
<GroupIcon />
|
<GroupIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
</ButtonsRow>
|
</ButtonsRow>
|
||||||
<ButtonsRow>
|
<ButtonsRow>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleMoveToBack}>
|
<ToolButton disabled={!hasSelection} onClick={handleMoveToBack}>
|
||||||
<Tooltip label="Move to Back" kbd={`#⇧[`}>
|
<Tooltip label="Move to Back" kbd={`#⇧[`} id="TD-Tools-PinBottom">
|
||||||
<PinBottomIcon />
|
<PinBottomIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleMoveBackward}>
|
<ToolButton disabled={!hasSelection} onClick={handleMoveBackward}>
|
||||||
<Tooltip label="Move Backward" kbd={`#[`}>
|
<Tooltip label="Move Backward" kbd={`#[`} id="TD-Tools-ArrowDown">
|
||||||
<ArrowDownIcon />
|
<ArrowDownIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleMoveForward}>
|
<ToolButton disabled={!hasSelection} onClick={handleMoveForward}>
|
||||||
<Tooltip label="Move Forward" kbd={`#]`}>
|
<Tooltip label="Move Forward" kbd={`#]`} id="TD-Tools-ArrowUp">
|
||||||
<ArrowUpIcon />
|
<ArrowUpIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleMoveToFront}>
|
<ToolButton disabled={!hasSelection} onClick={handleMoveToFront}>
|
||||||
<Tooltip label="Move to Front" kbd={`#⇧]`}>
|
<Tooltip label="Move to Front" kbd={`#⇧]`} id="TD-Tools-PinTop">
|
||||||
<PinTopIcon />
|
<PinTopIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasSelection} onClick={handleResetAngle}>
|
<ToolButton disabled={!hasSelection} onClick={handleResetAngle}>
|
||||||
<Tooltip label="Reset Angle">
|
<Tooltip label="Reset Angle" id="TD-Tools-ResetAngle">
|
||||||
<AngleIcon />
|
<AngleIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
</ButtonsRow>
|
</ButtonsRow>
|
||||||
<Divider />
|
<Divider />
|
||||||
<ButtonsRow>
|
<ButtonsRow>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignLeft}>
|
<ToolButton disabled={!hasTwoOrMore} onClick={alignLeft} id="TD-Tools-AlignLeft">
|
||||||
<AlignLeftIcon />
|
<AlignLeftIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignCenterHorizontal}>
|
<ToolButton
|
||||||
|
disabled={!hasTwoOrMore}
|
||||||
|
onClick={alignCenterHorizontal}
|
||||||
|
id="TD-Tools-AlignCenterHorizontal"
|
||||||
|
>
|
||||||
<AlignCenterHorizontallyIcon />
|
<AlignCenterHorizontallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignRight}>
|
<ToolButton disabled={!hasTwoOrMore} onClick={alignRight} id="TD-Tools-AlignRight">
|
||||||
<AlignRightIcon />
|
<AlignRightIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={stretchHorizontally}>
|
<ToolButton
|
||||||
|
disabled={!hasTwoOrMore}
|
||||||
|
onClick={stretchHorizontally}
|
||||||
|
id="TD-Tools-StretchHorizontal"
|
||||||
|
>
|
||||||
<StretchHorizontallyIcon />
|
<StretchHorizontallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasThreeOrMore} onClick={distributeHorizontally}>
|
<ToolButton
|
||||||
|
disabled={!hasThreeOrMore}
|
||||||
|
onClick={distributeHorizontally}
|
||||||
|
id="TD-Tools-SpaceEvenlyHorizontal"
|
||||||
|
>
|
||||||
<SpaceEvenlyHorizontallyIcon />
|
<SpaceEvenlyHorizontallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
</ButtonsRow>
|
</ButtonsRow>
|
||||||
<ButtonsRow>
|
<ButtonsRow>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignTop}>
|
<ToolButton disabled={!hasTwoOrMore} onClick={alignTop} id="TD-Tools-AlignTop">
|
||||||
<AlignTopIcon />
|
<AlignTopIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignCenterVertical}>
|
<ToolButton
|
||||||
|
disabled={!hasTwoOrMore}
|
||||||
|
onClick={alignCenterVertical}
|
||||||
|
id="TD-Tools-AlignCenterVertical"
|
||||||
|
>
|
||||||
<AlignCenterVerticallyIcon />
|
<AlignCenterVerticallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={alignBottom}>
|
<ToolButton disabled={!hasTwoOrMore} onClick={alignBottom} id="TD-Tools-AlignBottom">
|
||||||
<AlignBottomIcon />
|
<AlignBottomIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasTwoOrMore} onClick={stretchVertically}>
|
<ToolButton
|
||||||
|
disabled={!hasTwoOrMore}
|
||||||
|
onClick={stretchVertically}
|
||||||
|
id="TD-Tools-tretchVertical"
|
||||||
|
>
|
||||||
<StretchVerticallyIcon />
|
<StretchVerticallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
<ToolButton disabled={!hasThreeOrMore} onClick={distributeVertically}>
|
<ToolButton
|
||||||
|
disabled={!hasThreeOrMore}
|
||||||
|
onClick={distributeVertically}
|
||||||
|
id="TD-Tools-SpaceEvenlyVertical"
|
||||||
|
>
|
||||||
<SpaceEvenlyVerticallyIcon />
|
<SpaceEvenlyVerticallyIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
</ButtonsRow>
|
</ButtonsRow>
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const BackToContent = React.memo(function BackToContent() {
|
||||||
if (!isEmptyCanvas) return null
|
if (!isEmptyCanvas) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BackToContentContainer>
|
<BackToContentContainer id="TD-Tools-Back_to_content">
|
||||||
<RowButton onClick={app.zoomToContent}>Back to content</RowButton>
|
<RowButton onClick={app.zoomToContent}>Back to content</RowButton>
|
||||||
</BackToContentContainer>
|
</BackToContentContainer>
|
||||||
)
|
)
|
||||||
|
|
|
@ -18,7 +18,7 @@ export function DeleteButton(): JSX.Element {
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label="Delete" kbd="⌫">
|
<Tooltip label="Delete" kbd="⌫" id="TD-Delete">
|
||||||
<ToolButton variant="circle" disabled={!hasSelection} onSelect={handleDelete}>
|
<ToolButton variant="circle" disabled={!hasSelection} onSelect={handleDelete}>
|
||||||
<TrashIcon />
|
<TrashIcon />
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function LockButton(): JSX.Element {
|
||||||
const isToolLocked = app.useStore(isToolLockedSelector)
|
const isToolLocked = app.useStore(isToolLockedSelector)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label="Lock Tool" kbd="7">
|
<Tooltip label="Lock Tool" kbd="7" id="TD-Lock">
|
||||||
<ToolButton variant="circle" isActive={isToolLocked} onSelect={app.toggleToolLock}>
|
<ToolButton variant="circle" isActive={isToolLocked} onSelect={app.toggleToolLock}>
|
||||||
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
|
|
|
@ -44,6 +44,7 @@ export const PenMenu = React.memo(function PenMenu({ activeTool }: ShapesMenuPro
|
||||||
onDoubleClick={handleDoubleClick}
|
onDoubleClick={handleDoubleClick}
|
||||||
onClick={selectShapeTool}
|
onClick={selectShapeTool}
|
||||||
isActive={penShapes.includes(activeTool as PenShape)}
|
isActive={penShapes.includes(activeTool as PenShape)}
|
||||||
|
id="TD-Pen"
|
||||||
>
|
>
|
||||||
{penShapeIcons[lastActiveTool]}
|
{penShapeIcons[lastActiveTool]}
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
|
@ -55,6 +56,7 @@ export const PenMenu = React.memo(function PenMenu({ activeTool }: ShapesMenuPro
|
||||||
key={shape}
|
key={shape}
|
||||||
label={shape[0].toUpperCase() + shape.slice(1)}
|
label={shape[0].toUpperCase() + shape.slice(1)}
|
||||||
kbd={(1 + i).toString()}
|
kbd={(1 + i).toString()}
|
||||||
|
id={`TD-Pen-${shape}`}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<ToolButton
|
<ToolButton
|
||||||
|
|
|
@ -48,12 +48,13 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Panel side="center">
|
<Panel side="center" id="TD-PrimaryTools">
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'1'}
|
kbd={'1'}
|
||||||
label={'select'}
|
label={'select'}
|
||||||
onClick={selectSelectTool}
|
onClick={selectSelectTool}
|
||||||
isActive={activeTool === 'select'}
|
isActive={activeTool === 'select'}
|
||||||
|
id="TD-PrimaryTools-CursorArrow"
|
||||||
>
|
>
|
||||||
<CursorArrowIcon />
|
<CursorArrowIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
@ -62,6 +63,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
label={TDShapeType.Draw}
|
label={TDShapeType.Draw}
|
||||||
onClick={selectDrawTool}
|
onClick={selectDrawTool}
|
||||||
isActive={activeTool === TDShapeType.Draw}
|
isActive={activeTool === TDShapeType.Draw}
|
||||||
|
id="TD-PrimaryTools-Pencil"
|
||||||
>
|
>
|
||||||
<Pencil1Icon />
|
<Pencil1Icon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
@ -70,6 +72,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
label={'eraser'}
|
label={'eraser'}
|
||||||
onClick={selectEraseTool}
|
onClick={selectEraseTool}
|
||||||
isActive={activeTool === 'erase'}
|
isActive={activeTool === 'erase'}
|
||||||
|
id="TD-PrimaryTools-Eraser"
|
||||||
>
|
>
|
||||||
<EraserIcon />
|
<EraserIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
@ -80,6 +83,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
onClick={selectArrowTool}
|
onClick={selectArrowTool}
|
||||||
isLocked={isToolLocked}
|
isLocked={isToolLocked}
|
||||||
isActive={activeTool === TDShapeType.Arrow}
|
isActive={activeTool === TDShapeType.Arrow}
|
||||||
|
id="TD-PrimaryTools-ArrowTopRight"
|
||||||
>
|
>
|
||||||
<ArrowTopRightIcon />
|
<ArrowTopRightIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
@ -89,6 +93,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
onClick={selectTextTool}
|
onClick={selectTextTool}
|
||||||
isLocked={isToolLocked}
|
isLocked={isToolLocked}
|
||||||
isActive={activeTool === TDShapeType.Text}
|
isActive={activeTool === TDShapeType.Text}
|
||||||
|
id="TD-PrimaryTools-Text"
|
||||||
>
|
>
|
||||||
<TextIcon />
|
<TextIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
@ -97,6 +102,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
label={TDShapeType.Sticky}
|
label={TDShapeType.Sticky}
|
||||||
onClick={selectStickyTool}
|
onClick={selectStickyTool}
|
||||||
isActive={activeTool === TDShapeType.Sticky}
|
isActive={activeTool === TDShapeType.Sticky}
|
||||||
|
id="TD-PrimaryTools-Pencil2"
|
||||||
>
|
>
|
||||||
<Pencil2Icon />
|
<Pencil2Icon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
|
|
|
@ -75,7 +75,7 @@ export const ShapesMenu = React.memo(function ShapesMenu({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr" onOpenChange={selectShapeTool}>
|
<DropdownMenu.Root dir="ltr" onOpenChange={selectShapeTool}>
|
||||||
<DropdownMenu.Trigger dir="ltr" asChild>
|
<DropdownMenu.Trigger dir="ltr" asChild id="TD-PrimaryTools-Shapes">
|
||||||
<ToolButton
|
<ToolButton
|
||||||
disabled={isActive && app.shiftKey} // otherwise this continuously opens and closes on "SpacePanning"
|
disabled={isActive && app.shiftKey} // otherwise this continuously opens and closes on "SpacePanning"
|
||||||
variant="primary"
|
variant="primary"
|
||||||
|
@ -94,6 +94,7 @@ export const ShapesMenu = React.memo(function ShapesMenu({
|
||||||
key={shape}
|
key={shape}
|
||||||
label={shape[0].toUpperCase() + shape.slice(1)}
|
label={shape[0].toUpperCase() + shape.slice(1)}
|
||||||
kbd={(4 + i).toString()}
|
kbd={(4 + i).toString()}
|
||||||
|
id={`TD-PrimaryTools-Shapes-${shape}`}
|
||||||
>
|
>
|
||||||
<DropdownMenu.Item asChild>
|
<DropdownMenu.Item asChild>
|
||||||
<ToolButton
|
<ToolButton
|
||||||
|
|
|
@ -13,7 +13,7 @@ export function StatusBar(): JSX.Element | null {
|
||||||
const activeTool = app.useStore(activeToolSelector)
|
const activeTool = app.useStore(activeToolSelector)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledStatusBar bp={breakpoints}>
|
<StyledStatusBar bp={breakpoints} id="TD-StatusBar">
|
||||||
<StyledSection>
|
<StyledSection>
|
||||||
{activeTool} | {status}
|
{activeTool} | {status}
|
||||||
</StyledSection>
|
</StyledSection>
|
||||||
|
|
|
@ -20,7 +20,7 @@ export const ToolsPanel = React.memo(function ToolsPanel({ onBlur }: ToolsPanelP
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledToolsPanelContainer onBlur={onBlur}>
|
<StyledToolsPanelContainer onBlur={onBlur}>
|
||||||
<StyledCenterWrap>
|
<StyledCenterWrap id="TD-Tools">
|
||||||
<BackToContent />
|
<BackToContent />
|
||||||
<StyledPrimaryTools>
|
<StyledPrimaryTools>
|
||||||
<ActionButton />
|
<ActionButton />
|
||||||
|
|
|
@ -121,48 +121,58 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr">
|
<DropdownMenu.Root dir="ltr">
|
||||||
<DMTriggerIcon isSponsor={showSponsorLink}>
|
<DMTriggerIcon isSponsor={showSponsorLink} id="TD-MenuIcon">
|
||||||
<HamburgerMenuIcon />
|
<HamburgerMenuIcon />
|
||||||
</DMTriggerIcon>
|
</DMTriggerIcon>
|
||||||
<DMContent variant="menu">
|
<DMContent variant="menu" id="TD-Menu">
|
||||||
{showFileMenu && (
|
{showFileMenu && (
|
||||||
<DMSubMenu label="File...">
|
<DMSubMenu label="File..." id="TD-MenuItem-File">
|
||||||
{app.callbacks.onNewProject && (
|
{app.callbacks.onNewProject && (
|
||||||
<DMItem onClick={onNewProject} kbd="#N">
|
<DMItem onClick={onNewProject} kbd="#N" id="TD-MenuItem-File-New_Project">
|
||||||
New Project
|
New Project
|
||||||
</DMItem>
|
</DMItem>
|
||||||
)}
|
)}
|
||||||
{app.callbacks.onOpenProject && (
|
{app.callbacks.onOpenProject && (
|
||||||
<DMItem onClick={onOpenProject} kbd="#O">
|
<DMItem onClick={onOpenProject} kbd="#O" id="TD-MenuItem-File-Open">
|
||||||
Open...
|
Open...
|
||||||
</DMItem>
|
</DMItem>
|
||||||
)}
|
)}
|
||||||
{app.callbacks.onSaveProject && (
|
{app.callbacks.onSaveProject && (
|
||||||
<DMItem onClick={onSaveProject} kbd="#S">
|
<DMItem onClick={onSaveProject} kbd="#S" id="TD-MenuItem-File-Save">
|
||||||
Save
|
Save
|
||||||
</DMItem>
|
</DMItem>
|
||||||
)}
|
)}
|
||||||
{app.callbacks.onSaveProjectAs && (
|
{app.callbacks.onSaveProjectAs && (
|
||||||
<DMItem onClick={onSaveProjectAs} kbd="#⇧S">
|
<DMItem onClick={onSaveProjectAs} kbd="#⇧S" id="TD-MenuItem-File-Save_As">
|
||||||
Save As...
|
Save As...
|
||||||
</DMItem>
|
</DMItem>
|
||||||
)}
|
)}
|
||||||
{app.callbacks.onExport && (
|
{app.callbacks.onExport && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<DMSubMenu label="Export" size="small">
|
<DMSubMenu label="Export" size="small" id="TD-MenuItem-File-Export">
|
||||||
<DMItem onClick={handleExportPNG}>PNG</DMItem>
|
<DMItem onClick={handleExportPNG} id="TD-MenuItem-File-Export-PNG">
|
||||||
<DMItem onClick={handleExportJPG}>JPG</DMItem>
|
PNG
|
||||||
<DMItem onClick={handleExportWEBP}>WEBP</DMItem>
|
</DMItem>
|
||||||
<DMItem onClick={handleExportSVG}>SVG</DMItem>
|
<DMItem onClick={handleExportJPG} id="TD-MenuItem-File-Export-JPG">
|
||||||
<DMItem onClick={handleExportJSON}>JSON</DMItem>
|
JPG
|
||||||
|
</DMItem>
|
||||||
|
<DMItem onClick={handleExportWEBP} id="TD-MenuItem-File-Export-WEBP">
|
||||||
|
WEBP
|
||||||
|
</DMItem>
|
||||||
|
<DMItem onClick={handleExportSVG} id="TD-MenuItem-File-Export-SVG">
|
||||||
|
SVG
|
||||||
|
</DMItem>
|
||||||
|
<DMItem onClick={handleExportJSON} id="TD-MenuItem-File-Export-JSON">
|
||||||
|
JSON
|
||||||
|
</DMItem>
|
||||||
</DMSubMenu>
|
</DMSubMenu>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{!disableAssets && (
|
{!disableAssets && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<DMItem onClick={handleUploadMedia} kbd="#U">
|
<DMItem onClick={handleUploadMedia} kbd="#U" id="TD-MenuItem-File-Upload_Media">
|
||||||
Upload Media
|
Upload Media
|
||||||
</DMItem>
|
</DMItem>
|
||||||
</>
|
</>
|
||||||
|
@ -171,15 +181,31 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
)}
|
)}
|
||||||
{!readOnly && (
|
{!readOnly && (
|
||||||
<>
|
<>
|
||||||
<DMSubMenu label="Edit...">
|
<DMSubMenu label="Edit..." id="TD-MenuItem-Edit">
|
||||||
<DMItem onSelect={preventEvent} onClick={app.undo} kbd="#Z">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={app.undo}
|
||||||
|
kbd="#Z"
|
||||||
|
id="TD-MenuItem-Edit-Undo"
|
||||||
|
>
|
||||||
Undo
|
Undo
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={app.redo} kbd="#⇧Z">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={app.redo}
|
||||||
|
kbd="#⇧Z"
|
||||||
|
id="TD-MenuItem-Edit-Redo"
|
||||||
|
>
|
||||||
Redo
|
Redo
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMDivider dir="ltr" />
|
<DMDivider dir="ltr" />
|
||||||
<DMItem onSelect={preventEvent} disabled={!hasSelection} onClick={handleCut} kbd="#X">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
disabled={!hasSelection}
|
||||||
|
onClick={handleCut}
|
||||||
|
kbd="#X"
|
||||||
|
id="TD-MenuItem-Edit-Cut"
|
||||||
|
>
|
||||||
Cut
|
Cut
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem
|
<DMItem
|
||||||
|
@ -187,10 +213,16 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
disabled={!hasSelection}
|
disabled={!hasSelection}
|
||||||
onClick={handleCopy}
|
onClick={handleCopy}
|
||||||
kbd="#C"
|
kbd="#C"
|
||||||
|
id="TD-MenuItem-Edit-Copy"
|
||||||
>
|
>
|
||||||
Copy
|
Copy
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={handlePaste} kbd="#V">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={handlePaste}
|
||||||
|
kbd="#V"
|
||||||
|
id="TD-MenuItem-Edit-Paste"
|
||||||
|
>
|
||||||
Paste
|
Paste
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMDivider dir="ltr" />
|
<DMDivider dir="ltr" />
|
||||||
|
@ -199,30 +231,45 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
disabled={!hasSelection}
|
disabled={!hasSelection}
|
||||||
onClick={handleCopySvg}
|
onClick={handleCopySvg}
|
||||||
kbd="#⇧C"
|
kbd="#⇧C"
|
||||||
|
id="TD-MenuItem-Edit-Copy_as_SVG"
|
||||||
>
|
>
|
||||||
Copy as SVG
|
Copy as SVG
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} disabled={!hasSelection} onClick={handleCopyJson}>
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
disabled={!hasSelection}
|
||||||
|
onClick={handleCopyJson}
|
||||||
|
id="TD-MenuItem-Edit-Copy_as_JSON"
|
||||||
|
>
|
||||||
Copy as JSON
|
Copy as JSON
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMDivider dir="ltr" />
|
<DMDivider dir="ltr" />
|
||||||
<DMItem onSelect={preventEvent} onClick={handleSelectAll} kbd="#A">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={handleSelectAll}
|
||||||
|
kbd="#A"
|
||||||
|
id="TD-MenuItem-Select_All"
|
||||||
|
>
|
||||||
Select All
|
Select All
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={handleSelectNone}>
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={handleSelectNone}
|
||||||
|
id="TD-MenuItem-Select_None"
|
||||||
|
>
|
||||||
Select None
|
Select None
|
||||||
</DMItem>
|
</DMItem>
|
||||||
</DMSubMenu>
|
</DMSubMenu>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<a href="https://tldraw.com/r">
|
<a href="https://tldraw.com/r">
|
||||||
<DMItem>Create a Multiplayer Room</DMItem>
|
<DMItem id="TD-MenuItem-Create_a_Multiplayer_Room">Create a Multiplayer Room</DMItem>
|
||||||
</a>
|
</a>
|
||||||
<DMDivider dir="ltr" />
|
<DMDivider dir="ltr" />
|
||||||
<PreferencesMenu />
|
<PreferencesMenu />
|
||||||
<DMDivider dir="ltr" />
|
<DMDivider dir="ltr" />
|
||||||
<a href="https://github.com/Tldraw/Tldraw" target="_blank" rel="nofollow">
|
<a href="https://github.com/Tldraw/Tldraw" target="_blank" rel="nofollow">
|
||||||
<DMItem>
|
<DMItem id="TD-MenuItem-Github">
|
||||||
GitHub
|
GitHub
|
||||||
<SmallIcon>
|
<SmallIcon>
|
||||||
<GitHubLogoIcon />
|
<GitHubLogoIcon />
|
||||||
|
@ -230,7 +277,7 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
</DMItem>
|
</DMItem>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://twitter.com/Tldraw" target="_blank" rel="nofollow">
|
<a href="https://twitter.com/Tldraw" target="_blank" rel="nofollow">
|
||||||
<DMItem>
|
<DMItem id="TD-MenuItem-Twitter">
|
||||||
Twitter
|
Twitter
|
||||||
<SmallIcon>
|
<SmallIcon>
|
||||||
<TwitterLogoIcon />
|
<TwitterLogoIcon />
|
||||||
|
@ -238,7 +285,7 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
</DMItem>
|
</DMItem>
|
||||||
</a>
|
</a>
|
||||||
<a href="https://discord.gg/SBBEVCA4PG" target="_blank" rel="nofollow">
|
<a href="https://discord.gg/SBBEVCA4PG" target="_blank" rel="nofollow">
|
||||||
<DMItem>
|
<DMItem id="TD-MenuItem-Discord">
|
||||||
Discord
|
Discord
|
||||||
<SmallIcon>
|
<SmallIcon>
|
||||||
<DiscordIcon />
|
<DiscordIcon />
|
||||||
|
@ -247,7 +294,7 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
</a>
|
</a>
|
||||||
{showSponsorLink && (
|
{showSponsorLink && (
|
||||||
<a href="https://github.com/sponsors/steveruizok" target="_blank" rel="nofollow">
|
<a href="https://github.com/sponsors/steveruizok" target="_blank" rel="nofollow">
|
||||||
<DMItem isSponsor>
|
<DMItem isSponsor id="TD-MenuItem-Become_a_Sponsor">
|
||||||
Become a Sponsor{' '}
|
Become a Sponsor{' '}
|
||||||
<SmallIcon>
|
<SmallIcon>
|
||||||
<HeartIcon />
|
<HeartIcon />
|
||||||
|
@ -258,9 +305,13 @@ export const Menu = React.memo(function Menu({ showSponsorLink, readOnly }: Menu
|
||||||
{showSignInOutMenu && (
|
{showSignInOutMenu && (
|
||||||
<>
|
<>
|
||||||
<DMDivider dir="ltr" />{' '}
|
<DMDivider dir="ltr" />{' '}
|
||||||
{app.callbacks.onSignIn && <DMItem onSelect={handleSignIn}>Sign In</DMItem>}
|
{app.callbacks.onSignIn && (
|
||||||
|
<DMItem onSelect={handleSignIn} id="TD-MenuItem-Sign_in">
|
||||||
|
Sign In
|
||||||
|
</DMItem>
|
||||||
|
)}
|
||||||
{app.callbacks.onSignOut && (
|
{app.callbacks.onSignOut && (
|
||||||
<DMItem onSelect={handleSignOut}>
|
<DMItem onSelect={handleSignOut} id="TD-MenuItem-Sign_out">
|
||||||
Sign Out
|
Sign Out
|
||||||
<SmallIcon>
|
<SmallIcon>
|
||||||
<ExitIcon />
|
<ExitIcon />
|
||||||
|
|
|
@ -47,7 +47,7 @@ export function PageMenu(): JSX.Element {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr" open={isOpen} onOpenChange={handleOpenChange}>
|
<DropdownMenu.Root dir="ltr" open={isOpen} onOpenChange={handleOpenChange}>
|
||||||
<DropdownMenu.Trigger dir="ltr" asChild>
|
<DropdownMenu.Trigger dir="ltr" asChild id="TD-Page">
|
||||||
<ToolButton variant="text">{currentPageName || 'Page'}</ToolButton>
|
<ToolButton variant="text">{currentPageName || 'Page'}</ToolButton>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DMContent variant="menu" align="start">
|
<DMContent variant="menu" align="start">
|
||||||
|
|
|
@ -43,37 +43,65 @@ export function PreferencesMenu() {
|
||||||
}, [app])
|
}, [app])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DMSubMenu label="Preferences">
|
<DMSubMenu label="Preferences" id="TD-MenuItem-Preferences">
|
||||||
<DMCheckboxItem checked={settings.isDarkMode} onCheckedChange={toggleDarkMode} kbd="#⇧D">
|
<DMCheckboxItem
|
||||||
|
checked={settings.isDarkMode}
|
||||||
|
onCheckedChange={toggleDarkMode}
|
||||||
|
kbd="#⇧D"
|
||||||
|
id="TD-MenuItem-Preferences-Dark_Mode"
|
||||||
|
>
|
||||||
Dark Mode
|
Dark Mode
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem checked={settings.isFocusMode} onCheckedChange={toggleFocusMode} kbd="#.">
|
<DMCheckboxItem
|
||||||
|
checked={settings.isFocusMode}
|
||||||
|
onCheckedChange={toggleFocusMode}
|
||||||
|
kbd="#."
|
||||||
|
id="TD-MenuItem-Preferences-Focus_Mode"
|
||||||
|
>
|
||||||
Focus Mode
|
Focus Mode
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem checked={settings.isDebugMode} onCheckedChange={toggleDebugMode}>
|
<DMCheckboxItem
|
||||||
|
checked={settings.isDebugMode}
|
||||||
|
onCheckedChange={toggleDebugMode}
|
||||||
|
id="TD-MenuItem-Preferences-Debug_Mode"
|
||||||
|
>
|
||||||
Debug Mode
|
Debug Mode
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMDivider />
|
<DMDivider />
|
||||||
<DMCheckboxItem checked={settings.showRotateHandles} onCheckedChange={toggleRotateHandle}>
|
<DMCheckboxItem
|
||||||
|
checked={settings.showRotateHandles}
|
||||||
|
onCheckedChange={toggleRotateHandle}
|
||||||
|
id="TD-MenuItem-Preferences-Rotate_Handles"
|
||||||
|
>
|
||||||
Rotate Handles
|
Rotate Handles
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem
|
<DMCheckboxItem
|
||||||
checked={settings.showBindingHandles}
|
checked={settings.showBindingHandles}
|
||||||
onCheckedChange={toggleBoundShapesHandle}
|
onCheckedChange={toggleBoundShapesHandle}
|
||||||
|
id="TD-MenuItem-Preferences-Binding_Handles"
|
||||||
>
|
>
|
||||||
Binding Handles
|
Binding Handles
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem checked={settings.showCloneHandles} onCheckedChange={toggleCloneControls}>
|
<DMCheckboxItem
|
||||||
|
checked={settings.showCloneHandles}
|
||||||
|
onCheckedChange={toggleCloneControls}
|
||||||
|
id="TD-MenuItem-Preferences-Clone_Handles"
|
||||||
|
>
|
||||||
Clone Handles
|
Clone Handles
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem
|
<DMCheckboxItem
|
||||||
checked={settings.showGrid}
|
checked={settings.showGrid}
|
||||||
onCheckedChange={toggleGrid}
|
onCheckedChange={toggleGrid}
|
||||||
kbd="#⇧G"
|
kbd="#⇧G"
|
||||||
|
id="TD-MenuItem-Preferences-Grid"
|
||||||
>
|
>
|
||||||
Grid
|
Grid
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<DMCheckboxItem checked={settings.isSnapping} onCheckedChange={toggleisSnapping}>
|
<DMCheckboxItem
|
||||||
|
checked={settings.isSnapping}
|
||||||
|
onCheckedChange={toggleisSnapping}
|
||||||
|
id="TD-MenuItem-Preferences-Always_Show_Snaps"
|
||||||
|
>
|
||||||
Always Show Snaps
|
Always Show Snaps
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
</DMSubMenu>
|
</DMSubMenu>
|
||||||
|
|
|
@ -167,7 +167,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr" onOpenChange={handleMenuOpenChange}>
|
<DropdownMenu.Root dir="ltr" onOpenChange={handleMenuOpenChange}>
|
||||||
<DropdownMenu.Trigger asChild>
|
<DropdownMenu.Trigger asChild id="TD-Styles">
|
||||||
<ToolButton variant="text">
|
<ToolButton variant="text">
|
||||||
Styles
|
Styles
|
||||||
<OverlapIcons
|
<OverlapIcons
|
||||||
|
@ -187,11 +187,16 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
</ToolButton>
|
</ToolButton>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DMContent>
|
<DMContent>
|
||||||
<StyledRow variant="tall">
|
<StyledRow variant="tall" id="TD-Styles-Color-Container">
|
||||||
<span>Color</span>
|
<span>Color</span>
|
||||||
<ColorGrid>
|
<ColorGrid>
|
||||||
{Object.keys(strokes.light).map((style: string) => (
|
{Object.keys(strokes.light).map((style: string) => (
|
||||||
<DropdownMenu.Item key={style} onSelect={preventEvent} asChild>
|
<DropdownMenu.Item
|
||||||
|
key={style}
|
||||||
|
onSelect={preventEvent}
|
||||||
|
asChild
|
||||||
|
id={`TD-Styles-Color-Swatch-${style}`}
|
||||||
|
>
|
||||||
<ToolButton
|
<ToolButton
|
||||||
variant="icon"
|
variant="icon"
|
||||||
isActive={displayedStyle.color === style}
|
isActive={displayedStyle.color === style}
|
||||||
|
@ -214,10 +219,11 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
variant="styleMenu"
|
variant="styleMenu"
|
||||||
checked={!!displayedStyle.isFilled}
|
checked={!!displayedStyle.isFilled}
|
||||||
onCheckedChange={handleToggleFilled}
|
onCheckedChange={handleToggleFilled}
|
||||||
|
id="TD-Styles-Fill"
|
||||||
>
|
>
|
||||||
Fill
|
Fill
|
||||||
</DMCheckboxItem>
|
</DMCheckboxItem>
|
||||||
<StyledRow>
|
<StyledRow id="TD-Styles-Dash-Container">
|
||||||
Dash
|
Dash
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.dash} onValueChange={handleDashChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.dash} onValueChange={handleDashChange}>
|
||||||
{Object.values(DashStyle).map((style) => (
|
{Object.values(DashStyle).map((style) => (
|
||||||
|
@ -227,13 +233,14 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
value={style}
|
value={style}
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
|
id={`TD-Styles-Dash-${style}`}
|
||||||
>
|
>
|
||||||
{DASH_ICONS[style as DashStyle]}
|
{DASH_ICONS[style as DashStyle]}
|
||||||
</DMRadioItem>
|
</DMRadioItem>
|
||||||
))}
|
))}
|
||||||
</StyledGroup>
|
</StyledGroup>
|
||||||
</StyledRow>
|
</StyledRow>
|
||||||
<StyledRow>
|
<StyledRow id="TD-Styles-Size-Container">
|
||||||
Size
|
Size
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.size} onValueChange={handleSizeChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.size} onValueChange={handleSizeChange}>
|
||||||
{Object.values(SizeStyle).map((sizeStyle) => (
|
{Object.values(SizeStyle).map((sizeStyle) => (
|
||||||
|
@ -243,6 +250,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
value={sizeStyle}
|
value={sizeStyle}
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
|
id={`TD-Styles-Dash-${sizeStyle}`}
|
||||||
>
|
>
|
||||||
{SIZE_ICONS[sizeStyle as SizeStyle]}
|
{SIZE_ICONS[sizeStyle as SizeStyle]}
|
||||||
</DMRadioItem>
|
</DMRadioItem>
|
||||||
|
@ -252,7 +260,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
{(options === 'text' || options === 'label') && (
|
{(options === 'text' || options === 'label') && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<StyledRow>
|
<StyledRow id="TD-Styles-Font-Container">
|
||||||
Font
|
Font
|
||||||
<StyledGroup dir="ltr" value={displayedStyle.font} onValueChange={handleFontChange}>
|
<StyledGroup dir="ltr" value={displayedStyle.font} onValueChange={handleFontChange}>
|
||||||
{Object.values(FontStyle).map((fontStyle) => (
|
{Object.values(FontStyle).map((fontStyle) => (
|
||||||
|
@ -262,6 +270,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
value={fontStyle}
|
value={fontStyle}
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
|
id={`TD-Styles-Font-${fontStyle}`}
|
||||||
>
|
>
|
||||||
<FontIcon fontStyle={fontStyle}>Aa</FontIcon>
|
<FontIcon fontStyle={fontStyle}>Aa</FontIcon>
|
||||||
</DMRadioItem>
|
</DMRadioItem>
|
||||||
|
@ -269,7 +278,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
</StyledGroup>
|
</StyledGroup>
|
||||||
</StyledRow>
|
</StyledRow>
|
||||||
{options === 'text' && (
|
{options === 'text' && (
|
||||||
<StyledRow>
|
<StyledRow id="TD-Styles-Align-Container">
|
||||||
Align
|
Align
|
||||||
<StyledGroup
|
<StyledGroup
|
||||||
dir="ltr"
|
dir="ltr"
|
||||||
|
@ -283,6 +292,7 @@ export const StyleMenu = React.memo(function ColorMenu(): JSX.Element {
|
||||||
value={style}
|
value={style}
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
|
id={`TD-Styles-Align-${style}`}
|
||||||
>
|
>
|
||||||
{ALIGN_ICONS[style]}
|
{ALIGN_ICONS[style]}
|
||||||
</DMRadioItem>
|
</DMRadioItem>
|
||||||
|
|
|
@ -32,7 +32,7 @@ export function TopPanel({
|
||||||
return (
|
return (
|
||||||
<StyledTopPanel>
|
<StyledTopPanel>
|
||||||
{(showMenu || showPages) && (
|
{(showMenu || showPages) && (
|
||||||
<Panel side="left">
|
<Panel side="left" id="TD-MenuPanel">
|
||||||
{showMenu && <Menu showSponsorLink={showSponsorLink} readOnly={readOnly} />}
|
{showMenu && <Menu showSponsorLink={showSponsorLink} readOnly={readOnly} />}
|
||||||
{showPages && <PageMenu />}
|
{showPages && <PageMenu />}
|
||||||
</Panel>
|
</Panel>
|
||||||
|
|
|
@ -16,25 +16,30 @@ export const ZoomMenu = React.memo(function ZoomMenu() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DropdownMenu.Root dir="ltr">
|
<DropdownMenu.Root dir="ltr">
|
||||||
<DropdownMenu.Trigger dir="ltr" asChild>
|
<DropdownMenu.Trigger dir="ltr" asChild id="TD-Zoom">
|
||||||
<FixedWidthToolButton onDoubleClick={app.resetZoom} variant="text">
|
<FixedWidthToolButton onDoubleClick={app.resetZoom} variant="text">
|
||||||
{Math.round(zoom * 100)}%
|
{Math.round(zoom * 100)}%
|
||||||
</FixedWidthToolButton>
|
</FixedWidthToolButton>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DMContent align="end">
|
<DMContent align="end">
|
||||||
<DMItem onSelect={preventEvent} onClick={app.zoomIn} kbd="#+">
|
<DMItem onSelect={preventEvent} onClick={app.zoomIn} kbd="#+" id="TD-Zoom-Zoom_In">
|
||||||
Zoom In
|
Zoom In
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={app.zoomOut} kbd="#−">
|
<DMItem onSelect={preventEvent} onClick={app.zoomOut} kbd="#−" id="TD-Zoom-Zoom_Out">
|
||||||
Zoom Out
|
Zoom Out
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={app.resetZoom} kbd="⇧0">
|
<DMItem onSelect={preventEvent} onClick={app.resetZoom} kbd="⇧0" id="TD-Zoom-Zoom_To_100%">
|
||||||
To 100%
|
To 100%
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={app.zoomToFit} kbd="⇧1">
|
<DMItem onSelect={preventEvent} onClick={app.zoomToFit} kbd="⇧1" id="TD-Zoom-To_Fit">
|
||||||
To Fit
|
To Fit
|
||||||
</DMItem>
|
</DMItem>
|
||||||
<DMItem onSelect={preventEvent} onClick={app.zoomToSelection} kbd="⇧2">
|
<DMItem
|
||||||
|
onSelect={preventEvent}
|
||||||
|
onClick={app.zoomToSelection}
|
||||||
|
kbd="⇧2"
|
||||||
|
id="TD-Zoom-To_Selection"
|
||||||
|
>
|
||||||
To Selection
|
To Selection
|
||||||
</DMItem>
|
</DMItem>
|
||||||
</DMContent>
|
</DMContent>
|
||||||
|
|
Loading…
Reference in a new issue