Skip to content

Commit cf24aed

Browse files
authored
Vertical toolbar example (tldraw#6532)
Vertical toolbar! Use it like this: ```tsx <Tldraw components={{ Toolbar: () => <DefaultToolbar orientation="vertical" /> }} /> ``` Right now, I've only supported a vertical toolbar on the left of the screen because to put it elsewhere we'd need a better way of moving other parts of the UI around. This also supports groups in the toolbar, and re-works the overflowing toolbar component to work both horizontally and vertically. ### Change type - [x] `api` ### Release notes ### API Changes - You can now position the toolbar vertically down the right of the screen by setting it's orientation to `vertical`. You can also now use `<TldrawUiMenuGroup />` to group together toolbar items.
1 parent 8568741 commit cf24aed

17 files changed

Lines changed: 821 additions & 204 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: Toolbar groups
3+
component: ./ToolbarGroupsExample.tsx
4+
category: ui
5+
keyword: [custom, vertical, toolbar, groups]
6+
---
7+
8+
Create groups within the toolbar to separate related concepts.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { useMemo, useState } from 'react'
2+
import {
3+
ArrowDownToolbarItem,
4+
ArrowLeftToolbarItem,
5+
ArrowRightToolbarItem,
6+
ArrowUpToolbarItem,
7+
CloudToolbarItem,
8+
DefaultToolbar,
9+
DiamondToolbarItem,
10+
DrawToolbarItem,
11+
EllipseToolbarItem,
12+
EraserToolbarItem,
13+
HandToolbarItem,
14+
HexagonToolbarItem,
15+
HighlightToolbarItem,
16+
LaserToolbarItem,
17+
OvalToolbarItem,
18+
RectangleToolbarItem,
19+
RhombusToolbarItem,
20+
SelectToolbarItem,
21+
StarToolbarItem,
22+
TLComponents,
23+
Tldraw,
24+
TldrawUiMenuGroup,
25+
TldrawUiMenuItem,
26+
TriangleToolbarItem,
27+
} from 'tldraw'
28+
import 'tldraw/tldraw.css'
29+
30+
export default function BasicExample() {
31+
const [orientation, setOrientation] = useState<'horizontal' | 'vertical'>('horizontal')
32+
33+
const components = useMemo((): TLComponents => {
34+
return {
35+
Toolbar: () => (
36+
<DefaultToolbar orientation={orientation}>
37+
<TldrawUiMenuGroup id="orientation">
38+
<TldrawUiMenuItem
39+
id="orientation"
40+
onSelect={() =>
41+
setOrientation(orientation === 'horizontal' ? 'vertical' : 'horizontal')
42+
}
43+
label="Toggle orientation"
44+
icon={<span style={{ fontSize: '2em' }}>🔄</span>}
45+
/>
46+
</TldrawUiMenuGroup>
47+
<TldrawUiMenuGroup id="controls">
48+
<SelectToolbarItem />
49+
<HandToolbarItem />
50+
<EraserToolbarItem />
51+
</TldrawUiMenuGroup>
52+
<TldrawUiMenuGroup id="pens">
53+
<DrawToolbarItem />
54+
<HighlightToolbarItem />
55+
<LaserToolbarItem />
56+
</TldrawUiMenuGroup>
57+
<TldrawUiMenuGroup id="shapes">
58+
<RectangleToolbarItem />
59+
<EllipseToolbarItem />
60+
<TriangleToolbarItem />
61+
<DiamondToolbarItem />
62+
<HexagonToolbarItem />
63+
64+
<OvalToolbarItem />
65+
<RhombusToolbarItem />
66+
<StarToolbarItem />
67+
<CloudToolbarItem />
68+
</TldrawUiMenuGroup>
69+
<TldrawUiMenuGroup id="arrows">
70+
<ArrowLeftToolbarItem />
71+
<ArrowUpToolbarItem />
72+
<ArrowDownToolbarItem />
73+
<ArrowRightToolbarItem />
74+
</TldrawUiMenuGroup>
75+
</DefaultToolbar>
76+
),
77+
}
78+
}, [orientation])
79+
80+
return (
81+
<div className="tldraw__editor">
82+
<Tldraw components={components} />
83+
</div>
84+
)
85+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Vertical toolbar
3+
component: ./VerticalToolbarExample.tsx
4+
category: ui
5+
keyword: [custom, vertical, toolbar]
6+
---
7+
8+
Switch from a horizontal toolbar at the bottom of the screen to a vertical one on the left.
9+
10+
---
11+
12+
Tldraw supports a vertical toolbar out of the box. Override the toolbar component to set the orientation of the default toolbar to vertical.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { DefaultToolbar, TLComponents, Tldraw } from 'tldraw'
2+
import 'tldraw/tldraw.css'
3+
4+
const components: TLComponents = {
5+
Toolbar: () => <DefaultToolbar orientation="vertical" />,
6+
}
7+
8+
export default function BasicExample() {
9+
return (
10+
<div className="tldraw__editor">
11+
<Tldraw components={components} />
12+
</div>
13+
)
14+
}

apps/examples/src/styles.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ li.examples__sidebar__item {
175175
overflow: hidden;
176176
text-overflow: ellipsis;
177177
white-space: nowrap;
178+
padding-right: 32px;
178179
}
179180

180181
.examples__sidebar__item__link {

packages/tldraw/api-report.api.md

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -986,6 +986,16 @@ export function DefaultToolbarContent(): JSX_2.Element;
986986
export interface DefaultToolbarProps {
987987
// (undocumented)
988988
children?: ReactNode;
989+
// (undocumented)
990+
maxItems?: number;
991+
// (undocumented)
992+
maxSizePx?: number;
993+
// (undocumented)
994+
minItems?: number;
995+
// (undocumented)
996+
minSizePx?: number;
997+
// (undocumented)
998+
orientation?: 'horizontal' | 'vertical';
989999
}
9901000

9911001
// @public (undocumented)
@@ -2169,12 +2179,24 @@ export function OpacitySlider(): JSX_2.Element | null;
21692179
export function OvalToolbarItem(): JSX_2.Element;
21702180

21712181
// @public (undocumented)
2172-
export function OverflowingToolbar({ children }: OverflowingToolbarProps): JSX_2.Element;
2182+
export function OverflowingToolbar({ children, orientation, sizingParentClassName, minItems, minSizePx, maxItems, maxSizePx, }: OverflowingToolbarProps): JSX_2.Element;
21732183

21742184
// @public (undocumented)
21752185
export interface OverflowingToolbarProps {
21762186
// (undocumented)
21772187
children: React.ReactNode;
2188+
// (undocumented)
2189+
maxItems: number;
2190+
// (undocumented)
2191+
maxSizePx: number;
2192+
// (undocumented)
2193+
minItems: number;
2194+
// (undocumented)
2195+
minSizePx: number;
2196+
// (undocumented)
2197+
orientation: 'horizontal' | 'vertical';
2198+
// (undocumented)
2199+
sizingParentClassName: string;
21782200
}
21792201

21802202
// @public (undocumented)
@@ -2982,6 +3004,9 @@ export function TldrawUiButtonLabel({ children }: TLUiButtonLabelProps): JSX_2.E
29823004
// @public (undocumented)
29833005
export const TldrawUiButtonPicker: <T extends string>(props: TLUiButtonPickerProps<T>) => ReactElement;
29843006

3007+
// @public
3008+
export const TldrawUiColumn: ForwardRefExoticComponent<TLUiLayoutProps & RefAttributes<HTMLDivElement>>;
3009+
29853010
// @public (undocumented)
29863011
export function TldrawUiComponentsProvider({ overrides, children, }: TLUiComponentsProviderProps): JSX_2.Element;
29873012

@@ -3075,6 +3100,27 @@ export function TldrawUiMenuSubmenu<Translation extends string = string>({ id, d
30753100
// @public (undocumented)
30763101
export function TldrawUiMenuToolItem({ toolId, ...rest }: TLUiMenuToolItemProps): JSX_2.Element | null;
30773102

3103+
// @public (undocumented)
3104+
export interface TldrawUiOrientationContext {
3105+
// (undocumented)
3106+
orientation: 'horizontal' | 'vertical';
3107+
// (undocumented)
3108+
tooltipSide: 'bottom' | 'left' | 'right' | 'top';
3109+
}
3110+
3111+
// @public (undocumented)
3112+
export function TldrawUiOrientationProvider({ children, orientation, tooltipSide, }: TldrawUiOrientationProviderProps): JSX_2.Element;
3113+
3114+
// @public (undocumented)
3115+
export interface TldrawUiOrientationProviderProps {
3116+
// (undocumented)
3117+
children: ReactNode;
3118+
// (undocumented)
3119+
orientation: 'horizontal' | 'vertical';
3120+
// (undocumented)
3121+
tooltipSide?: 'bottom' | 'left' | 'right' | 'top';
3122+
}
3123+
30783124
// @public (undocumented)
30793125
export function TldrawUiPopover({ id, children, onOpenChange, open, className }: TLUiPopoverProps): JSX_2.Element;
30803126

@@ -3115,7 +3161,7 @@ export const TldrawUiToolbarToggleGroup: ({ children, className, type, ...props
31153161
export const TldrawUiToolbarToggleItem: ({ children, className, type, value, tooltip, ...props }: TLUiToolbarToggleItemProps) => JSX_2.Element;
31163162

31173163
// @public (undocumented)
3118-
export function TldrawUiTooltip({ children, content, side, sideOffset, disabled, }: TldrawUiTooltipProps): JSX_2.Element;
3164+
export const TldrawUiTooltip: React_3.ForwardRefExoticComponent<TldrawUiTooltipProps & React_3.RefAttributes<HTMLButtonElement>>;
31193165

31203166
// @public (undocumented)
31213167
export interface TldrawUiTooltipProps {
@@ -3998,6 +4044,8 @@ export interface TLUiLayoutProps extends HTMLAttributes<HTMLDivElement> {
39984044
asChild?: boolean;
39994045
// (undocumented)
40004046
children: ReactNode;
4047+
// (undocumented)
4048+
tooltipSide?: 'bottom' | 'left' | 'right' | 'top';
40014049
}
40024050

40034051
// @public (undocumented)
@@ -4290,7 +4338,9 @@ export interface TLUiToolbarProps extends React_3.HTMLAttributes<HTMLDivElement>
42904338
// (undocumented)
42914339
label: string;
42924340
// (undocumented)
4293-
orientation?: 'grid' | 'horizontal';
4341+
orientation?: 'grid' | 'horizontal' | 'vertical';
4342+
// (undocumented)
4343+
tooltipSide?: 'bottom' | 'left' | 'right' | 'top';
42944344
}
42954345

42964346
// @public (undocumented)
@@ -5089,6 +5139,9 @@ export function useShowCollaborationUi(): boolean;
50895139
// @public (undocumented)
50905140
export function useTldrawUiComponents(): TLUiComponents;
50915141

5142+
// @public (undocumented)
5143+
export function useTldrawUiOrientation(): TldrawUiOrientationContext;
5144+
50925145
// @public (undocumented)
50935146
export function useToasts(): TLUiToastsContextType;
50945147

packages/tldraw/src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,13 @@ export { AccessibilityMenu } from './lib/ui/components/AccessibilityMenu'
2626
export { ColorSchemeMenu } from './lib/ui/components/ColorSchemeMenu'
2727
export { DefaultDialogs } from './lib/ui/components/Dialogs'
2828
export {
29+
TldrawUiColumn,
2930
TldrawUiGrid,
31+
TldrawUiOrientationProvider,
3032
TldrawUiRow,
33+
useTldrawUiOrientation,
34+
type TldrawUiOrientationContext,
35+
type TldrawUiOrientationProviderProps,
3136
type TLUiLayoutProps,
3237
} from './lib/ui/components/primitives/layout'
3338
export {

0 commit comments

Comments
 (0)