toolbar: rework overflow css logic (#3779)
Small side quest: This reworks the overflow toolbar css to rely on `nth-child` instead of putting together a long selector. This also address the minor issue/edge case raised in https://github.com/tldraw/tldraw/pull/3757 ### Change Type <!-- ❗ Please select a 'Scope' label ❗️ --> - [x] `sdk` — Changes the tldraw SDK - [ ] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [ ] `internal` — Does not affect user-facing stuff <!-- ❗ Please select a 'Type' label ❗️ --> - [ ] `bugfix` — Bug fix - [ ] `feature` — New feature - [x] `improvement` — Improving existing features - [ ] `chore` — Updating dependencies, other boring stuff - [ ] `galaxy brain` — Architectural changes - [ ] `tests` — Changes to any test code - [ ] `tools` — Changes to infrastructure, CI, internal scripts, debugging tools, etc. - [ ] `dunno` — I don't know ### Release Notes - Toolbar: cleanup overflow css rules. --------- Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
625d59e468
commit
453c98dd7e
4 changed files with 23 additions and 27 deletions
|
@ -61,21 +61,21 @@ export const STYLES = {
|
||||||
geo: [
|
geo: [
|
||||||
{ value: 'rectangle', icon: 'geo-rectangle' },
|
{ value: 'rectangle', icon: 'geo-rectangle' },
|
||||||
{ value: 'ellipse', icon: 'geo-ellipse' },
|
{ value: 'ellipse', icon: 'geo-ellipse' },
|
||||||
{ value: 'cloud', icon: 'geo-cloud' },
|
|
||||||
{ value: 'triangle', icon: 'geo-triangle' },
|
{ value: 'triangle', icon: 'geo-triangle' },
|
||||||
{ value: 'diamond', icon: 'geo-diamond' },
|
{ value: 'diamond', icon: 'geo-diamond' },
|
||||||
|
{ value: 'star', icon: 'geo-star' },
|
||||||
{ value: 'pentagon', icon: 'geo-pentagon' },
|
{ value: 'pentagon', icon: 'geo-pentagon' },
|
||||||
{ value: 'hexagon', icon: 'geo-hexagon' },
|
{ value: 'hexagon', icon: 'geo-hexagon' },
|
||||||
{ value: 'octagon', icon: 'geo-octagon' },
|
{ value: 'octagon', icon: 'geo-octagon' },
|
||||||
{ value: 'star', icon: 'geo-star' },
|
|
||||||
{ value: 'rhombus', icon: 'geo-rhombus' },
|
{ value: 'rhombus', icon: 'geo-rhombus' },
|
||||||
{ value: 'rhombus-2', icon: 'geo-rhombus-2' },
|
{ value: 'rhombus-2', icon: 'geo-rhombus-2' },
|
||||||
{ value: 'oval', icon: 'geo-oval' },
|
{ value: 'oval', icon: 'geo-oval' },
|
||||||
{ value: 'trapezoid', icon: 'geo-trapezoid' },
|
{ value: 'trapezoid', icon: 'geo-trapezoid' },
|
||||||
{ value: 'arrow-right', icon: 'geo-arrow-right' },
|
|
||||||
{ value: 'arrow-left', icon: 'geo-arrow-left' },
|
{ value: 'arrow-left', icon: 'geo-arrow-left' },
|
||||||
{ value: 'arrow-up', icon: 'geo-arrow-up' },
|
{ value: 'arrow-up', icon: 'geo-arrow-up' },
|
||||||
{ value: 'arrow-down', icon: 'geo-arrow-down' },
|
{ value: 'arrow-down', icon: 'geo-arrow-down' },
|
||||||
|
{ value: 'arrow-right', icon: 'geo-arrow-right' },
|
||||||
|
{ value: 'cloud', icon: 'geo-cloud' },
|
||||||
{ value: 'x-box', icon: 'geo-x-box' },
|
{ value: 'x-box', icon: 'geo-x-box' },
|
||||||
{ value: 'check-box', icon: 'geo-check-box' },
|
{ value: 'check-box', icon: 'geo-check-box' },
|
||||||
],
|
],
|
||||||
|
|
|
@ -16,14 +16,14 @@ export function DefaultToolbarContent() {
|
||||||
<AssetToolbarItem />
|
<AssetToolbarItem />
|
||||||
<RectangleToolbarItem />
|
<RectangleToolbarItem />
|
||||||
<EllipseToolbarItem />
|
<EllipseToolbarItem />
|
||||||
<DiamondToolbarItem />
|
|
||||||
<TriangleToolbarItem />
|
<TriangleToolbarItem />
|
||||||
<TrapezoidToolbarItem />
|
<DiamondToolbarItem />
|
||||||
<RhombusToolbarItem />
|
|
||||||
<HexagonToolbarItem />
|
|
||||||
<CloudToolbarItem />
|
<CloudToolbarItem />
|
||||||
<StarToolbarItem />
|
<StarToolbarItem />
|
||||||
|
<HexagonToolbarItem />
|
||||||
<OvalToolbarItem />
|
<OvalToolbarItem />
|
||||||
|
<TrapezoidToolbarItem />
|
||||||
|
<RhombusToolbarItem />
|
||||||
<XBoxToolbarItem />
|
<XBoxToolbarItem />
|
||||||
<CheckBoxToolbarItem />
|
<CheckBoxToolbarItem />
|
||||||
<ArrowLeftToolbarItem />
|
<ArrowLeftToolbarItem />
|
||||||
|
@ -32,8 +32,8 @@ export function DefaultToolbarContent() {
|
||||||
<ArrowRightToolbarItem />
|
<ArrowRightToolbarItem />
|
||||||
<LineToolbarItem />
|
<LineToolbarItem />
|
||||||
<HighlightToolbarItem />
|
<HighlightToolbarItem />
|
||||||
<FrameToolbarItem />
|
|
||||||
<LaserToolbarItem />
|
<LaserToolbarItem />
|
||||||
|
<FrameToolbarItem />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -165,6 +165,13 @@ export function CloudToolbarItem() {
|
||||||
return <TldrawUiMenuItem {...tools['cloud']} isSelected={isSelected} />
|
return <TldrawUiMenuItem {...tools['cloud']} isSelected={isSelected} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @public */
|
||||||
|
export function PentagonToolbarItem() {
|
||||||
|
const tools = useTools()
|
||||||
|
const isSelected = useIsToolSelected(tools['pentagon'])
|
||||||
|
return <TldrawUiMenuItem {...tools['pentagon']} isSelected={isSelected} />
|
||||||
|
}
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export function StarToolbarItem() {
|
export function StarToolbarItem() {
|
||||||
const tools = useTools()
|
const tools = useTools()
|
||||||
|
|
|
@ -31,25 +31,13 @@ export function OverflowingToolbar({ children }: { children: React.ReactNode })
|
||||||
const [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)
|
const [lastActiveOverflowItem, setLastActiveOverflowItem] = useState<string | null>(null)
|
||||||
|
|
||||||
const css = useMemo(() => {
|
const css = useMemo(() => {
|
||||||
const showInMainSelectors = []
|
const activeCss = lastActiveOverflowItem ? `:not([data-value="${lastActiveOverflowItem}"])` : ''
|
||||||
const hideFromOverflowSelectors = []
|
|
||||||
|
|
||||||
if (lastActiveOverflowItem) {
|
|
||||||
showInMainSelectors.push(`[data-value="${lastActiveOverflowItem}"]`)
|
|
||||||
} else {
|
|
||||||
showInMainSelectors.push(`:nth-child(${overflowIndex + 1})`)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < overflowIndex; i++) {
|
|
||||||
showInMainSelectors.push(`:nth-child(${i + 1})`)
|
|
||||||
hideFromOverflowSelectors.push(`:nth-child(${i + 1})`)
|
|
||||||
}
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
#${id}_main > *:not(${showInMainSelectors.join(', ')}) {
|
#${id}_main > *:nth-child(n + ${overflowIndex + (lastActiveOverflowItem ? 1 : 2)})${activeCss} {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
${hideFromOverflowSelectors.map((s) => `#${id}_more > *${s}`).join(', ')} {
|
#${id}_more > *:nth-child(-n + ${overflowIndex}) {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
@ -156,7 +144,8 @@ export function OverflowingToolbar({ children }: { children: React.ReactNode })
|
||||||
{children}
|
{children}
|
||||||
</TldrawUiMenuContextProvider>
|
</TldrawUiMenuContextProvider>
|
||||||
</div>
|
</div>
|
||||||
{totalItems > overflowIndex && (
|
{/* There is a +1 because if the menu is just one item, it's not necessary. */}
|
||||||
|
{totalItems > overflowIndex + 1 && (
|
||||||
<IsInOverflowContext.Provider value={true}>
|
<IsInOverflowContext.Provider value={true}>
|
||||||
<TldrawUiDropdownMenuRoot id="toolbar overflow" modal={false}>
|
<TldrawUiDropdownMenuRoot id="toolbar overflow" modal={false}>
|
||||||
<TldrawUiDropdownMenuTrigger>
|
<TldrawUiDropdownMenuTrigger>
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { Editor, TLContent, VecLike } from '@tldraw/editor'
|
||||||
export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?: VecLike) {
|
export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?: VecLike) {
|
||||||
const p = point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : undefined)
|
const p = point ?? (editor.inputs.shiftKey ? editor.inputs.currentPagePoint : undefined)
|
||||||
|
|
||||||
const seletionBoundsBefore = editor.getSelectionPageBounds()
|
const selectionBoundsBefore = editor.getSelectionPageBounds()
|
||||||
editor.mark('paste')
|
editor.mark('paste')
|
||||||
editor.putContentOntoCurrentPage(clipboard, {
|
editor.putContentOntoCurrentPage(clipboard, {
|
||||||
point: p,
|
point: p,
|
||||||
|
@ -19,9 +19,9 @@ export function pasteTldrawContent(editor: Editor, clipboard: TLContent, point?:
|
||||||
})
|
})
|
||||||
const selectedBoundsAfter = editor.getSelectionPageBounds()
|
const selectedBoundsAfter = editor.getSelectionPageBounds()
|
||||||
if (
|
if (
|
||||||
seletionBoundsBefore &&
|
selectionBoundsBefore &&
|
||||||
selectedBoundsAfter &&
|
selectedBoundsAfter &&
|
||||||
seletionBoundsBefore?.collides(selectedBoundsAfter)
|
selectionBoundsBefore?.collides(selectedBoundsAfter)
|
||||||
) {
|
) {
|
||||||
// Creates a 'puff' to show a paste has happened.
|
// Creates a 'puff' to show a paste has happened.
|
||||||
editor.updateInstanceState({ isChangingStyle: true })
|
editor.updateInstanceState({ isChangingStyle: true })
|
||||||
|
|
Loading…
Reference in a new issue