diff --git a/packages/docs/stories/Dropdown.stories.tsx b/packages/docs/stories/Dropdown.stories.tsx
index a1dc5a94..4c3e142e 100644
--- a/packages/docs/stories/Dropdown.stories.tsx
+++ b/packages/docs/stories/Dropdown.stories.tsx
@@ -397,29 +397,6 @@ export const OverlappingDropdown: Story = {
},
};
-export const OutOfBoundsAtBottom: Story = {
- args: {
- children: (
-
- - 0px
- - 4px
- - 9px
- - 18px
- - 36px
- - 54px
- - 72px
- - 144px
- - 167px
- - 198px
-
- ),
- className: 'out-of-bounds-example',
- isSearchable: true,
- name: 'outofboundsatbottom',
- placeholder: 'Show above',
- },
-};
-
export const OutOfBoundsAtRight: Story = {
args: {
children: (
diff --git a/packages/docs/stories/useIsOutOfBounds.css b/packages/docs/stories/useIsOutOfBounds.css
new file mode 100644
index 00000000..e9453ce4
--- /dev/null
+++ b/packages/docs/stories/useIsOutOfBounds.css
@@ -0,0 +1,36 @@
+.out-of-bounds-example.uktdropdown {
+ position: absolute;
+ bottom: 50px;
+}
+.out-of-bounds-example input {
+ width: 150px;
+}
+
+.out-of-bounds-example .uktdropdown-body {
+ width: 250px;
+}
+
+.position-right.uktdropdown {
+ position: absolute;
+ right: 70px;
+}
+
+.out-of-bounds-example.no-direction-change.uktdropdown {
+ position: relative;
+ margin-top: 100px;
+}
+
+.out-of-bounds-example.no-direction-change.uktdropdown .uktdropdown-body {
+ top: 100%;
+}
+
+#anchor--uikit-controls-dropdown--out-of-bounds-with-no-direction-change
+ .innerZoomElementWrapper
+ > * {
+ overflow: auto;
+ height: 200px;
+}
+
+#anchor--uikit-controls-dropdown--out-of-bounds-with-no-direction-change .sb-story {
+ height: 230px;
+}
diff --git a/packages/docs/stories/useIsOutOfBounds.stories.tsx b/packages/docs/stories/useIsOutOfBounds.stories.tsx
new file mode 100644
index 00000000..fcbc1cc2
--- /dev/null
+++ b/packages/docs/stories/useIsOutOfBounds.stories.tsx
@@ -0,0 +1,157 @@
+import * as React from 'react';
+
+import Dropdown from '../../dropdown/src/Dropdown.js';
+
+import './Dropdown.css';
+import './useIsOutOfBounds.css';
+
+import type { Meta, StoryObj } from '@storybook/react';
+
+const meta: Meta = {
+ component: Dropdown,
+ parameters: {
+ docs: {
+ description: {
+ component:
+ `\`useIsOutOfBounds\` is a React hook that returns an object indicating if the
+current component is out of the bounds of its nearest ancestor that doesn’t have overflow: visible.
+The return value is
+\`
+type OutOfBounds = {
+ bottom: boolean;
+ hasLayout: boolean;
+ left: boolean;
+ maxHeight: null | number;
+ maxWidth: null | number;
+ right: boolean;
+ top: boolean;
+};
+\`
+It is used by in @acusti/dropdown to automatically position the dropdown in the direction
+where there is room for it to render, so this story uses \`\` to illustrate that behavior.
+
+`,
+ },
+ },
+ },
+ //https://storybook.js.org/docs/react/writing-docs/autodocs#setup-automated-documentation
+ tags: ['autodocs'],
+ title: 'UIKit/Hooks/useIsOutOfBounds',
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+const list = (
+
+ - Brunei Darussalam
+ - Cambodia
+ - Indonesia
+ - Laos
+ - Malaysia
+ - Myanmar (Burma)
+ - Philippines
+ - Singapore
+ - Thailand
+ - Timor-Leste (East Timor)
+ - Vietnam
+
+);
+
+export const NotOutOfBounds: Story = {
+ args: {
+ children: list,
+ className: 'not-out-of-bounds-example',
+ isSearchable: true,
+ name: 'notoutofbounds',
+ placeholder: 'Default behavior',
+ },
+};
+
+export const OutOfBoundsAtBottom: Story = {
+ args: {
+ children: list,
+ className: 'out-of-bounds-example',
+ isSearchable: true,
+ name: 'outofboundsatbottom',
+ placeholder: 'Show above',
+ },
+};
+
+export const OutOfBoundsAtRight: Story = {
+ args: {
+ children: list,
+ className: 'out-of-bounds-example position-right',
+ isSearchable: true,
+ name: 'outofboundsatright',
+ placeholder: 'Show above & to the left',
+ },
+};
+
+export const OutOfBoundsTopAndBottom: Story = {
+ args: {
+ children: (
+
+ - Algeria
+ - Angola
+ - Benin
+ - Botswana
+ - Burkina Faso
+ - Burundi
+ - Cabo Verde
+ - Cameroon
+ - Central African Republic
+ - Chad
+ - Comoros
+ - Congo, Democratic Republic of the
+ - Congo, Republic of the
+ - Cote d'Ivoire
+ - Djibouti
+ - Egypt
+ - Equatorial Guinea
+ - Eritrea
+ - Eswatini
+ - Ethiopia
+ - Gabon
+ - Gambia
+ - Ghana
+ - Guinea
+ - Guinea-Bissau
+ - Kenya
+ - Lesotho
+ - Liberia
+ - Libya
+ - Madagascar
+ - Malawi
+ - Mali
+ - Mauritania
+ - Mauritius
+ - Morocco
+ - Mozambique
+ - Namibia
+ - Niger
+ - Nigeria
+ - Rwanda
+ - Sao Tome and Principe
+ - Senegal
+ - Seychelles
+ - Sierra Leone
+ - Somalia
+ - South Africa
+ - South Sudan
+ - Sudan
+ - Tanzania
+ - Togo
+ - Tunisia
+ - Uganda
+ - Zambia
+ - Zimbabwe
+
+ ),
+ className: 'out-of-bounds-top-and-bottom-example',
+ isSearchable: true,
+ name: 'outofboundstopandbottom',
+ placeholder: 'long list',
+ },
+};