From 7c61dda900509a825b3148993566c28547c9b208 Mon Sep 17 00:00:00 2001 From: Konrad Michalik Date: Tue, 23 Jun 2026 14:12:42 +0200 Subject: [PATCH 1/2] feat: Add initial docstrings for iOS Stack v5 header --- .../header/StackHeaderConfig.ios.types.ts | 191 ++++++++++++++++++ .../header/ios/StackHeaderMenu.ios.types.ts | 151 ++++++++++++++ 2 files changed, 342 insertions(+) diff --git a/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts b/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts index 88c9deb29a..3a89f4d325 100644 --- a/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts +++ b/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts @@ -2,50 +2,194 @@ import type { ReactElement } from 'react'; import type { StackHeaderMenuIOS } from './ios/StackHeaderMenu.ios.types'; export interface StackHeaderBaseItemIOS { + /** + * @summary A unique identifier within the screen header. + * + * @platform iOS + */ key: string; + /** + * @summary A label for the item that is displayed in the header. + * + * @platform iOS + */ label?: string | undefined; } export interface SupportsMenuIOS { + /** + * @summary Menu definition for the context menu that appears when item is tapped. + * + * @platform iOS + */ menu?: StackHeaderMenuIOS | undefined; } +/** + * @summary Native header item with text label. + * + * @platform iOS + */ export interface StackHeaderInlineItemIOS extends StackHeaderBaseItemIOS, SupportsMenuIOS { + /** + * @summary Marks this object as a header item definition. + * + * @platform iOS + */ type: 'item'; } +/** + * @summary Header item with custom view. + * + * @platform iOS + */ export interface StackHeaderInlineCustomItemIOS extends SupportsMenuIOS { + /** + * @summary A unique identifier within the screen header. + * + * @platform iOS + */ key: string; + /** + * @summary Marks this object as a header item definition. + * + * @platform iOS + */ type: 'item'; + /** + * @summary A function that renders the custom view. + * + * @description + * The subview is sized by React Native's layout engine but positioned by the + * platform native layout. Each item's size is calculated independently and will + * not respect flex layout. Use static width and height for best results. + * + * @platform iOS + */ render: () => ReactElement; } +/** + * @summary A spacer item for visual separation of items. + * + * @description Separates items defined in {@link StackHeaderConfigPropsIOS.leadingItems | leadingItems} + * and {@link StackHeaderConfigPropsIOS.trailingItems | trailingItems}. The fixed size spacing works + * for iOS 18 and below, for iOS 26 it only splits liquid glass bubble for two adjacent items. + * + * @platform iOS + */ interface StackHeaderFixedSpacerItemIOS { + /** + * @summary A unique identifier within the screen header. + * + * @platform iOS + */ key: string; + /** + * @summary Marks this object as a spacer definition. + * + * @platform iOS + */ type: 'spacer'; + /** + * @summary Marks this object as a fixed-size spacer definition. + * + * @platform iOS + */ sizing: 'fixed'; + /** + * @summary Specifies space width between adjacent header items. + * + * @platform iOS + */ width: number; } +/** + * @summary A spacer item for visual separation of items. + * + * @description Separates items defined in {@link StackHeaderConfigPropsIOS.leadingItems | leadingItems} + * and {@link StackHeaderConfigPropsIOS.trailingItems | trailingItems}. + * For iOS 26 it splits liquid glass bubble for two adjacent items. + * + * @platform iOS + */ interface StackHeaderFlexibleSpacerItemIOS { + /** + * @summary A unique identifier within the screen header. + * + * @platform iOS + */ key: string; + /** + * @summary Marks this object as a spacer definition. + * + * @platform iOS + */ type: 'spacer'; + /** + * @summary Marks this object as a flexible-size spacer definition. + * + * @platform iOS + */ sizing: 'flexible'; } +/** + * @summary A header spacer item type + */ export type StackHeaderSpacerItemIOS = | StackHeaderFixedSpacerItemIOS | StackHeaderFlexibleSpacerItemIOS; export interface StackHeaderTitleCustomItemIOS { + /** + * @summary A unique identifier within the screen header. + * + * @platform iOS + */ key: string; + /** + * @summary A function that renders the custom view. + * + * @description + * The subview is sized by React Native's layout engine but positioned by the + * platform native layout. Each item's size is calculated independently and will + * not respect flex layout. Use static width and height for best results. + * + * Note: Due to layout process limitations, text view resizing and ellipsizing will not work. + * For text-only elements that should ellipsize is recommended to use regular `title` instead. + * + * @platform iOS + */ render: () => ReactElement; } export interface StackHeaderConfigPropsIOS { + /** + * @summary Custom item to display as a subtitle. + * + * @description Takes precedence over subtitle text. + * + * @platform iOS + * + * @supported iOS 26 and higher + */ subtitleItem?: StackHeaderTitleCustomItemIOS | undefined; + /** + * @summary A list of items placed beginning from the leading edge. + * + * @description Items are placed directly to the right of back button, if present. + * If there is not enough space to fit all leading items at once, they are all moved to overflow menu. + * This differs from trailing items, which are moved one by one. + * + * Note: Custom items are not put into overflow menu, but are removed entirely. + * + * @platform iOS + */ leadingItems?: | ( | StackHeaderInlineItemIOS @@ -53,7 +197,22 @@ export interface StackHeaderConfigPropsIOS { | StackHeaderSpacerItemIOS )[] | undefined; + /** + * @summary Custom item to display as a title. + * + * @description Takes precedence over title text. + * + * @platform iOS + */ titleItem?: StackHeaderTitleCustomItemIOS | undefined; + /** + * @summary A list of items placed beginning from the trailing edge. + * If there is not enough space to fit some items, they are moved to the overflow menu, one by one. + * + * Note: Custom items are not put into overflow menu, but are removed entirely. + * + * @platform iOS + */ trailingItems?: | ( | StackHeaderInlineItemIOS @@ -61,9 +220,41 @@ export interface StackHeaderConfigPropsIOS { | StackHeaderSpacerItemIOS )[] | undefined; + /** + * @summary Large title text, displayed when `largeTitleEnabled = true`. + * + * @description When ScrollView is present on the screen, large header is displayed only when + * fully scrolled to top, otherwise it collapses to regular header. If `largeTitle` is not defined, + * it fallbacks to regular title. + * + * @platform iOS + */ largeTitle?: string | undefined; + /** + * @summary Tells the header to display large title. It collapses to regular header when scrolling. + * + * @platform iOS + */ largeTitleEnabled?: boolean | undefined; + /** + * @summary Large subtitle text, displayed when `largeTitleEnabled = true`. + * + * @description When ScrollView is present on the screen, large header is displayed only when + * fully scrolled to top, otherwise it collapses to regular header. If `largeSubititle` is not defined, + * it fallbacks to regular subtitle. + * + * @platform iOS + * + * @supported iOS 26 and higher + */ largeSubtitle?: string | undefined; + /** + * @summary Custom item to display as a subtitle for large header. Takes precedence over largeSubtitle text. + * + * @platform iOS + * + * @supported iOS 26 and higher + */ largeSubtitleItem?: StackHeaderTitleCustomItemIOS | undefined; } diff --git a/src/components/gamma/stack/header/ios/StackHeaderMenu.ios.types.ts b/src/components/gamma/stack/header/ios/StackHeaderMenu.ios.types.ts index 53445514c7..c642bd06c2 100644 --- a/src/components/gamma/stack/header/ios/StackHeaderMenu.ios.types.ts +++ b/src/components/gamma/stack/header/ios/StackHeaderMenu.ios.types.ts @@ -1,21 +1,172 @@ +/** + * @summary Represents a single actionable item inside a {@link StackHeaderMenuIOS} menu. + * + * @description + * A menu item is a leaf element that the user can interact with. + * Depending on its {@link StackHeaderMenuItemIOS.itemType | itemType}, the item + * behaves as a one-shot action or a stateful toggle. + * + * @platform ios + */ export interface StackHeaderMenuItemIOS { + /** + * @summary Unique identifier of the menu item. + * + * @description + * Used to locate the item inside a menu tree and to identify selected items + * in {@link StackHeaderMenuIOS.onSelectionChanged} callback. + * + * @platform ios + */ id: string; + /** + * @summary Marks this object as a menu item definition. + * + * @platform ios + */ type: 'menuItem'; + /** + * @summary Title displayed for the menu item. + * + * @platform ios + */ title?: string | undefined; + /** + * @summary Determines the behavior of the menu item. + * + * @description + * The following values are available: + * - `action` - a button that fires {@link StackHeaderMenuItemIOS.onPress | onPress} + * when tapped. Cannot be used inside a `singleSelection` menu. + * - `toggle` - a stateful item whose on/off state is tracked automatically. + * Toggle items do not fire `onPress`; instead, parent menu + * (or Single Selection Root in case of {@link StackHeaderMenuIOS.singleSelection | singleSelection}) + * is passed currently selected items with {@link StackHeaderMenuIOS.onSelectionChanged | onSelectionChanged} + * - `automatic` - resolved at render time: becomes `toggle` when the item is + * under `singleSelection` hierarchy, `action` otherwise. + * + * @default automatic + * + * @platform ios + */ itemType?: 'action' | 'toggle' | 'automatic' | undefined; + /** + * @summary Initial on/off state of a toggle item. + * + * @description + * Only meaningful when {@link StackHeaderMenuItemIOS.itemType | itemType} + * resolves to `toggle`. Inside a `singleSelection` hierarchy, at most one + * item can set this to `true`. + * + * @default false + * + * @platform ios + */ initialToggleState?: boolean | undefined; + /** + * @summary Callback invoked when the menu item is pressed. + * + * @description + * Fires only for items whose effective type is `action`. For toggle items, + * this callback will not fire — use + * {@link StackHeaderMenuIOS.onSelectionChanged | onSelectionChanged} on the + * parent menu instead. + * + * @platform ios + */ onPress?: () => void | undefined; } +/** + * @summary Represents a menu (or submenu) that groups + * {@link StackHeaderMenuElementIOS} children. + * + * @description + * A menu is a container that can hold both leaf items + * ({@link StackHeaderMenuItemIOS}) and nested menus. Set + * {@link StackHeaderMenuIOS.singleSelection | singleSelection} to `true` to + * make the menu behave like radio group across its entire hierarchy. + * + * Note: The topmost menu that enables this prop becomes Single Selection Root. + * Only the root receives {@link StackHeaderMenuIOS.onSelectionChanged | onSelectionChanged} + * event, with exactly one item id passed to the callback. Only one item may be selected, + * across the whole hierarchy under Single Selection Root (even when mixing items and nested menus). + * Previously selected item is deselected automatically. + * Multiple Single Selection Roots may exist only if their hierarchy is completely separate. + * + * @platform ios + */ export interface StackHeaderMenuIOS { + /** + * @summary Unique identifier of the menu. + * + * @description + * Used to locate the menu inside a tree and as the reference when querying or + * manipulating menu state. + * + * @platform ios + */ id: string; + /** + * @summary Marks this object as a menu definition. + * + * @platform ios + */ type: 'menu'; + /** + * @summary Title displayed for the menu. + * + * @platform ios + */ title?: string | undefined; + /** + * @summary Enables single selection mode for this menu and its descendants. + * + * @description + * The topmost menu with `singleSelection` enabled becomes Single Selection Root. + * At most one toggle item in the entire hierarchy rooted at this + * menu can be selected at a time. + * + * Items with `itemType` set to `automatic` are resolved to `toggle` inside a + * `singleSelection` hierarchy. `action` items are disallowed. + * + * @default false + * @platform ios + */ singleSelection?: boolean | undefined; + /** + * @summary Child elements of this menu. + * + * @description + * Each child is either a {@link StackHeaderMenuItemIOS} (leaf) or another + * {@link StackHeaderMenuIOS}, allowing arbitrarily nested menu trees. + * + * @platform ios + */ children: StackHeaderMenuElementIOS[]; + /** + * @summary Callback invoked when the set of selected toggle items changes. + * + * @description + * Receives an array of IDs of all currently selected toggle items in this + * menu's hierarchy. For Single Selection Root, always returns one item. + * When defined below Single Selection Root, the callback doesn't fire. + * In regular non-single-selection case, only changes to direct children are reflected. + * + * @platform ios + */ onSelectionChanged?: (selectedMenuElementIds: string[]) => void; } +/** + * @summary A menu element type. + * + * @description + * A menu element is either a {@link StackHeaderMenuIOS | menu} (container with + * children) or a {@link StackHeaderMenuItemIOS | menu item} (actionable leaf). + * + * @platform ios + */ export type StackHeaderMenuElementIOS = | StackHeaderMenuIOS | StackHeaderMenuItemIOS; From 18a477f25094a6f4d2dcc13969e68f0fdc2873b0 Mon Sep 17 00:00:00 2001 From: Konrad Michalik Date: Wed, 24 Jun 2026 09:34:38 +0200 Subject: [PATCH 2/2] apply review suggestions --- .../header/StackHeaderConfig.ios.types.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts b/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts index 3a89f4d325..75b2de37f6 100644 --- a/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts +++ b/src/components/gamma/stack/header/StackHeaderConfig.ios.types.ts @@ -160,8 +160,10 @@ export interface StackHeaderTitleCustomItemIOS { * platform native layout. Each item's size is calculated independently and will * not respect flex layout. Use static width and height for best results. * - * Note: Due to layout process limitations, text view resizing and ellipsizing will not work. - * For text-only elements that should ellipsize is recommended to use regular `title` instead. + * Note: Due to layout process limitations, text view will not resize and + * ellipsize to fit available space without manually setting desired view + * width. For text-only elements that should ellipsize it is recommended to + * use regular `title` instead. * * @platform iOS */ @@ -180,13 +182,13 @@ export interface StackHeaderConfigPropsIOS { */ subtitleItem?: StackHeaderTitleCustomItemIOS | undefined; /** - * @summary A list of items placed beginning from the leading edge. + * @summary A list of items placed starting from the leading edge. * - * @description Items are placed directly to the right of back button, if present. - * If there is not enough space to fit all leading items at once, they are all moved to overflow menu. - * This differs from trailing items, which are moved one by one. + * @description Items are placed next to the back button, if present. If there + * is not enough space to fit all leading items at once, they are all moved to + * overflow menu. This differs from trailing items, which are moved one by one. * - * Note: Custom items are not put into overflow menu, but are removed entirely. + * Note: Custom items are not put into the overflow menu, but are removed entirely. * * @platform iOS */ @@ -206,10 +208,10 @@ export interface StackHeaderConfigPropsIOS { */ titleItem?: StackHeaderTitleCustomItemIOS | undefined; /** - * @summary A list of items placed beginning from the trailing edge. + * @summary A list of items placed starting from the trailing edge. * If there is not enough space to fit some items, they are moved to the overflow menu, one by one. * - * Note: Custom items are not put into overflow menu, but are removed entirely. + * Note: Custom items are not put into the overflow menu, but are removed entirely. * * @platform iOS */ @@ -225,13 +227,13 @@ export interface StackHeaderConfigPropsIOS { * * @description When ScrollView is present on the screen, large header is displayed only when * fully scrolled to top, otherwise it collapses to regular header. If `largeTitle` is not defined, - * it fallbacks to regular title. + * it falls back to regular title. * * @platform iOS */ largeTitle?: string | undefined; /** - * @summary Tells the header to display large title. It collapses to regular header when scrolling. + * @summary Specifies if the header should display the large title. It collapses to a regular header when scrolling. * * @platform iOS */ @@ -241,7 +243,7 @@ export interface StackHeaderConfigPropsIOS { * * @description When ScrollView is present on the screen, large header is displayed only when * fully scrolled to top, otherwise it collapses to regular header. If `largeSubititle` is not defined, - * it fallbacks to regular subtitle. + * it falls back to regular subtitle. * * @platform iOS *