Fix 'style panel doesn't always disappear if you switch to the hand/laser tools' (#2886)
We had some bad logic in `useRelevantStyles` explicitly allowing an opacity-slider to be rendered at all times when there is at least one shape selected. This shouldn't be the case when the editor is in non-shape-focused tools like the move tool and the laser pointer tool. I refactored the hook slightly to make it easier to express the correct logic. See the comment for a more detailed description. ### Change Type - [x] `patch` — Bug fix [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Release Notes - Fixes an bug causing the opacity slider to show up in the move tool and laser pointer tool.
This commit is contained in:
parent
9b65b0e20f
commit
3e12b27728
8 changed files with 30 additions and 25 deletions
|
@ -7168,9 +7168,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
private _selectionSharedStyles = computed<ReadonlySharedStyleMap>(
|
@computed
|
||||||
'_selectionSharedStyles',
|
private _getSelectionSharedStyles(): ReadonlySharedStyleMap {
|
||||||
() => {
|
|
||||||
const selectedShapes = this.getSelectedShapes()
|
const selectedShapes = this.getSelectedShapes()
|
||||||
|
|
||||||
const sharedStyles = new SharedStyleMap()
|
const sharedStyles = new SharedStyleMap()
|
||||||
|
@ -7180,7 +7179,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
|
|
||||||
return sharedStyles
|
return sharedStyles
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
/** @internal */
|
/** @internal */
|
||||||
getStyleForNextShape<T>(style: StyleProp<T>): T {
|
getStyleForNextShape<T>(style: StyleProp<T>): T {
|
||||||
|
@ -7213,7 +7211,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
||||||
// If we're in selecting and if we have a selection, return the shared styles from the
|
// If we're in selecting and if we have a selection, return the shared styles from the
|
||||||
// current selection
|
// current selection
|
||||||
if (this.isIn('select') && this.getSelectedShapeIds().length > 0) {
|
if (this.isIn('select') && this.getSelectedShapeIds().length > 0) {
|
||||||
return this._selectionSharedStyles.get()
|
return this._getSelectionSharedStyles()
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the current tool is associated with a shape, return the styles for that shape.
|
// If the current tool is associated with a shape, return the styles for that shape.
|
||||||
|
|
|
@ -23513,7 +23513,7 @@
|
||||||
"text": ";"
|
"text": ";"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"fileUrlPath": "packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts",
|
"fileUrlPath": "packages/tldraw/src/lib/ui/hooks/useRelevantStyles.ts",
|
||||||
"returnTypeTokenRange": {
|
"returnTypeTokenRange": {
|
||||||
"startIndex": 5,
|
"startIndex": 5,
|
||||||
"endIndex": 7
|
"endIndex": 7
|
||||||
|
|
|
@ -81,7 +81,7 @@ export { useKeyboardShortcuts } from './lib/ui/hooks/useKeyboardShortcuts'
|
||||||
export { useLocalStorageState } from './lib/ui/hooks/useLocalStorageState'
|
export { useLocalStorageState } from './lib/ui/hooks/useLocalStorageState'
|
||||||
export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen'
|
export { useMenuIsOpen } from './lib/ui/hooks/useMenuIsOpen'
|
||||||
export { useReadonly } from './lib/ui/hooks/useReadonly'
|
export { useReadonly } from './lib/ui/hooks/useReadonly'
|
||||||
export { useRelevantStyles } from './lib/ui/hooks/useRevelantStyles'
|
export { useRelevantStyles } from './lib/ui/hooks/useRelevantStyles'
|
||||||
export {
|
export {
|
||||||
toolbarItem,
|
toolbarItem,
|
||||||
useToolbarSchema,
|
useToolbarSchema,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
} from '@tldraw/editor'
|
} from '@tldraw/editor'
|
||||||
import { useCallback } from 'react'
|
import { useCallback } from 'react'
|
||||||
import { useTldrawUiComponents } from '../context/components'
|
import { useTldrawUiComponents } from '../context/components'
|
||||||
import { useRelevantStyles } from '../hooks/useRevelantStyles'
|
import { useRelevantStyles } from '../hooks/useRelevantStyles'
|
||||||
import { useTranslation } from '../hooks/useTranslation/useTranslation'
|
import { useTranslation } from '../hooks/useTranslation/useTranslation'
|
||||||
import { TldrawUiButton } from './primitives/Button/TldrawUiButton'
|
import { TldrawUiButton } from './primitives/Button/TldrawUiButton'
|
||||||
import { TldrawUiButtonIcon } from './primitives/Button/TldrawUiButtonIcon'
|
import { TldrawUiButtonIcon } from './primitives/Button/TldrawUiButtonIcon'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { useEditor } from '@tldraw/editor'
|
import { useEditor } from '@tldraw/editor'
|
||||||
import classNames from 'classnames'
|
import classNames from 'classnames'
|
||||||
import { memo, useCallback } from 'react'
|
import { memo, useCallback } from 'react'
|
||||||
import { useRelevantStyles } from '../../hooks/useRevelantStyles'
|
import { useRelevantStyles } from '../../hooks/useRelevantStyles'
|
||||||
import { DefaultStylePanelContent } from './DefaultStylePanelContent'
|
import { DefaultStylePanelContent } from './DefaultStylePanelContent'
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
|
|
|
@ -13,7 +13,6 @@ import {
|
||||||
ReadonlySharedStyleMap,
|
ReadonlySharedStyleMap,
|
||||||
StyleProp,
|
StyleProp,
|
||||||
TLArrowShapeArrowheadStyle,
|
TLArrowShapeArrowheadStyle,
|
||||||
TLDefaultVerticalAlignStyle,
|
|
||||||
minBy,
|
minBy,
|
||||||
useEditor,
|
useEditor,
|
||||||
useValue,
|
useValue,
|
||||||
|
@ -21,7 +20,7 @@ import {
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { STYLES } from '../../../styles'
|
import { STYLES } from '../../../styles'
|
||||||
import { useUiEvents } from '../../context/events'
|
import { useUiEvents } from '../../context/events'
|
||||||
import { useRelevantStyles } from '../../hooks/useRevelantStyles'
|
import { useRelevantStyles } from '../../hooks/useRelevantStyles'
|
||||||
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
||||||
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
import { TldrawUiButton } from '../primitives/Button/TldrawUiButton'
|
||||||
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
import { TldrawUiButtonIcon } from '../primitives/Button/TldrawUiButtonIcon'
|
||||||
|
@ -201,7 +200,7 @@ function TextStylePickerSet({ styles }: { styles: ReadonlySharedStyleMap }) {
|
||||||
<TldrawUiButtonIcon icon="vertical-align-center" />
|
<TldrawUiButtonIcon icon="vertical-align-center" />
|
||||||
</TldrawUiButton>
|
</TldrawUiButton>
|
||||||
) : (
|
) : (
|
||||||
<DropdownPicker<TLDefaultVerticalAlignStyle>
|
<DropdownPicker
|
||||||
type="icon"
|
type="icon"
|
||||||
id="geo-vertical-alignment"
|
id="geo-vertical-alignment"
|
||||||
uiType="verticalAlign"
|
uiType="verticalAlign"
|
||||||
|
|
|
@ -82,9 +82,9 @@ function _DoubleDropdownPicker<T extends string>({
|
||||||
</TldrawUiDropdownMenuTrigger>
|
</TldrawUiDropdownMenuTrigger>
|
||||||
<TldrawUiDropdownMenuContent side="bottom" align="end" sideOffset={0} alignOffset={-2}>
|
<TldrawUiDropdownMenuContent side="bottom" align="end" sideOffset={0} alignOffset={-2}>
|
||||||
<div className="tlui-buttons__grid">
|
<div className="tlui-buttons__grid">
|
||||||
{itemsA.map((item) => {
|
{itemsA.map((item, i) => {
|
||||||
return (
|
return (
|
||||||
<TldrawUiDropdownMenuItem data-testid={`style.${uiTypeA}.${item.value}`}>
|
<TldrawUiDropdownMenuItem key={i} data-testid={`style.${uiTypeA}.${item.value}`}>
|
||||||
<TldrawUiButton
|
<TldrawUiButton
|
||||||
type="icon"
|
type="icon"
|
||||||
key={item.value}
|
key={item.value}
|
||||||
|
|
|
@ -24,8 +24,8 @@ export function useRelevantStyles(stylesToCheck = selectToolStyles): ReadonlySha
|
||||||
'getRelevantStyles',
|
'getRelevantStyles',
|
||||||
() => {
|
() => {
|
||||||
const styles = new SharedStyleMap(editor.getSharedStyles())
|
const styles = new SharedStyleMap(editor.getSharedStyles())
|
||||||
const hasShape =
|
const isInShapeSpecificTool = !!editor.root.getCurrent()?.shapeType
|
||||||
editor.getSelectedShapeIds().length > 0 || !!editor.root.getCurrent()?.shapeType
|
const hasShapesSelected = editor.isIn('select') && editor.getSelectedShapeIds().length > 0
|
||||||
|
|
||||||
if (styles.size === 0 && editor.isIn('select') && editor.getSelectedShapeIds().length === 0) {
|
if (styles.size === 0 && editor.isIn('select') && editor.getSelectedShapeIds().length === 0) {
|
||||||
for (const style of stylesToCheck) {
|
for (const style of stylesToCheck) {
|
||||||
|
@ -33,8 +33,16 @@ export function useRelevantStyles(stylesToCheck = selectToolStyles): ReadonlySha
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (styles.size === 0 && !hasShape) return null
|
if (isInShapeSpecificTool || hasShapesSelected || styles.size > 0) {
|
||||||
|
// If size is 0 we may still want to return an empty styles map to allow
|
||||||
|
// the opacity slider to show up.
|
||||||
|
// This can happen in two situations:
|
||||||
|
// 1. When the user is in the select tool and has multiple shapes selected but they have no supported styles (beyond opacity).
|
||||||
|
// 2. When the user is in a shape-specific tool and the shape has no supported styles (beyond opacity obvs).
|
||||||
return styles
|
return styles
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
},
|
},
|
||||||
[editor]
|
[editor]
|
||||||
)
|
)
|
Loading…
Add table
Add a link
Reference in a new issue