Fix tooltip label & color contrast (#262)
* Fix tooltip label & color contrast * adds fix for context menu * Fix focus within * Add inline docs * Fix color for kbd * Fix for submenu * tighten up code * Added onBlur mock function Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
913b4dc5d2
commit
4dd1aea572
6 changed files with 28 additions and 8 deletions
|
@ -12,7 +12,7 @@ This package contains the [tldraw](https://tldraw.com) editor as a React compone
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Use your package manager of choice to install `@tldraw/core` and its peer dependencies.
|
Use your package manager of choice to install `@tldraw/tldraw` and its peer dependencies.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn add @tldraw/tldraw
|
yarn add @tldraw/tldraw
|
||||||
|
@ -154,7 +154,7 @@ const tldocument: TLDrawDocument = {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Tip:** TLDraw is built [@tldraw/core](https://github.com/tldraw/core). The pages and pagestates in TLDraw are just objects containing `TLPage` and `TLPageState` objects from the core library. For more about these types, check out the [@tldraw/core](https://github.com/tldraw/core) documentation.
|
**Tip:** TLDraw is built on [@tldraw/core](https://github.com/tldraw/core). The pages and pageStates in TLDraw are just objects containing `TLPage` and `TLPageState` objects from the core library. For more about these types, check out the [@tldraw/core](https://github.com/tldraw/core) documentation.
|
||||||
|
|
||||||
**Important:** In the `pages` object, each `TLPage` object must be keyed under its `id` property. Likewise, each `TLPageState` object must be keyed under its `id`. In addition, each `TLPageState` object must have an `id` that matches its corresponding page.
|
**Important:** In the `pages` object, each `TLPage` object must be keyed under its `id` property. Likewise, each `TLPageState` object must be keyed under its `id`. In addition, each `TLPageState` object must have an `id` that matches its corresponding page.
|
||||||
|
|
||||||
|
|
|
@ -394,10 +394,21 @@ const InnerTLDraw = React.memo(function InnerTLDraw({
|
||||||
state.changePage(currentPageId)
|
state.changePage(currentPageId)
|
||||||
}, [currentPageId, state])
|
}, [currentPageId, state])
|
||||||
|
|
||||||
|
// When the context menu is blurred, close the menu by sending pointer events
|
||||||
|
// to the context menu's ref. This is a hack around the fact that certain shapes
|
||||||
|
// stop event propagation, which causes the menu to stay open even when blurred.
|
||||||
|
const handleContextMenuBlur = React.useCallback<React.FocusEventHandler>((e) => {
|
||||||
|
const elm = rWrapper.current
|
||||||
|
if (!elm) return
|
||||||
|
if (!elm.contains(e.relatedTarget)) return
|
||||||
|
elm.dispatchEvent(new Event('pointerdown', { bubbles: true }))
|
||||||
|
elm.dispatchEvent(new Event('pointerup', { bubbles: true }))
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<StyledLayout ref={rWrapper} tabIndex={0} className={settings.isDarkMode ? dark : ''}>
|
<StyledLayout ref={rWrapper} tabIndex={0} className={settings.isDarkMode ? dark : ''}>
|
||||||
<OneOff focusableRef={rWrapper} autofocus={autofocus} />
|
<OneOff focusableRef={rWrapper} autofocus={autofocus} />
|
||||||
<ContextMenu>
|
<ContextMenu onBlur={handleContextMenuBlur}>
|
||||||
<Renderer
|
<Renderer
|
||||||
id={id}
|
id={id}
|
||||||
containerRef={rWrapper}
|
containerRef={rWrapper}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { renderWithContext } from '~test'
|
||||||
describe('context menu', () => {
|
describe('context menu', () => {
|
||||||
test('mounts component without crashing', () => {
|
test('mounts component without crashing', () => {
|
||||||
renderWithContext(
|
renderWithContext(
|
||||||
<ContextMenu>
|
<ContextMenu onBlur={jest.fn()}>
|
||||||
<div>Hello</div>
|
<div>Hello</div>
|
||||||
</ContextMenu>
|
</ContextMenu>
|
||||||
)
|
)
|
||||||
|
|
|
@ -44,10 +44,11 @@ const hasGroupSelectedSelector = (s: TLDrawSnapshot) => {
|
||||||
const preventDefault = (e: Event) => e.stopPropagation()
|
const preventDefault = (e: Event) => e.stopPropagation()
|
||||||
|
|
||||||
interface ContextMenuProps {
|
interface ContextMenuProps {
|
||||||
|
onBlur: React.FocusEventHandler
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ContextMenu = ({ children }: ContextMenuProps): JSX.Element => {
|
export const ContextMenu = ({ onBlur, children }: ContextMenuProps): JSX.Element => {
|
||||||
const { state, useSelector } = useTLDrawContext()
|
const { state, useSelector } = useTLDrawContext()
|
||||||
const hasSelection = useSelector(has1SelectedIdsSelector)
|
const hasSelection = useSelector(has1SelectedIdsSelector)
|
||||||
const hasTwoOrMore = useSelector(has2SelectedIdsSelector)
|
const hasTwoOrMore = useSelector(has2SelectedIdsSelector)
|
||||||
|
@ -120,7 +121,14 @@ export const ContextMenu = ({ children }: ContextMenuProps): JSX.Element => {
|
||||||
return (
|
return (
|
||||||
<RadixContextMenu.Root>
|
<RadixContextMenu.Root>
|
||||||
<RadixContextMenu.Trigger dir="ltr">{children}</RadixContextMenu.Trigger>
|
<RadixContextMenu.Trigger dir="ltr">{children}</RadixContextMenu.Trigger>
|
||||||
<RadixContextMenu.Content dir="ltr" ref={rContent} onEscapeKeyDown={preventDefault} asChild>
|
<RadixContextMenu.Content
|
||||||
|
dir="ltr"
|
||||||
|
ref={rContent}
|
||||||
|
onEscapeKeyDown={preventDefault}
|
||||||
|
asChild
|
||||||
|
tabIndex={-1}
|
||||||
|
onBlur={onBlur}
|
||||||
|
>
|
||||||
<MenuContent>
|
<MenuContent>
|
||||||
{hasSelection ? (
|
{hasSelection ? (
|
||||||
<>
|
<>
|
||||||
|
|
|
@ -51,6 +51,7 @@ export const StyledKbd = styled('kbd', {
|
||||||
variant: {
|
variant: {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
'& > span': {
|
'& > span': {
|
||||||
|
color: '$tooltipText',
|
||||||
background: '$overlayContrast',
|
background: '$overlayContrast',
|
||||||
boxShadow: '$key',
|
boxShadow: '$key',
|
||||||
width: '20px',
|
width: '20px',
|
||||||
|
|
|
@ -51,7 +51,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Panel side="center">
|
<Panel side="center">
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'2'}
|
kbd={'1'}
|
||||||
label={'select'}
|
label={'select'}
|
||||||
onClick={selectSelectTool}
|
onClick={selectSelectTool}
|
||||||
isActive={activeTool === 'select'}
|
isActive={activeTool === 'select'}
|
||||||
|
@ -76,7 +76,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'4'}
|
kbd={'4'}
|
||||||
label={TLDrawShapeType.Draw}
|
label={TLDrawShapeType.Ellipse}
|
||||||
onClick={selectEllipseTool}
|
onClick={selectEllipseTool}
|
||||||
isActive={activeTool === TLDrawShapeType.Ellipse}
|
isActive={activeTool === TLDrawShapeType.Ellipse}
|
||||||
>
|
>
|
||||||
|
|
Loading…
Reference in a new issue