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:
Mime Čuvalo 2024-05-21 15:28:09 +01:00 committed by GitHub
parent 625d59e468
commit 453c98dd7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 23 additions and 27 deletions

View file

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

View file

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

View file

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

View file

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