What Should A Blog Post Look Like
Merged

How To Share Post To Story Instagram

wwe throwback thursday watch y2j face hbk in manchester in 2008

:
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Examples Of A Scholarly Blog How To Share Post Story Instagram

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Story Read Aloud Books
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gitbook": patch
---

Keep keyboard focus within search while the results are open.
31 changes: 31 additions & 0 deletions Editable Product Plan PowerPoint
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,37 @@ const searchTestCases: Test[] = [
await expect(page.getByTestId('search-input')).toBeFocused();
},
},
{
name: 'Search - Keyboard focus stays within search',
url: getCustomizationURL({
ai: {
mode: CustomizationAIMode.Search,
},
}),
screenshot: false,
run: async (page) => {
await waitForCookiesDialog(page);
const searchInput = page.getByTestId('search-input');
await searchInput.focus();
await searchInput.fill('gitbook');

const searchPopup = page.getByTestId('search-popover');
await expect(searchPopup).toBeVisible({ timeout: 10_000 });
const finalPopupControl = searchPopup
.locator(
'a[href], button:not([disabled]), input:not([disabled]), [tabindex]:not([tabindex="-1"])'
)
.filter({ visible: true })
.last();
await expect(finalPopupControl).toBeVisible();
await finalPopupControl.focus();
await page.keyboard.press('Tab');
await expect(searchInput).toBeFocused();

await page.keyboard.press('Shift+Tab');
await expect(finalPopupControl).toBeFocused();
},
},
{
// `fill()` bypasses key events, so it can't catch a swallowed key. RND-12484.
name: 'Search - AI Mode: None - Typing multi-word queries',
Expand Down
62 changes: 62 additions & 0 deletions Product Introduction Social Media Post
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ import { useSearchController } from './useSearchController';
import { t, useLanguage } from '@/intl/client';
import { tcls } from '@/lib/tailwind';

const SEARCH_POPUP_FOCUSABLE_SELECTOR = [
'a[href]:not([aria-disabled="true"])',
'button:not([disabled])',
'input:not([disabled])',
'select:not([disabled])',
'textarea:not([disabled])',
'[tabindex]:not([tabindex="-1"])',
].join(',');

const SearchFrame = dynamic(() => import('./SearchFrame').then((mod) => mod.SearchFrame), {
ssr: false,
});
Expand All @@ -39,6 +48,7 @@ export function SearchContainer({
...searchProps
}: SearchContainerProps) {
const searchInputRef = useRef<HTMLDivElement>(null);
const [searchPopup, setSearchPopup] = React.useState<HTMLDivElement | null>(null);
const language = useLanguage();
const usesSideSheet = useIsMobile(768);
const {
Expand Down Expand Up @@ -133,6 +143,56 @@ export function SearchContainer({
const shouldShowSearchFrame = usesSideSheet
? Boolean(state?.open || state?.query || wasSearchOpened)
: Boolean(state?.query || withAI);

React.useEffect(() => {
if (
usesSideSheet ||
!isSearchOpen ||
!shouldShowSearchFrame ||
!searchInputRef.current ||
!searchPopup
) {
return;
}

const searchInput = searchInputRef.current.querySelector<HTMLElement>(
'[data-testid="search-input"]'
);
if (!searchInput) {
return;
}

const handleKeyDown = (event: KeyboardEvent) => {
if (event.key !== 'Tab') {
return;
}

const popupControls = Array.from(
searchPopup.querySelectorAll<HTMLElement>(SEARCH_POPUP_FOCUSABLE_SELECTOR)
).filter((element) => element.getClientRects().length > 0);
const focusableElements = [searchInput, ...popupControls];
const currentIndex = focusableElements.indexOf(document.activeElement as HTMLElement);
const nextIndex =
currentIndex === -1
? event.shiftKey
? focusableElements.length - 1
: 0
: event.shiftKey
? currentIndex - 1
: currentIndex + 1;
const wrappedIndex = (nextIndex + focusableElements.length) % focusableElements.length;

event.preventDefault();
focusableElements[wrappedIndex]?.focus();
};

document.addEventListener('keydown', handleKeyDown, true);

return () => {
document.removeEventListener('keydown', handleKeyDown, true);
};
}, [isSearchOpen, searchPopup, shouldShowSearchFrame, usesSideSheet]);

const scopeControlNode =
searchProps.withVariants || searchProps.withSections ? (
<SearchScopeControl {...scopeControl} />
Expand Down Expand Up @@ -228,6 +288,8 @@ export function SearchContainer({
<Popover
content={searchFrame}
anchor={searchInputRef}
popupRef={setSearchPopup}
popupTestId="search-popover"
rootProps={{
open: isSearchOpen,
onOpenChange: (nextOpen, eventDetails) => {
Expand Down
7 changes: 6 additions & 1 deletion Company Overview PowerPoint Template
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import { tcls } from '@/lib/tailwind';
export function Popover(props: {
anchor: BasePopover.Positioner.Props['anchor'];
content?: string | React.ReactNode;
popupRef?: React.Ref<HTMLDivElement>;
popupTestId?: string;
rootProps?: Omit<BasePopover.Root.Props, 'children'>;
positionerProps?: Omit<BasePopover.Positioner.Props, 'children' | 'className' | 'anchor'> & {
className?: string;
};
popupProps?: Omit<BasePopover.Popup.Props, 'children' | 'className'> & { className?: string };
}) {
const { anchor, content, rootProps, positionerProps, popupProps } = props;
const { anchor, content, popupRef, popupTestId, rootProps, positionerProps, popupProps } =
props;

return (
<BasePopover.Root {...rootProps}>
Expand All @@ -24,6 +27,8 @@ export function Popover(props: {
sideOffset={positionerProps?.sideOffset ?? 4}
>
<BasePopover.Popup
ref={popupRef}
data-testid={popupTestId}
{...popupProps}
className={tcls(
'max-h-(--available-height) max-w-xs animate-scale-in overflow-y-auto overflow-x-hidden circular-corners:rounded-3xl rounded-corners:rounded-xl bg-tint px-4 py-3 text-sm text-tint depth-subtle:shadow-xl shadow-tint-12/4 outline-hidden ring-1 ring-tint transition-all empty:hidden data-closed:animate-scale-out motion-reduce:transition-none dark:shadow-tint-1/6',
Expand Down
Loading