UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

271 lines • 9.38 kB
import React from 'react'; import type { ResponsiveValue } from '../hooks/useResponsiveValue'; import type { FCWithSlotMarker, WithSlotMarker } from '../utils/types'; import { type PaneWidthValue, type PaneWidth, type CustomWidthOptions } from './usePaneWidth'; declare const SPACING_MAP: { none: number; condensed: number; normal: (number | null)[]; }; export type PageLayoutProps = { /** The maximum width of the page container */ containerWidth?: 'full' | 'medium' | 'large' | 'xlarge'; /** The spacing between the outer edges of the page container and the viewport */ padding?: keyof typeof SPACING_MAP; rowGap?: keyof typeof SPACING_MAP; columnGap?: keyof typeof SPACING_MAP; /** Private prop to allow SplitPageLayout to customize slot components */ _slotsConfig?: Record<'header' | 'footer' | 'sidebar', React.ElementType>; className?: string; style?: React.CSSProperties; }; export type PageLayoutHeaderProps = { /** * A unique label for the rendered banner landmark */ 'aria-label'?: React.AriaAttributes['aria-label']; /** * An id to an element which uniquely labels the rendered banner landmark */ 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']; padding?: keyof typeof SPACING_MAP; divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'>; /** * @deprecated Use the `divider` prop with a responsive value instead. * * Before: * ``` * divider="line" * dividerWhenNarrow="filled" * ``` * * After: * ``` * divider={{regular: 'line', narrow: 'filled'}} * ``` */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled'; hidden?: boolean | ResponsiveValue<boolean>; className?: string; style?: React.CSSProperties; }; export type PageLayoutContentProps = { /** * Provide an optional element type for the outermost element rendered by the component. * @default 'main' */ as?: React.ElementType; /** * A unique label for the rendered main landmark */ 'aria-label'?: React.AriaAttributes['aria-label']; /** * An id to an element which uniquely labels the rendered main landmark */ 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']; width?: 'full' | 'medium' | 'large' | 'xlarge'; padding?: keyof typeof SPACING_MAP; hidden?: boolean | ResponsiveValue<boolean>; className?: string; style?: React.CSSProperties; }; export type PageLayoutPaneBaseProps = { position?: 'start' | 'end' | ResponsiveValue<'start' | 'end'>; /** * @deprecated Use the `position` prop with a responsive value instead. * * Before: * ``` * position="start" * positionWhenNarrow="end" * ``` * * After: * ``` * position={{regular: 'start', narrow: 'end'}} * ``` */ positionWhenNarrow?: 'inherit' | 'start' | 'end'; 'aria-labelledby'?: string; 'aria-label'?: string; /** * The width of the pane. * - Named sizes: `'small'` | `'medium'` | `'large'` * - Custom object: `{min: string, default: string, max: string}` * * When `resizable` is enabled, this defines the default width and constraints * (min/max bounds for dragging). Use `currentWidth` to control the displayed width. */ width?: PaneWidthValue; /** * Minimum width of the pane in pixels. Only used with named `width` sizes. * Ignored when `width` is a custom object (use `width.min` instead). */ minWidth?: number; /** * localStorage key used to persist the pane width across sessions. * Only applies when `resizable` is `true` and no `onResizeEnd` callback is provided. * @default 'paneWidth' */ widthStorageKey?: string; padding?: keyof typeof SPACING_MAP; divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'>; /** * @deprecated Use the `divider` prop with a responsive value instead. * * Before: * ``` * divider="line" * dividerWhenNarrow="filled" * ``` * * After: * ``` * divider={{regular: 'line', narrow: 'filled'}} * ``` */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled'; sticky?: boolean; offsetHeader?: string | number; hidden?: boolean | ResponsiveValue<boolean>; /** * Enable resizable pane behavior. * When `true`, the pane may be resized by the user via drag or keyboard. * Uses localStorage persistence by default unless `onResizeEnd` is provided. * * Note: With default localStorage persistence in SSR, the server-rendered * width may differ from the stored client width, causing a brief layout * shift on hydration. Use `onResizeEnd` with server-aware storage to avoid this. */ resizable?: boolean; id?: string; className?: string; style?: React.CSSProperties; }; export type PageLayoutPaneProps = PageLayoutPaneBaseProps & ({ /** * Callback fired when a resize operation ends (drag release or keyboard key up). * When provided, this callback is used instead of localStorage persistence. */ onResizeEnd: (width: number) => void; /** * Current/controlled width value in pixels. * When provided, this is used as the current pane width instead of internal state. * The `width` prop still defines the default used when resetting (e.g., double-click). * Pass `undefined` when the persisted value has not loaded yet (e.g., async fetch). */ currentWidth: number | undefined; } | { onResizeEnd?: never; currentWidth?: never; }); declare const Pane: React.ForwardRefExoticComponent<React.PropsWithChildren<PageLayoutPaneProps> & React.RefAttributes<HTMLDivElement>>; export type PageLayoutSidebarProps = { /** * A unique label for the sidebar region */ 'aria-label'?: React.AriaAttributes['aria-label']; /** * An id to an element which uniquely labels the sidebar region */ 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']; /** * Position of the sidebar relative to the page layout * @default 'start' */ position?: 'start' | 'end'; /** * Width configuration for the sidebar */ width?: PaneWidth | CustomWidthOptions; /** * Minimum width of the sidebar when resizable * @default 256 */ minWidth?: number; /** * Whether the sidebar can be resized * @default false */ resizable?: boolean; /** * localStorage key used to persist the sidebar width across sessions. * Only applies when `resizable` is `true`. * When omitted, localStorage is not used. */ widthStorageKey?: string; /** * Padding inside the sidebar */ padding?: keyof typeof SPACING_MAP; /** * Divider style between sidebar and content */ divider?: 'none' | 'line'; /** * Whether the sidebar sticks to the viewport when scrolling. * When enabled, the sidebar uses `position: sticky` with `top: 0` and `height: 100vh`. * @default false */ sticky?: boolean; /** * Controls sidebar behavior at narrow viewport widths (below 768px). * - `'default'`: the sidebar retains its normal inline layout. * - `'fullscreen'`: the sidebar expands to cover the full viewport like a dialog overlay. * @default 'default' */ responsiveVariant?: 'default' | 'fullscreen'; /** * Whether the sidebar is hidden */ hidden?: boolean | ResponsiveValue<boolean>; /** * Optional id for the sidebar element */ id?: string; className?: string; style?: React.CSSProperties; }; declare const Sidebar: React.ForwardRefExoticComponent<PageLayoutSidebarProps & { children?: React.ReactNode | undefined; } & React.RefAttributes<HTMLDivElement>>; export type PageLayoutFooterProps = { /** * A unique label for the rendered contentinfo landmark */ 'aria-label'?: React.AriaAttributes['aria-label']; /** * An id to an element which uniquely labels the rendered contentinfo landmark */ 'aria-labelledby'?: React.AriaAttributes['aria-labelledby']; padding?: keyof typeof SPACING_MAP; divider?: 'none' | 'line' | ResponsiveValue<'none' | 'line', 'none' | 'line' | 'filled'>; /** * @deprecated Use the `divider` prop with a responsive value instead. * * Before: * ``` * divider="line" * dividerWhenNarrow="filled" * ``` * * After: * ``` * divider={{regular: 'line', narrow: 'filled'}} * ``` */ dividerWhenNarrow?: 'inherit' | 'none' | 'line' | 'filled'; hidden?: boolean | ResponsiveValue<boolean>; className?: string; style?: React.CSSProperties; }; export declare const PageLayout: React.FC<React.PropsWithChildren<PageLayoutProps>> & { __SLOT__: symbol; Header: FCWithSlotMarker<React.PropsWithChildren<PageLayoutHeaderProps>>; Content: FCWithSlotMarker<React.PropsWithChildren<PageLayoutContentProps>>; Pane: WithSlotMarker<typeof Pane>; Sidebar: WithSlotMarker<typeof Sidebar>; Footer: FCWithSlotMarker<React.PropsWithChildren<PageLayoutFooterProps>>; }; export {}; //# sourceMappingURL=PageLayout.d.ts.map