Fix style panel opening when disabled (#1983)
Closes #1982 When choosing whether to disable the mobile style menu, we now also check if the select tool is active and whether any shapes have been selected. ### Change Type - [x] `patch` — Bug fix - [ ] `minor` — New feature - [ ] `major` — Breaking change - [ ] `dependencies` — Changes to package dependencies[^1] - [ ] `documentation` — Changes to the documentation only[^2] - [ ] `tests` — Changes to any test code only[^2] - [ ] `internal` — Any other changes that don't affect the published package[^2] - [ ] I don't know [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Test Plan 1. On a small screen 2. Choose the select tool 3. Deselect all shapes 4. Click on the disabled style menu button Expected: Nothing should happen Actual: The style menu opens ### Release Notes - When select tool is active, the style menu shouldn't be openable unless a shape is also selected. Before/After <img width="300" src="https://github.com/tldraw/tldraw/assets/98838967/91ea55c8-0fcc-4f73-b61e-565829a5f25e" /> <img width="300" src="https://github.com/tldraw/tldraw/assets/98838967/ee4070fe-e236-4818-8fb4-43520210102b" /> --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
f2833b52c9
commit
512696c1ab
3 changed files with 57 additions and 35 deletions
|
@ -1,5 +1,12 @@
|
|||
import { DefaultColorStyle, getDefaultColorTheme, useEditor, useValue } from '@tldraw/editor'
|
||||
import {
|
||||
DefaultColorStyle,
|
||||
TLDefaultColorStyle,
|
||||
getDefaultColorTheme,
|
||||
useEditor,
|
||||
useValue,
|
||||
} from '@tldraw/editor'
|
||||
import { useCallback } from 'react'
|
||||
import { useRelevantStyles } from '../hooks/useRevelantStyles'
|
||||
import { useTranslation } from '../hooks/useTranslation/useTranslation'
|
||||
import { StylePanel } from './StylePanel/StylePanel'
|
||||
import { Button } from './primitives/Button'
|
||||
|
@ -10,17 +17,12 @@ export function MobileStylePanel() {
|
|||
const editor = useEditor()
|
||||
const msg = useTranslation()
|
||||
|
||||
const currentColor = useValue(
|
||||
'current color',
|
||||
() => {
|
||||
const color = editor.sharedStyles.get(DefaultColorStyle)
|
||||
if (!color) return 'var(--color-muted-1)'
|
||||
if (color.type === 'mixed') return null
|
||||
const theme = getDefaultColorTheme({ isDarkMode: editor.user.isDarkMode })
|
||||
return theme[color.value].solid
|
||||
},
|
||||
[editor]
|
||||
)
|
||||
const relevantStyles = useRelevantStyles()
|
||||
const color = relevantStyles?.styles.get(DefaultColorStyle)
|
||||
const theme = getDefaultColorTheme({ isDarkMode: editor.user.isDarkMode })
|
||||
const currentColor = (
|
||||
color?.type === 'shared' ? theme[color.value as TLDefaultColorStyle] : theme.black
|
||||
).solid
|
||||
|
||||
const disableStylePanel = useValue(
|
||||
'isHandOrEraserToolActive',
|
||||
|
@ -43,10 +45,12 @@ export function MobileStylePanel() {
|
|||
<Button
|
||||
className="tlui-toolbar__tools__button tlui-toolbar__styles__button"
|
||||
data-testid="mobile.styles"
|
||||
style={{ color: currentColor ?? 'var(--color-text)' }}
|
||||
style={{
|
||||
color: disableStylePanel ? 'var(--color-muted-1)' : currentColor,
|
||||
}}
|
||||
title={msg('style-panel.title')}
|
||||
>
|
||||
<Icon icon={currentColor ? 'blob' : 'mixed'} />
|
||||
<Icon icon={disableStylePanel ? 'blob' : color?.type === 'mixed' ? 'mixed' : 'blob'} />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent side="top" align="end">
|
||||
|
|
|
@ -8,18 +8,16 @@ import {
|
|||
DefaultHorizontalAlignStyle,
|
||||
DefaultSizeStyle,
|
||||
DefaultVerticalAlignStyle,
|
||||
Editor,
|
||||
GeoShapeGeoStyle,
|
||||
LineShapeSplineStyle,
|
||||
ReadonlySharedStyleMap,
|
||||
SharedStyle,
|
||||
SharedStyleMap,
|
||||
StyleProp,
|
||||
minBy,
|
||||
useEditor,
|
||||
useValue,
|
||||
} from '@tldraw/editor'
|
||||
import React, { useCallback } from 'react'
|
||||
import { useRelevantStyles } from '../../hooks/useRevelantStyles'
|
||||
import { useTranslation } from '../../hooks/useTranslation/useTranslation'
|
||||
import { Button } from '../primitives/Button'
|
||||
import { ButtonPicker } from '../primitives/ButtonPicker'
|
||||
|
@ -32,28 +30,11 @@ interface StylePanelProps {
|
|||
isMobile?: boolean
|
||||
}
|
||||
|
||||
const selectToolStyles = [DefaultColorStyle, DefaultDashStyle, DefaultFillStyle, DefaultSizeStyle]
|
||||
function getRelevantStyles(
|
||||
editor: Editor
|
||||
): { styles: ReadonlySharedStyleMap; opacity: SharedStyle<number> } | null {
|
||||
const styles = new SharedStyleMap(editor.sharedStyles)
|
||||
const hasShape = editor.selectedShapeIds.length > 0 || !!editor.root.current.value?.shapeType
|
||||
|
||||
if (styles.size === 0 && editor.isIn('select') && editor.selectedShapeIds.length === 0) {
|
||||
for (const style of selectToolStyles) {
|
||||
styles.applyValue(style, editor.getStyleForNextShape(style))
|
||||
}
|
||||
}
|
||||
|
||||
if (styles.size === 0 && !hasShape) return null
|
||||
return { styles, opacity: editor.sharedOpacity }
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const StylePanel = function StylePanel({ isMobile }: StylePanelProps) {
|
||||
const editor = useEditor()
|
||||
|
||||
const relevantStyles = useValue('getRelevantStyles', () => getRelevantStyles(editor), [editor])
|
||||
const relevantStyles = useRelevantStyles()
|
||||
|
||||
const handlePointerOut = useCallback(() => {
|
||||
if (!isMobile) {
|
||||
|
|
37
packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts
Normal file
37
packages/tldraw/src/lib/ui/hooks/useRevelantStyles.ts
Normal file
|
@ -0,0 +1,37 @@
|
|||
import {
|
||||
DefaultColorStyle,
|
||||
DefaultDashStyle,
|
||||
DefaultFillStyle,
|
||||
DefaultSizeStyle,
|
||||
ReadonlySharedStyleMap,
|
||||
SharedStyle,
|
||||
SharedStyleMap,
|
||||
useEditor,
|
||||
useValue,
|
||||
} from '@tldraw/editor'
|
||||
|
||||
const selectToolStyles = [DefaultColorStyle, DefaultDashStyle, DefaultFillStyle, DefaultSizeStyle]
|
||||
|
||||
export function useRelevantStyles(): {
|
||||
styles: ReadonlySharedStyleMap
|
||||
opacity: SharedStyle<number>
|
||||
} | null {
|
||||
const editor = useEditor()
|
||||
return useValue(
|
||||
'getRelevantStyles',
|
||||
() => {
|
||||
const styles = new SharedStyleMap(editor.sharedStyles)
|
||||
const hasShape = editor.selectedShapeIds.length > 0 || !!editor.root.current.value?.shapeType
|
||||
|
||||
if (styles.size === 0 && editor.isIn('select') && editor.selectedShapeIds.length === 0) {
|
||||
for (const style of selectToolStyles) {
|
||||
styles.applyValue(style, editor.getStyleForNextShape(style))
|
||||
}
|
||||
}
|
||||
|
||||
if (styles.size === 0 && !hasShape) return null
|
||||
return { styles, opacity: editor.sharedOpacity }
|
||||
},
|
||||
[editor]
|
||||
)
|
||||
}
|
Loading…
Reference in a new issue