Skip to content

Commit 9781181

Browse files
committed
fix: focus now stays on options dropdown after switching display mode
1 parent 62c79ef commit 9781181

2 files changed

Lines changed: 56 additions & 23 deletions

File tree

packages/module/patternfly-docs/content/extensions/chatbot/examples/demos/Chatbot.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,16 +130,16 @@ This demo displays a ChatBot in a static, inline drawer. This demo includes:
130130

131131
```
132132

133-
### Display mode ChatBot
133+
### Display mode switcher
134134

135135
This demo showcases how the ChatBot can be rendered in different display modes to suit various application layouts. It demonstrates how to dynamically change the page structure in response to the user's selection. This demo includes:
136136

137-
1. The ability to switch between Overlay, Docked, and Fullscreen modes using the [`<ChatbotHeaderOptionsDropdown>`](/patternfly-ai/chatbot/ui#header-options) in the header.
138-
2. A conditional page layout that renders the ChatBot:
139-
- As a floating window on top of the page content (Overlay mode).
140-
- Inside a PatternFly `<Drawer>` as a side panel for a docked experience.
141-
- As a top-level component that covers the entire screen (Fullscreen mode).
142-
3. Logic to show or hide the `<ChatbotToggle>` button, which is only present in the default Overlay mode.
137+
1. The ability to switch between overlay, docked, and fullscreen modes using the [`<ChatbotHeaderOptionsDropdown>`](/patternfly-ai/chatbot/ui#header-options) in the header.
138+
2. A conditional page layout that renders the ChatBot for each display mode option:
139+
- **Overlay:** As a floating window on top of the page content.
140+
- **Drawer:** Inside an inline PatternFly `<Drawer>` as a side panel.
141+
- **Fullscreen:** As a top-level component that covers the entire screen for an embedded experience.
142+
3. Logic to show or hide the `<ChatbotToggle>` button, which is only present in the default overlay mode.
143143
4. A [basic ChatBot](#basic-chatbot) with a header, welcome prompt, and message bar to populate the different layouts.
144144

145145
```js file="./ChatbotDisplayMode.tsx" isFullscreen

packages/module/patternfly-docs/content/extensions/chatbot/examples/demos/ChatbotDisplayMode.tsx

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ import {
1818
DrawerContent,
1919
DrawerContentBody,
2020
DrawerPanelContent,
21-
DropdownGroup,
22-
DrawerActions
21+
DropdownGroup
2322
} from '@patternfly/react-core';
2423

2524
import ChatbotToggle from '@patternfly/chatbot/dist/dynamic/ChatbotToggle';
@@ -147,6 +146,8 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
147146
const drawerRef = useRef<HTMLDivElement>();
148147
const [chatbotVisible, setChatbotVisible] = useState<boolean>(true);
149148
const toggleRef = useRef<HTMLButtonElement>(null);
149+
const chatbotRef = useRef<HTMLDivElement>(null);
150+
const [shouldFocusOptions, setShouldFocusOptions] = useState(false);
150151

151152
const [displayMode, setDisplayMode] = useState<ChatbotDisplayMode>(ChatbotDisplayMode.default);
152153

@@ -162,6 +163,23 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
162163
}
163164
}, [messages]);
164165

166+
// Focus options dropdown after display mode changes
167+
useEffect(() => {
168+
if (shouldFocusOptions) {
169+
// Use a more reliable timeout to ensure DOM has updated
170+
const timeoutId = setTimeout(() => {
171+
// Find the options dropdown button via CSS selector since ref forwarding isn't supported
172+
const optionsButton = document.querySelector('.pf-chatbot__button--toggle-options');
173+
if (optionsButton instanceof HTMLElement) {
174+
optionsButton.focus();
175+
}
176+
setShouldFocusOptions(false);
177+
}, 100);
178+
179+
return () => clearTimeout(timeoutId);
180+
}
181+
}, [displayMode, shouldFocusOptions]);
182+
165183
const onSelectModel = (_event: MouseEvent<Element, MouseEvent> | undefined, value: string | number | undefined) => {
166184
setSelectedModel(value as string);
167185
};
@@ -171,6 +189,8 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
171189
value: string | number | undefined
172190
) => {
173191
setDisplayMode(value as ChatbotDisplayMode);
192+
// Flag to focus options dropdown after render
193+
setShouldFocusOptions(true);
174194
};
175195

176196
const generateId = () => {
@@ -283,11 +303,31 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
283303
</PageSidebar>
284304
);
285305

286-
const skipToChatbot = (event: MouseEvent) => {
287-
event.preventDefault();
288-
if (historyRef.current) {
289-
historyRef.current.focus();
306+
const skipToChatbot = (e: MouseEvent) => {
307+
e.preventDefault();
308+
/* eslint-disable indent */
309+
switch (displayMode) {
310+
case ChatbotDisplayMode.default:
311+
if (!chatbotVisible && toggleRef.current) {
312+
toggleRef.current.focus();
313+
}
314+
if (chatbotVisible && chatbotRef.current) {
315+
chatbotRef.current.focus();
316+
}
317+
break;
318+
319+
case ChatbotDisplayMode.docked:
320+
if (chatbotRef.current) {
321+
chatbotRef.current.focus();
322+
}
323+
break;
324+
default:
325+
if (historyRef.current) {
326+
historyRef.current.focus();
327+
}
328+
break;
290329
}
330+
/* eslint-enable indent */
291331
};
292332

293333
const skipToContent = (
@@ -302,7 +342,7 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
302342
};
303343

304344
const chatbotComponent = (
305-
<Chatbot isVisible={chatbotVisible} displayMode={displayMode}>
345+
<Chatbot isVisible={chatbotVisible} displayMode={displayMode} ref={chatbotRef}>
306346
<ChatbotConversationHistoryNav
307347
displayMode={displayMode}
308348
onDrawerToggle={() => {
@@ -364,7 +404,7 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
364404
icon={<OpenDrawerRightIcon aria-hidden />}
365405
isSelected={displayMode === ChatbotDisplayMode.drawer}
366406
>
367-
<span>Dock to window</span>
407+
<span>Drawer</span>
368408
</DropdownItem>
369409
<DropdownItem
370410
value={ChatbotDisplayMode.fullscreen}
@@ -425,14 +465,7 @@ export const ChatbotDisplayModeDemo: FunctionComponent = () => {
425465
/>
426466
) : null;
427467

428-
const panelContent = (
429-
<DrawerPanelContent>
430-
{chatbotComponent}
431-
<DrawerActions>
432-
<ChatbotHeaderCloseButton onClick={() => setIsDrawerOpen(false)} />
433-
</DrawerActions>
434-
</DrawerPanelContent>
435-
);
468+
const panelContent = <DrawerPanelContent>{chatbotComponent}</DrawerPanelContent>;
436469

437470
const pageContent = (
438471
<Page skipToContent={skipToContent} masthead={masthead} sidebar={sidebar} isContentFilled>

0 commit comments

Comments
 (0)