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:
Proful Sadangi 2021-11-11 20:54:58 +11:00 committed by GitHub
parent 913b4dc5d2
commit 4dd1aea572
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 8 deletions

View file

@ -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.

View file

@ -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}

View file

@ -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>
) )

View file

@ -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 ? (
<> <>

View file

@ -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',

View file

@ -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}
> >