diff --git a/Documentation/Toolbar/fan-out.md b/Documentation/Toolbar/fan-out.md
index 49d46f0..e0b8b0c 100644
--- a/Documentation/Toolbar/fan-out.md
+++ b/Documentation/Toolbar/fan-out.md
@@ -21,6 +21,18 @@ By default the panel fans out to the right. Use `fanOutDirection='left'` when th
```
+You can also fan out vertically:
+
+```tsx
+
+ ...
+
+
+
+ ...
+
+```
+
## ReactNode Icons
Like `ToolbarButton`, the `icon` prop accepts a `string | ReactNode`. Pass any React element as the trigger icon:
diff --git a/Source/Toolbar/Toolbar.css b/Source/Toolbar/Toolbar.css
index 87c43fb..3b05877 100644
--- a/Source/Toolbar/Toolbar.css
+++ b/Source/Toolbar/Toolbar.css
@@ -163,6 +163,23 @@
clip-path: inset(0 0 0 100% round 1rem);
}
+.toolbar-fanout-panel--up {
+ top: auto;
+ right: auto;
+ bottom: calc(100% + 0.5rem);
+ left: 50%;
+ transform: translateX(-50%);
+ clip-path: inset(100% 0 0 0 round 1rem);
+}
+
+.toolbar-fanout-panel--down {
+ top: calc(100% + 0.5rem);
+ right: auto;
+ left: 50%;
+ transform: translateX(-50%);
+ clip-path: inset(0 0 100% 0 round 1rem);
+}
+
/* Expanded state — fully visible, pointer events restored */
.toolbar-fanout-panel--visible {
clip-path: inset(0 0 0 0 round 1rem);
diff --git a/Source/Toolbar/Toolbar.stories.tsx b/Source/Toolbar/Toolbar.stories.tsx
index 88fdfb6..d47e9a8 100644
--- a/Source/Toolbar/Toolbar.stories.tsx
+++ b/Source/Toolbar/Toolbar.stories.tsx
@@ -318,6 +318,26 @@ export const WithFanOut: Story = {
},
};
+/** Demonstrates a {@link ToolbarFanOutItem} that fans out downwards. */
+export const WithFanOutDown: Story = {
+ render: () => (
+
+
+
+
+
+
+
+
+
+ ),
+};
+
/** Demonstrates a folder with a single nested button. */
export const WithFolderOneButton: Story = {
render: () => (
diff --git a/Source/Toolbar/ToolbarFanOutItem.tsx b/Source/Toolbar/ToolbarFanOutItem.tsx
index aecba6c..2bd591a 100644
--- a/Source/Toolbar/ToolbarFanOutItem.tsx
+++ b/Source/Toolbar/ToolbarFanOutItem.tsx
@@ -19,7 +19,7 @@ export interface ToolbarFanOutItemProps {
tooltipPosition?: TooltipPosition;
/** Direction the panel fans out from the trigger button (default: 'right'). */
- fanOutDirection?: 'right' | 'left';
+ fanOutDirection?: 'right' | 'left' | 'up' | 'down';
/** The toolbar items to render inside the fan-out panel. */
children: ReactNode;
diff --git a/Source/Toolbar/for_ToolbarFanOutItem/when_direction_is_set/and_item_is_rendered.ts b/Source/Toolbar/for_ToolbarFanOutItem/when_direction_is_set/and_item_is_rendered.ts
new file mode 100644
index 0000000..17e2300
--- /dev/null
+++ b/Source/Toolbar/for_ToolbarFanOutItem/when_direction_is_set/and_item_is_rendered.ts
@@ -0,0 +1,41 @@
+// Copyright (c) Cratis. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+import React from 'react';
+import { renderToStaticMarkup } from 'react-dom/server';
+import { vi } from 'vitest';
+import { ToolbarFanOutItem } from '../../ToolbarFanOutItem';
+
+vi.mock('../../Common/Tooltip', () => ({
+ Tooltip: (props: { children?: React.ReactNode }) => React.createElement('div', null, props.children),
+}));
+
+describe('when ToolbarFanOutItem direction is set and item is rendered', () => {
+ const render = (fanOutDirection?: 'left' | 'right' | 'up' | 'down') =>
+ renderToStaticMarkup(
+ React.createElement(
+ ToolbarFanOutItem,
+ {
+ icon: 'pi pi-th-large',
+ tooltip: 'Shapes',
+ fanOutDirection,
+ },
+ React.createElement('div', null, 'Child'),
+ ),
+ );
+
+ it('should_default_to_right_direction', () => {
+ const html = render();
+ html.should.include('toolbar-fanout-panel--right');
+ });
+
+ it('should_support_up_direction', () => {
+ const html = render('up');
+ html.should.include('toolbar-fanout-panel--up');
+ });
+
+ it('should_support_down_direction', () => {
+ const html = render('down');
+ html.should.include('toolbar-fanout-panel--down');
+ });
+});