@bitrise/bitkit-v2 0.3.513 → 0.3.514
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/BitkitPageSidebar/BitkitPageSidebar.d.ts +18 -0
- package/dist/components/BitkitPageSidebar/BitkitPageSidebar.js +50 -0
- package/dist/components/BitkitPageSidebar/BitkitPageSidebar.js.map +1 -1
- package/dist/components/BitkitPageSidebar/pageSidebarPart.d.ts +10 -0
- package/dist/components/BitkitPageSidebar/pageSidebarPart.js +14 -0
- package/dist/components/BitkitPageSidebar/pageSidebarPart.js.map +1 -0
- package/dist/components/index.d.ts +1 -1
- package/dist/theme/slot-recipes/PageSidebar.recipe.d.ts +12 -1
- package/dist/theme/slot-recipes/PageSidebar.recipe.js +46 -3
- package/dist/theme/slot-recipes/PageSidebar.recipe.js.map +1 -1
- package/dist/theme/slot-recipes/index.d.ts +12 -1
- package/dist/theme/tokens/keyframes.js +4 -0
- package/dist/theme/tokens/keyframes.js.map +1 -1
- package/package.json +1 -1
|
@@ -119,6 +119,23 @@ export type BitkitPageSidebarTitleProps = BitkitPageSidebarTitleButtonProps | Bi
|
|
|
119
119
|
export interface BitkitPageSidebarBodyProps extends BoxProps {
|
|
120
120
|
children: ReactNode;
|
|
121
121
|
}
|
|
122
|
+
export interface BitkitPageSidebarSectionProps extends Omit<BoxProps, 'title'> {
|
|
123
|
+
children: ReactNode;
|
|
124
|
+
/** Shown above the content and kept in view while the content scrolls. */
|
|
125
|
+
title?: string;
|
|
126
|
+
/**
|
|
127
|
+
* The title's heading level. The look stays `heading/h4` at every level: the level comes from
|
|
128
|
+
* where the section sits in the page's outline, so pick the one that follows the page's own
|
|
129
|
+
* headings.
|
|
130
|
+
*/
|
|
131
|
+
titleAs?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
132
|
+
/**
|
|
133
|
+
* The full-width rule along the top, which separates the section from the navigation above it.
|
|
134
|
+
* Turn it off when nothing is shown above the section, e.g. while the page hides its navigation.
|
|
135
|
+
* That also drops the title's top padding, since the sidebar's own top padding then makes the gap.
|
|
136
|
+
*/
|
|
137
|
+
withDivider?: boolean;
|
|
138
|
+
}
|
|
122
139
|
export interface BitkitPageSidebarFooterProps extends BoxProps {
|
|
123
140
|
children: ReactNode;
|
|
124
141
|
}
|
|
@@ -145,6 +162,7 @@ declare const _default: import('react').ForwardRefExoticComponent<BitkitPageSide
|
|
|
145
162
|
Item: import('react').ForwardRefExoticComponent<BitkitPageSidebarItemProps & import('react').RefAttributes<HTMLAnchorElement | HTMLButtonElement>>;
|
|
146
163
|
ProgressItem: import('react').ForwardRefExoticComponent<BitkitPageSidebarProgressItemProps & import('react').RefAttributes<HTMLButtonElement>>;
|
|
147
164
|
Project: import('react').ForwardRefExoticComponent<BitkitPageSidebarProjectProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
165
|
+
Section: import('react').ForwardRefExoticComponent<BitkitPageSidebarSectionProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
148
166
|
Title: import('react').ForwardRefExoticComponent<BitkitPageSidebarTitleProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
149
167
|
};
|
|
150
168
|
export default _default;
|
|
@@ -8,6 +8,7 @@ import BitkitGroupHeading from "../BitkitGroupHeading/BitkitGroupHeading.js";
|
|
|
8
8
|
import useResponsive from "../../hooks/useResponsive.js";
|
|
9
9
|
import BitkitOverflowTooltip from "../BitkitOverflowTooltip/BitkitOverflowTooltip.js";
|
|
10
10
|
import useIsTruncated from "../../utilities/useIsTruncated.js";
|
|
11
|
+
import pageSidebarPart from "./pageSidebarPart.js";
|
|
11
12
|
import { chakra, useChakraContext, useSlotRecipe } from "@chakra-ui/react/styled-system";
|
|
12
13
|
import { forwardRef } from "react";
|
|
13
14
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -42,6 +43,10 @@ var showAtMobile = { display: {
|
|
|
42
43
|
* taller than the viewport the whole thing — footer included — grows and scrolls with the page,
|
|
43
44
|
* which is why `Body` keeps a minimum gap above the footer so the two blocks never touch.
|
|
44
45
|
*
|
|
46
|
+
* A `Section` between `Body` and `Footer` changes that: the section takes the space left under the
|
|
47
|
+
* navigation and scrolls on its own, and `Body` scrolls too once the section is down to its
|
|
48
|
+
* `minHeight`. See `BitkitPageSidebar.Section`.
|
|
49
|
+
*
|
|
45
50
|
* The `<nav>` carries a default `aria-label` so it is not announced as an unnamed landmark. A page
|
|
46
51
|
* with more than one sidebar should name each one — pass your own `aria-label` (or
|
|
47
52
|
* `aria-labelledby`), which overrides the default.
|
|
@@ -310,18 +315,62 @@ BitkitPageSidebarTitle.displayName = "BitkitPageSidebarTitle";
|
|
|
310
315
|
* Holds the navigation items. It absorbs the space left between `Title` and `Footer`, so the footer
|
|
311
316
|
* sits at the bottom of the viewport on a short navigation, and keeps a minimum gap above the
|
|
312
317
|
* footer so the two blocks stay visually separate however long the list gets.
|
|
318
|
+
*
|
|
319
|
+
* Next to a `Section` it keeps its natural height instead and leaves the free space to the section.
|
|
320
|
+
* When the sidebar runs out of room, it scrolls on its own, with a fade at the bottom while there is
|
|
321
|
+
* more below. The rule reaches `Body` even when it is wrapped, e.g. in an element that animates it,
|
|
322
|
+
* but then the wrapper is what has to shrink: give it `flex="0 1 auto"` and `minHeight={0}`, and make
|
|
323
|
+
* it a flex column so `Body` can shrink inside it. Otherwise the wrapper keeps its content height,
|
|
324
|
+
* `Body` never scrolls, and the sidebar overflows.
|
|
313
325
|
*/
|
|
314
326
|
var BitkitPageSidebarBody = forwardRef((props, ref) => {
|
|
315
327
|
const { children, css, ...rest } = props;
|
|
316
328
|
const styles = useSlotRecipe({ key: "pageSidebar" })();
|
|
317
329
|
return /* @__PURE__ */ jsx(Box, {
|
|
318
330
|
ref,
|
|
331
|
+
...pageSidebarPart("body"),
|
|
319
332
|
css: [styles.body, css],
|
|
320
333
|
...rest,
|
|
321
334
|
children
|
|
322
335
|
});
|
|
323
336
|
});
|
|
324
337
|
BitkitPageSidebarBody.displayName = "BitkitPageSidebarBody";
|
|
338
|
+
/**
|
|
339
|
+
* A second area of the sidebar, between `Body` and `Footer`, for content that is not navigation: a
|
|
340
|
+
* file tree, a list, filters. It takes the space left under the navigation and scrolls inside
|
|
341
|
+
* itself on both axes, so wide content scrolls sideways instead of wrapping.
|
|
342
|
+
*
|
|
343
|
+
* ```tsx
|
|
344
|
+
* <BitkitPageSidebar>
|
|
345
|
+
* <BitkitPageSidebar.Body>…</BitkitPageSidebar.Body>
|
|
346
|
+
* <BitkitPageSidebar.Section minHeight="128" title="Configuration modules">…</BitkitPageSidebar.Section>
|
|
347
|
+
* <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>
|
|
348
|
+
* </BitkitPageSidebar>
|
|
349
|
+
* ```
|
|
350
|
+
*
|
|
351
|
+
* When space runs out, the section gives up its height first, down to its `minHeight`, and only then
|
|
352
|
+
* does `Body` start to scroll. How small it may get depends on the content, so `minHeight` is a
|
|
353
|
+
* plain style prop rather than a recipe value.
|
|
354
|
+
*/
|
|
355
|
+
var BitkitPageSidebarSection = forwardRef((props, ref) => {
|
|
356
|
+
const { children, css, title, titleAs = "h2", withDivider = true, ...rest } = props;
|
|
357
|
+
const styles = useSlotRecipe({ key: "pageSidebar" })({ withDivider });
|
|
358
|
+
return /* @__PURE__ */ jsxs(Box, {
|
|
359
|
+
ref,
|
|
360
|
+
...pageSidebarPart("section"),
|
|
361
|
+
css: [styles.section, css],
|
|
362
|
+
...rest,
|
|
363
|
+
children: [title && /* @__PURE__ */ jsx(Text, {
|
|
364
|
+
as: titleAs,
|
|
365
|
+
css: styles.sectionTitle,
|
|
366
|
+
children: title
|
|
367
|
+
}), /* @__PURE__ */ jsx(Box, {
|
|
368
|
+
css: styles.sectionContent,
|
|
369
|
+
children
|
|
370
|
+
})]
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
BitkitPageSidebarSection.displayName = "BitkitPageSidebarSection";
|
|
325
374
|
var BitkitPageSidebarFooter = forwardRef((props, ref) => {
|
|
326
375
|
const { children, css, ...rest } = props;
|
|
327
376
|
const styles = useSlotRecipe({ key: "pageSidebar" })();
|
|
@@ -417,6 +466,7 @@ var BitkitPageSidebar_default = withSubComponents(BitkitPageSidebar, {
|
|
|
417
466
|
Item: BitkitPageSidebarItem,
|
|
418
467
|
ProgressItem: BitkitPageSidebarProgressItem,
|
|
419
468
|
Project: BitkitPageSidebarProject,
|
|
469
|
+
Section: BitkitPageSidebarSection,
|
|
420
470
|
Title: BitkitPageSidebarTitle
|
|
421
471
|
});
|
|
422
472
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitPageSidebar.js","names":["_Fragment"],"sources":["../../../lib/components/BitkitPageSidebar/BitkitPageSidebar.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { Drawer } from '@chakra-ui/react/drawer';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator, type SeparatorProps } from '@chakra-ui/react/separator';\nimport { chakra, type HTMLChakraProps, useChakraContext, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';\n\nimport useResponsive from '../../hooks/useResponsive';\nimport { type BitkitIconComponent } from '../../icons';\nimport IconChevronLeft from '../../icons/IconChevronLeft';\nimport { type BitkitColorToken } from '../../theme/themeUtils';\nimport focusableDisabledProps from '../../utilities/focusableDisabledProps';\nimport useIsTruncated from '../../utilities/useIsTruncated';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitCloseButton from '../BitkitCloseButton/BitkitCloseButton';\nimport BitkitControlButton from '../BitkitControlButton/BitkitControlButton';\nimport BitkitGroupHeading, { type BitkitGroupHeadingProps } from '../BitkitGroupHeading/BitkitGroupHeading';\nimport BitkitOverflowTooltip from '../BitkitOverflowTooltip/BitkitOverflowTooltip';\nimport BitkitTooltip from '../BitkitTooltip/BitkitTooltip';\n\n// The 16 and 24 icons are separate drawings, not one scaled to two sizes, so the breakpoint swap\n// cannot live in the recipe — both are rendered and one is hidden. A `useBreakpointValue` would\n// render a single icon, but it only re-reads on mount: resize a live page across `tablet` and the\n// row resizes underneath an icon that keeps its old size.\nconst showAtDesktop = { display: { base: 'none', tablet: 'block' } };\nconst showAtMobile = { display: { base: 'block', tablet: 'none' } };\n\n// ----- BitkitPageSidebar (Root) -----\n\nexport interface BitkitPageSidebarProps extends BoxProps {\n children: ReactNode;\n /**\n * Header of the mobile drawer panel, naming what the navigation belongs to — pass a\n * `BitkitPageSidebar.DrawerHeader`. Only rendered in drawer mode.\n */\n drawerHeader?: ReactNode;\n /**\n * Mobile drawer visibility. Controlled, because the page header's menu button is what opens it.\n * Passing `onOpenChange` is what opts the sidebar into the drawer below `tablet`; without it the\n * sidebar stays in the flow at full width there. Both are ignored from `tablet` up.\n *\n * Style props and `css` apply to the sidebar beside the page only — the drawer panel sizes\n * itself, so a desktop `width` or padding never reaches the navigation inside it.\n */\n onOpenChange?: (open: boolean) => void;\n open?: boolean;\n}\n\n/**\n * Page-level navigation sidebar. It expects three children, in this order:\n *\n * ```tsx\n * <BitkitPageSidebar>\n * <BitkitPageSidebar.Title>Title</BitkitPageSidebar.Title>\n * <BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Item icon={IconWorkflow}>Workflows</BitkitPageSidebar.Item>\n * </BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>\n * </BitkitPageSidebar>\n * ```\n *\n * `Title` and `Footer` are optional. The sidebar scrolls as a single block: when the navigation is\n * taller than the viewport the whole thing — footer included — grows and scrolls with the page,\n * which is why `Body` keeps a minimum gap above the footer so the two blocks never touch.\n *\n * The `<nav>` carries a default `aria-label` so it is not announced as an unnamed landmark. A page\n * with more than one sidebar should name each one — pass your own `aria-label` (or\n * `aria-labelledby`), which overrides the default.\n *\n * It stands at least viewport-tall by default. An embedded panel that should size to its content\n * opts out with `minHeight=\"auto\"`.\n *\n * Below the `tablet` breakpoint it switches to the mobile design on its own — full width, 48px\n * rows, larger icons and labels, a squared-off selection edge. A sidebar that sits beside page\n * content has nowhere to go at that width, so it can become a drawer instead: pass `open` and\n * `onOpenChange` (opened by `BitkitPageHeader`'s menu button) and below `tablet` it slides in\n * from the trailing edge over a backdrop, with its close button on the backdrop beside the panel\n * and a `drawerHeader` naming the page. Both props are ignored from `tablet` up.\n */\nconst BitkitPageSidebar = forwardRef<HTMLElement, BitkitPageSidebarProps>((props, ref) => {\n const { children, css, drawerHeader, onOpenChange, open = false, ...rest } = props;\n\n const { isMobile } = useResponsive();\n const { splitCssProps } = useChakraContext();\n const hasDrawer = onOpenChange !== undefined;\n const isDrawer = isMobile && hasDrawer;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ layout: isDrawer ? 'drawer' : hasDrawer ? 'hidden' : 'static' });\n\n if (!isDrawer) {\n return (\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={[styles.root, css]} {...rest}>\n <nav>{children}</nav>\n </Box>\n );\n }\n\n // The consumer's sizing is for the sidebar beside the page; inside the panel only the recipe\n // lays the navigation out.\n const [, navProps] = splitCssProps(rest);\n\n return (\n <Drawer.Root onOpenChange={(details) => onOpenChange(details.open)} open={open}>\n <Portal>\n <Drawer.Backdrop css={styles.drawerBackdrop} />\n <Drawer.Positioner>\n <Drawer.Content aria-label=\"Navigation\" css={styles.drawerContent}>\n {drawerHeader}\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={styles.root} {...navProps}>\n <nav>{children}</nav>\n </Box>\n <Box css={styles.drawerCloseButton}>\n <BitkitCloseButton\n aria-label=\"Close navigation\"\n colorVariant=\"white\"\n onClick={() => onOpenChange(false)}\n size=\"md\"\n />\n </Box>\n </Drawer.Content>\n </Drawer.Positioner>\n </Portal>\n </Drawer.Root>\n );\n});\n\nBitkitPageSidebar.displayName = 'BitkitPageSidebar';\n\n// ----- BitkitPageSidebar.Item -----\n\ninterface BitkitPageSidebarItemCommonProps {\n badge?: ReactNode;\n /**\n * The item's label. Typed as a string rather than `ReactNode` because the row truncates it with\n * an ellipsis, and the overflow tooltip needs the full text to reveal.\n */\n children: string;\n /**\n * Why the item is unavailable, shown in a tooltip on it while `state` is `\"disabled\"`. The item\n * then stays focusable and is announced as disabled (`aria-disabled`), so the tooltip opens on\n * hover and focus. It still neither navigates nor activates. Use it instead of wrapping a disabled\n * item in `BitkitTooltip`.\n */\n disabledReason?: string;\n icon?: BitkitIconComponent;\n /**\n * Marks the item as the current page. Mutually exclusive with `state=\"disabled\"` — you cannot be\n * on a page whose nav item is unavailable — but the two are not type-checked against each other:\n * the combination only ever arrives from a computed `selected`, which no union can catch, and\n * checking it would break the ordinary `selected={item.id === currentId}` mapping. If both do\n * turn up, disabled wins, since that is the one of the two the design actually defines.\n */\n selected?: boolean;\n state?: 'disabled';\n suffixIcon?: BitkitIconComponent;\n}\n\ninterface BitkitPageSidebarItemLinkProps\n extends Omit<HTMLChakraProps<'a'>, 'children'>, BitkitPageSidebarItemCommonProps {\n href: string;\n}\n\ninterface BitkitPageSidebarItemButtonProps\n extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'>, BitkitPageSidebarItemCommonProps {\n href?: never;\n}\n\nexport type BitkitPageSidebarItemProps = BitkitPageSidebarItemButtonProps | BitkitPageSidebarItemLinkProps;\n\nconst BitkitPageSidebarItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, BitkitPageSidebarItemProps>(\n (props, ref) => {\n const { badge, children, disabledReason, icon: Icon, selected, state, suffixIcon: SuffixIcon, ...rest } = props;\n\n const isDisabled = state === 'disabled';\n const hasReason = isDisabled && !!disabledReason;\n // `selected` and `state=\"disabled\"` are not checked against each other in the types, so this is\n // the single place the overlap is resolved: disabled wins, and the two recipe variants can never\n // both claim the same slot.\n const isSelected = selected === true && !isDisabled;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, selected: isSelected });\n\n // The design gives neither a selected row nor a disabled one a trailing icon — the desktop\n // (`20014:6498`, `20014:6494`) and mobile (`9221:4417`) items drop it in those states.\n const VisibleSuffixIcon = isSelected || isDisabled ? undefined : SuffixIcon;\n\n const { isTruncated, ref: labelRef } = useIsTruncated<HTMLSpanElement>(children);\n\n const itemContent = (\n <>\n {/* `span`, not the default `div`: in button mode these sit inside a `<button>`, whose\n content model allows phrasing content only. */}\n <Box as=\"span\" css={styles.contentBlock}>\n {Icon && (\n <>\n <Icon css={[styles.itemIcon, showAtDesktop]} size=\"16\" />\n <Icon css={[styles.itemIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n <Text as=\"span\" css={styles.itemLabel} ref={labelRef}>\n {children}\n </Text>\n </Box>\n {badge}\n {VisibleSuffixIcon && (\n <>\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtDesktop]} size=\"16\" />\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </>\n );\n\n // The overflow tooltip anchors to the row itself, which is the focusable element: anchored to an\n // inner node it would only ever open on hover, leaving keyboard users unable to read a truncated\n // label. `Tooltip.Trigger` renders `asChild` and composes refs, so the consumer's forwarded ref\n // survives, and the ref measuring the truncation sits on the label further in.\n // The reason tooltip is always rendered so a state change can't remount the row and drop its focus.\n const withTooltip = (row: ReactNode) => (\n <BitkitTooltip disabled={!hasReason} placement=\"right\" text={disabledReason ?? ''}>\n <BitkitOverflowTooltip disabled={!isTruncated || hasReason} text={children}>\n {row}\n </BitkitOverflowTooltip>\n </BitkitTooltip>\n );\n\n // `chakra.a` / `chakra.button` rather than a named primitive: the item carries its own slot recipe,\n // and Chakra's `Button`/`Link` would layer their own recipe styles on top of it.\n if (rest.href !== undefined) {\n const { className, href, onClick, onKeyDown, ...linkRest } = rest;\n const handleClick = isDisabled\n ? (event: MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (event: KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n : onKeyDown;\n\n return withTooltip(\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...linkRest}\n aria-current={isSelected ? 'page' : undefined}\n aria-disabled={isDisabled || undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n // Dropping the attribute is what actually disables the link, the way `BitkitLink` and\n // `BitkitControlButton` do it. The handlers below only block `click` and `Enter`/`Space`;\n // a middle click fires `auxclick`, and \"Open link in new tab\" never reaches the page at\n // all, so both would still navigate while an `href` is there to follow.\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n // Without `href` the anchor is neither a link nor focusable, and the reason tooltip needs both.\n {...(hasReason && { role: 'link', tabIndex: 0 })}\n >\n {itemContent}\n </chakra.a>,\n );\n }\n\n const { className, href: _href, ...buttonRest } = rest;\n\n return withTooltip(\n <chakra.button\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n aria-current={isSelected ? 'page' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n disabled={isDisabled && !hasReason}\n type=\"button\"\n {...(hasReason && focusableDisabledProps)}\n >\n {itemContent}\n </chakra.button>,\n );\n },\n);\n\nBitkitPageSidebarItem.displayName = 'BitkitPageSidebarItem';\n\n// ----- BitkitPageSidebar.ProgressItem -----\n\nexport interface BitkitPageSidebarProgressItemProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {\n /**\n * Trailing content between the label and the connector — a `BitkitBadge` counting what the stage\n * is waiting on. Sized to itself; the connector takes the rest.\n *\n * The design draws it 20px tall, which is `size=\"xs\"`. The badge arrives as a node, so the\n * component cannot set that for you — a taller one grows the row past its 40px.\n */\n badge?: ReactNode;\n /** The row's label. */\n children: ReactNode;\n /**\n * The status icon. Unlike `Item`, whose icon colour the sidebar owns, this one carries the\n * stage's status, so `iconColor` is the consumer's to set — `selected`, `notRequired` and\n * `state=\"disabled\"` still win over it, since those describe the row rather than the status.\n */\n icon: BitkitIconComponent;\n /**\n * A semantic token for the status the icon is showing. Left out, the icon takes the sidebar's own\n * `icon/secondary` — which is what the design gives a stage whose icon carries no status, such as\n * an approvals step.\n *\n * Narrowed to the `icon/*` and `color/*` tokens, so a name that does not exist is a compile error\n * rather than a colour that silently does not apply. Both families are here because the statuses\n * need both: the design takes success and failure from `icon/*` but in-progress from\n * `color/orange/bold`, which the `icon/*` set has no equivalent of.\n */\n iconColor?: BitkitColorToken<'color' | 'icon'>;\n /**\n * A stage the release does not have to clear. Steps the icon and the label down one level, so the\n * row reads as present but not awaited.\n */\n notRequired?: boolean;\n /** Follows the label after a middle dot — `auto-upload`, `not required`. */\n secondaryText?: string;\n selected?: boolean;\n state?: 'disabled';\n /**\n * Draws the dashed rule that runs from the badge to the trailing edge, tying one stage to the\n * next. The last stage in a list has nothing to tie to, so it goes without.\n */\n withConnector?: boolean;\n}\n\n/**\n * A stage of something that progresses, as a row of the page sidebar — a release running through\n * its steps, and whatever comes to look like it.\n *\n * It is a sibling of `Item` rather than a variant of it: the row reports where a stage stands\n * rather than navigating, so its icon is status-coloured, its label does not grow, and a dashed\n * connector runs to the trailing edge between the stages.\n *\n * Always a `<button>`, and always interactive — it carries the shared row's pointer cursor and\n * hover background, so a row without an `onClick` looks actionable and is not. `Item`'s\n * button-or-anchor union is deliberately not here: a stage is selected within the page it is\n * already on rather than navigated to.\n */\nconst BitkitPageSidebarProgressItem = forwardRef<HTMLButtonElement, BitkitPageSidebarProgressItemProps>(\n (props, ref) => {\n const {\n badge,\n children,\n className,\n css,\n icon: Icon,\n iconColor,\n notRequired,\n secondaryText,\n selected,\n state,\n withConnector,\n ...rest\n } = props;\n\n const isDisabled = state === 'disabled';\n // Disabled is the whole state of the row, so the other two are dropped rather than merged: the\n // recipe resolves a combination in its own order, and a disabled row came out of it carrying\n // the selected icon colour. Nothing about a disabled stage is selected or not-required.\n const isSelected = selected && !isDisabled;\n // And `selected` wins over `notRequired`, which the design decides rather than declaration\n // order: its `selected=yes, notRequired=true` variant draws the selected row's icon and label\n // and keeps `not required` in the secondary text -- which is what dropping this produces.\n const isNotRequired = notRequired && !isDisabled && !isSelected;\n\n const statusColor = isDisabled || isNotRequired || isSelected ? undefined : iconColor;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, notRequired: isNotRequired, selected: isSelected });\n\n return (\n <chakra.button\n ref={ref}\n {...rest}\n // `step` rather than the `page` an `Item` carries: these are stages of one thing, not\n // separate pages.\n aria-current={isSelected ? 'step' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={[styles.item, styles.progressRow, css]}\n disabled={isDisabled}\n type=\"button\"\n >\n <Box as=\"span\" css={[styles.contentBlock, styles.progressContentBlock]}>\n {/* Two icons, one per size, for the reason `Item` has two -- see `showAtDesktop`.\n The status colour applies while the row is ordinary: `selected`, `notRequired` and\n disabled are states of the row rather than of the status, and the design recolours the\n icon in all three, so the recipe takes it back there. */}\n <Icon color={statusColor} css={[styles.progressIcon, showAtDesktop]} size=\"16\" />\n <Icon color={statusColor} css={[styles.progressIcon, showAtMobile]} size=\"24\" />\n <Box as=\"span\" css={styles.progressTextBlock}>\n <Text as=\"span\" css={styles.progressLabel}>\n {children}\n </Text>\n {secondaryText && (\n <Text as=\"span\" css={styles.progressSecondaryText}>\n {`\\u00b7 ${secondaryText}`}\n </Text>\n )}\n </Box>\n {(badge || withConnector) && (\n <Box as=\"span\" css={styles.progressBlocker}>\n {badge}\n {/* Decorative: it ties the stages together visually and has nothing to separate in\n the button's accessibility tree. */}\n {withConnector && <Separator aria-hidden css={styles.progressConnector} />}\n </Box>\n )}\n </Box>\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </chakra.button>\n );\n },\n);\n\nBitkitPageSidebarProgressItem.displayName = 'BitkitPageSidebarProgressItem';\n\n// ----- BitkitPageSidebar.Title -----\n\ninterface BitkitPageSidebarTitleCommonProps extends BoxProps {\n backLabel?: string;\n children: ReactNode;\n}\n\ninterface BitkitPageSidebarTitleLinkProps extends BitkitPageSidebarTitleCommonProps {\n backHref: string;\n onBackClick?: never;\n}\n\ninterface BitkitPageSidebarTitleButtonProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick: () => void;\n}\n\ninterface BitkitPageSidebarTitlePlainProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick?: never;\n}\n\nexport type BitkitPageSidebarTitleProps =\n BitkitPageSidebarTitleButtonProps | BitkitPageSidebarTitleLinkProps | BitkitPageSidebarTitlePlainProps;\n\nconst BitkitPageSidebarTitle = forwardRef<HTMLDivElement, BitkitPageSidebarTitleProps>((props, ref) => {\n const { backHref, backLabel = 'Back', children, css, onBackClick, ...rest } = props;\n\n const hasBack = backHref !== undefined || onBackClick !== undefined;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasBack });\n\n return (\n <Box ref={ref} css={[styles.title, css]} {...rest}>\n <Box css={styles.titleBlock}>\n {/* The label tooltip opens to the right. Its default `top` has nowhere to go here — the\n button sits at the very top of the sidebar, so the tooltip jams against the viewport\n edge and covers the header instead of flipping. */}\n {hasBack &&\n (backHref !== undefined ? (\n <BitkitControlButton\n href={backHref}\n icon={IconChevronLeft}\n label={backLabel}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ) : (\n <BitkitControlButton\n icon={IconChevronLeft}\n label={backLabel}\n onClick={onBackClick}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ))}\n <Text as=\"span\" css={styles.titleText}>\n {children}\n </Text>\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarTitle.displayName = 'BitkitPageSidebarTitle';\n\n// ----- BitkitPageSidebar.Body -----\n\nexport interface BitkitPageSidebarBodyProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Holds the navigation items. It absorbs the space left between `Title` and `Footer`, so the footer\n * sits at the bottom of the viewport on a short navigation, and keeps a minimum gap above the\n * footer so the two blocks stay visually separate however long the list gets.\n */\nconst BitkitPageSidebarBody = forwardRef<HTMLDivElement, BitkitPageSidebarBodyProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.body, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarBody.displayName = 'BitkitPageSidebarBody';\n\n// ----- BitkitPageSidebar.Footer -----\n\nexport interface BitkitPageSidebarFooterProps extends BoxProps {\n children: ReactNode;\n}\n\nconst BitkitPageSidebarFooter = forwardRef<HTMLDivElement, BitkitPageSidebarFooterProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.footer, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarFooter.displayName = 'BitkitPageSidebarFooter';\n\n// ----- BitkitPageSidebar.Project -----\n\nexport interface BitkitPageSidebarProjectProps extends BoxProps {\n label: string;\n value: string;\n}\n\nconst BitkitPageSidebarProject = forwardRef<HTMLDivElement, BitkitPageSidebarProjectProps>((props, ref) => {\n const { css, label, value, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n const { isTruncated, ref: valueRef } = useIsTruncated<HTMLSpanElement>(value);\n\n return (\n <Box ref={ref} css={[styles.project, css]} {...rest}>\n <Text as=\"span\" css={styles.projectLabel}>\n {label}\n </Text>\n {/* Wrapper for the same reason as in Item: the trigger cannot be the element being measured. */}\n <BitkitOverflowTooltip disabled={!isTruncated} text={value}>\n <Box css={styles.projectValueWrapper}>\n <Text as=\"span\" css={styles.projectValue} ref={valueRef}>\n {value}\n </Text>\n </Box>\n </BitkitOverflowTooltip>\n </Box>\n );\n});\n\nBitkitPageSidebarProject.displayName = 'BitkitPageSidebarProject';\n\n// ----- BitkitPageSidebar.GroupHeading -----\n\nexport type BitkitPageSidebarGroupHeadingProps = BitkitGroupHeadingProps;\n\nconst BitkitPageSidebarGroupHeading = forwardRef<HTMLDivElement, BitkitPageSidebarGroupHeadingProps>((props, ref) => {\n return <BitkitGroupHeading ref={ref} paddingBlockEnd=\"8\" paddingBlockStart=\"16\" paddingInline=\"24\" {...props} />;\n});\n\nBitkitPageSidebarGroupHeading.displayName = 'BitkitPageSidebarGroupHeading';\n\n// ----- BitkitPageSidebar.DrawerHeader -----\n\nexport interface BitkitPageSidebarDrawerHeaderProps extends Omit<BoxProps, 'title'> {\n /** App icon or user avatar before the title — a 32px `BitkitAvatar`. */\n avatar?: ReactNode;\n /** The entity's secondary line, an app's bundle id or a user's email. Its presence selects the entity layout. */\n secondaryText?: string;\n /** What the navigation belongs to: the page, app or user. */\n title: string;\n}\n\n/**\n * Header of the sidebar's mobile drawer (Figma `mobilePageSidebarHeader`). Pass it as the\n * sidebar's `drawerHeader`; it is what the panel opens with, above the navigation.\n */\nconst BitkitPageSidebarDrawerHeader = forwardRef<HTMLDivElement, BitkitPageSidebarDrawerHeaderProps>((props, ref) => {\n const { avatar, css, secondaryText, title, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasSecondaryText: secondaryText !== undefined });\n\n return (\n <Box ref={ref} css={[styles.drawerHeader, css]} {...rest}>\n {avatar !== undefined && <Box css={styles.drawerHeaderAvatar}>{avatar}</Box>}\n <Box css={styles.drawerHeaderTextBlock}>\n <Text css={styles.drawerHeaderTitle}>{title}</Text>\n {secondaryText !== undefined && <Text css={styles.drawerHeaderSecondaryText}>{secondaryText}</Text>}\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarDrawerHeader.displayName = 'BitkitPageSidebarDrawerHeader';\n\n// ----- BitkitPageSidebar.Divider -----\n\nexport type BitkitPageSidebarDividerProps = SeparatorProps;\n\nconst BitkitPageSidebarDivider = forwardRef<HTMLDivElement, BitkitPageSidebarDividerProps>((props, ref) => {\n const { css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return <Separator ref={ref} css={[styles.divider, css]} {...rest} />;\n});\n\nBitkitPageSidebarDivider.displayName = 'BitkitPageSidebarDivider';\n\nexport default withSubComponents(BitkitPageSidebar, {\n Body: BitkitPageSidebarBody,\n Divider: BitkitPageSidebarDivider,\n DrawerHeader: BitkitPageSidebarDrawerHeader,\n Footer: BitkitPageSidebarFooter,\n GroupHeading: BitkitPageSidebarGroupHeading,\n Item: BitkitPageSidebarItem,\n ProgressItem: BitkitPageSidebarProgressItem,\n Project: BitkitPageSidebarProject,\n Title: BitkitPageSidebarTitle,\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BitkitPageSidebar.js","names":["_Fragment"],"sources":["../../../lib/components/BitkitPageSidebar/BitkitPageSidebar.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { Drawer } from '@chakra-ui/react/drawer';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator, type SeparatorProps } from '@chakra-ui/react/separator';\nimport { chakra, type HTMLChakraProps, useChakraContext, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';\n\nimport useResponsive from '../../hooks/useResponsive';\nimport { type BitkitIconComponent } from '../../icons';\nimport IconChevronLeft from '../../icons/IconChevronLeft';\nimport { type BitkitColorToken } from '../../theme/themeUtils';\nimport focusableDisabledProps from '../../utilities/focusableDisabledProps';\nimport useIsTruncated from '../../utilities/useIsTruncated';\nimport { withSubComponents } from '../../utilities/withSubComponents';\nimport BitkitCloseButton from '../BitkitCloseButton/BitkitCloseButton';\nimport BitkitControlButton from '../BitkitControlButton/BitkitControlButton';\nimport BitkitGroupHeading, { type BitkitGroupHeadingProps } from '../BitkitGroupHeading/BitkitGroupHeading';\nimport BitkitOverflowTooltip from '../BitkitOverflowTooltip/BitkitOverflowTooltip';\nimport BitkitTooltip from '../BitkitTooltip/BitkitTooltip';\nimport pageSidebarPart from './pageSidebarPart';\n\n// The 16 and 24 icons are separate drawings, not one scaled to two sizes, so the breakpoint swap\n// cannot live in the recipe — both are rendered and one is hidden. A `useBreakpointValue` would\n// render a single icon, but it only re-reads on mount: resize a live page across `tablet` and the\n// row resizes underneath an icon that keeps its old size.\nconst showAtDesktop = { display: { base: 'none', tablet: 'block' } };\nconst showAtMobile = { display: { base: 'block', tablet: 'none' } };\n\n// ----- BitkitPageSidebar (Root) -----\n\nexport interface BitkitPageSidebarProps extends BoxProps {\n children: ReactNode;\n /**\n * Header of the mobile drawer panel, naming what the navigation belongs to — pass a\n * `BitkitPageSidebar.DrawerHeader`. Only rendered in drawer mode.\n */\n drawerHeader?: ReactNode;\n /**\n * Mobile drawer visibility. Controlled, because the page header's menu button is what opens it.\n * Passing `onOpenChange` is what opts the sidebar into the drawer below `tablet`; without it the\n * sidebar stays in the flow at full width there. Both are ignored from `tablet` up.\n *\n * Style props and `css` apply to the sidebar beside the page only — the drawer panel sizes\n * itself, so a desktop `width` or padding never reaches the navigation inside it.\n */\n onOpenChange?: (open: boolean) => void;\n open?: boolean;\n}\n\n/**\n * Page-level navigation sidebar. It expects three children, in this order:\n *\n * ```tsx\n * <BitkitPageSidebar>\n * <BitkitPageSidebar.Title>Title</BitkitPageSidebar.Title>\n * <BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Item icon={IconWorkflow}>Workflows</BitkitPageSidebar.Item>\n * </BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>\n * </BitkitPageSidebar>\n * ```\n *\n * `Title` and `Footer` are optional. The sidebar scrolls as a single block: when the navigation is\n * taller than the viewport the whole thing — footer included — grows and scrolls with the page,\n * which is why `Body` keeps a minimum gap above the footer so the two blocks never touch.\n *\n * A `Section` between `Body` and `Footer` changes that: the section takes the space left under the\n * navigation and scrolls on its own, and `Body` scrolls too once the section is down to its\n * `minHeight`. See `BitkitPageSidebar.Section`.\n *\n * The `<nav>` carries a default `aria-label` so it is not announced as an unnamed landmark. A page\n * with more than one sidebar should name each one — pass your own `aria-label` (or\n * `aria-labelledby`), which overrides the default.\n *\n * It stands at least viewport-tall by default. An embedded panel that should size to its content\n * opts out with `minHeight=\"auto\"`.\n *\n * Below the `tablet` breakpoint it switches to the mobile design on its own — full width, 48px\n * rows, larger icons and labels, a squared-off selection edge. A sidebar that sits beside page\n * content has nowhere to go at that width, so it can become a drawer instead: pass `open` and\n * `onOpenChange` (opened by `BitkitPageHeader`'s menu button) and below `tablet` it slides in\n * from the trailing edge over a backdrop, with its close button on the backdrop beside the panel\n * and a `drawerHeader` naming the page. Both props are ignored from `tablet` up.\n */\nconst BitkitPageSidebar = forwardRef<HTMLElement, BitkitPageSidebarProps>((props, ref) => {\n const { children, css, drawerHeader, onOpenChange, open = false, ...rest } = props;\n\n const { isMobile } = useResponsive();\n const { splitCssProps } = useChakraContext();\n const hasDrawer = onOpenChange !== undefined;\n const isDrawer = isMobile && hasDrawer;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ layout: isDrawer ? 'drawer' : hasDrawer ? 'hidden' : 'static' });\n\n if (!isDrawer) {\n return (\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={[styles.root, css]} {...rest}>\n <nav>{children}</nav>\n </Box>\n );\n }\n\n // The consumer's sizing is for the sidebar beside the page; inside the panel only the recipe\n // lays the navigation out.\n const [, navProps] = splitCssProps(rest);\n\n return (\n <Drawer.Root onOpenChange={(details) => onOpenChange(details.open)} open={open}>\n <Portal>\n <Drawer.Backdrop css={styles.drawerBackdrop} />\n <Drawer.Positioner>\n <Drawer.Content aria-label=\"Navigation\" css={styles.drawerContent}>\n {drawerHeader}\n <Box ref={ref} aria-label=\"Page navigation\" asChild css={styles.root} {...navProps}>\n <nav>{children}</nav>\n </Box>\n <Box css={styles.drawerCloseButton}>\n <BitkitCloseButton\n aria-label=\"Close navigation\"\n colorVariant=\"white\"\n onClick={() => onOpenChange(false)}\n size=\"md\"\n />\n </Box>\n </Drawer.Content>\n </Drawer.Positioner>\n </Portal>\n </Drawer.Root>\n );\n});\n\nBitkitPageSidebar.displayName = 'BitkitPageSidebar';\n\n// ----- BitkitPageSidebar.Item -----\n\ninterface BitkitPageSidebarItemCommonProps {\n badge?: ReactNode;\n /**\n * The item's label. Typed as a string rather than `ReactNode` because the row truncates it with\n * an ellipsis, and the overflow tooltip needs the full text to reveal.\n */\n children: string;\n /**\n * Why the item is unavailable, shown in a tooltip on it while `state` is `\"disabled\"`. The item\n * then stays focusable and is announced as disabled (`aria-disabled`), so the tooltip opens on\n * hover and focus. It still neither navigates nor activates. Use it instead of wrapping a disabled\n * item in `BitkitTooltip`.\n */\n disabledReason?: string;\n icon?: BitkitIconComponent;\n /**\n * Marks the item as the current page. Mutually exclusive with `state=\"disabled\"` — you cannot be\n * on a page whose nav item is unavailable — but the two are not type-checked against each other:\n * the combination only ever arrives from a computed `selected`, which no union can catch, and\n * checking it would break the ordinary `selected={item.id === currentId}` mapping. If both do\n * turn up, disabled wins, since that is the one of the two the design actually defines.\n */\n selected?: boolean;\n state?: 'disabled';\n suffixIcon?: BitkitIconComponent;\n}\n\ninterface BitkitPageSidebarItemLinkProps\n extends Omit<HTMLChakraProps<'a'>, 'children'>, BitkitPageSidebarItemCommonProps {\n href: string;\n}\n\ninterface BitkitPageSidebarItemButtonProps\n extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'>, BitkitPageSidebarItemCommonProps {\n href?: never;\n}\n\nexport type BitkitPageSidebarItemProps = BitkitPageSidebarItemButtonProps | BitkitPageSidebarItemLinkProps;\n\nconst BitkitPageSidebarItem = forwardRef<HTMLButtonElement | HTMLAnchorElement, BitkitPageSidebarItemProps>(\n (props, ref) => {\n const { badge, children, disabledReason, icon: Icon, selected, state, suffixIcon: SuffixIcon, ...rest } = props;\n\n const isDisabled = state === 'disabled';\n const hasReason = isDisabled && !!disabledReason;\n // `selected` and `state=\"disabled\"` are not checked against each other in the types, so this is\n // the single place the overlap is resolved: disabled wins, and the two recipe variants can never\n // both claim the same slot.\n const isSelected = selected === true && !isDisabled;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, selected: isSelected });\n\n // The design gives neither a selected row nor a disabled one a trailing icon — the desktop\n // (`20014:6498`, `20014:6494`) and mobile (`9221:4417`) items drop it in those states.\n const VisibleSuffixIcon = isSelected || isDisabled ? undefined : SuffixIcon;\n\n const { isTruncated, ref: labelRef } = useIsTruncated<HTMLSpanElement>(children);\n\n const itemContent = (\n <>\n {/* `span`, not the default `div`: in button mode these sit inside a `<button>`, whose\n content model allows phrasing content only. */}\n <Box as=\"span\" css={styles.contentBlock}>\n {Icon && (\n <>\n <Icon css={[styles.itemIcon, showAtDesktop]} size=\"16\" />\n <Icon css={[styles.itemIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n <Text as=\"span\" css={styles.itemLabel} ref={labelRef}>\n {children}\n </Text>\n </Box>\n {badge}\n {VisibleSuffixIcon && (\n <>\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtDesktop]} size=\"16\" />\n <VisibleSuffixIcon css={[styles.suffixIcon, showAtMobile]} size=\"24\" />\n </>\n )}\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </>\n );\n\n // The overflow tooltip anchors to the row itself, which is the focusable element: anchored to an\n // inner node it would only ever open on hover, leaving keyboard users unable to read a truncated\n // label. `Tooltip.Trigger` renders `asChild` and composes refs, so the consumer's forwarded ref\n // survives, and the ref measuring the truncation sits on the label further in.\n // The reason tooltip is always rendered so a state change can't remount the row and drop its focus.\n const withTooltip = (row: ReactNode) => (\n <BitkitTooltip disabled={!hasReason} placement=\"right\" text={disabledReason ?? ''}>\n <BitkitOverflowTooltip disabled={!isTruncated || hasReason} text={children}>\n {row}\n </BitkitOverflowTooltip>\n </BitkitTooltip>\n );\n\n // `chakra.a` / `chakra.button` rather than a named primitive: the item carries its own slot recipe,\n // and Chakra's `Button`/`Link` would layer their own recipe styles on top of it.\n if (rest.href !== undefined) {\n const { className, href, onClick, onKeyDown, ...linkRest } = rest;\n const handleClick = isDisabled\n ? (event: MouseEvent<HTMLAnchorElement>) => {\n event.preventDefault();\n event.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (event: KeyboardEvent<HTMLAnchorElement>) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n event.stopPropagation();\n }\n }\n : onKeyDown;\n\n return withTooltip(\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...linkRest}\n aria-current={isSelected ? 'page' : undefined}\n aria-disabled={isDisabled || undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n // Dropping the attribute is what actually disables the link, the way `BitkitLink` and\n // `BitkitControlButton` do it. The handlers below only block `click` and `Enter`/`Space`;\n // a middle click fires `auxclick`, and \"Open link in new tab\" never reaches the page at\n // all, so both would still navigate while an `href` is there to follow.\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n // Without `href` the anchor is neither a link nor focusable, and the reason tooltip needs both.\n {...(hasReason && { role: 'link', tabIndex: 0 })}\n >\n {itemContent}\n </chakra.a>,\n );\n }\n\n const { className, href: _href, ...buttonRest } = rest;\n\n return withTooltip(\n <chakra.button\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n aria-current={isSelected ? 'page' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={styles.item}\n disabled={isDisabled && !hasReason}\n type=\"button\"\n {...(hasReason && focusableDisabledProps)}\n >\n {itemContent}\n </chakra.button>,\n );\n },\n);\n\nBitkitPageSidebarItem.displayName = 'BitkitPageSidebarItem';\n\n// ----- BitkitPageSidebar.ProgressItem -----\n\nexport interface BitkitPageSidebarProgressItemProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {\n /**\n * Trailing content between the label and the connector — a `BitkitBadge` counting what the stage\n * is waiting on. Sized to itself; the connector takes the rest.\n *\n * The design draws it 20px tall, which is `size=\"xs\"`. The badge arrives as a node, so the\n * component cannot set that for you — a taller one grows the row past its 40px.\n */\n badge?: ReactNode;\n /** The row's label. */\n children: ReactNode;\n /**\n * The status icon. Unlike `Item`, whose icon colour the sidebar owns, this one carries the\n * stage's status, so `iconColor` is the consumer's to set — `selected`, `notRequired` and\n * `state=\"disabled\"` still win over it, since those describe the row rather than the status.\n */\n icon: BitkitIconComponent;\n /**\n * A semantic token for the status the icon is showing. Left out, the icon takes the sidebar's own\n * `icon/secondary` — which is what the design gives a stage whose icon carries no status, such as\n * an approvals step.\n *\n * Narrowed to the `icon/*` and `color/*` tokens, so a name that does not exist is a compile error\n * rather than a colour that silently does not apply. Both families are here because the statuses\n * need both: the design takes success and failure from `icon/*` but in-progress from\n * `color/orange/bold`, which the `icon/*` set has no equivalent of.\n */\n iconColor?: BitkitColorToken<'color' | 'icon'>;\n /**\n * A stage the release does not have to clear. Steps the icon and the label down one level, so the\n * row reads as present but not awaited.\n */\n notRequired?: boolean;\n /** Follows the label after a middle dot — `auto-upload`, `not required`. */\n secondaryText?: string;\n selected?: boolean;\n state?: 'disabled';\n /**\n * Draws the dashed rule that runs from the badge to the trailing edge, tying one stage to the\n * next. The last stage in a list has nothing to tie to, so it goes without.\n */\n withConnector?: boolean;\n}\n\n/**\n * A stage of something that progresses, as a row of the page sidebar — a release running through\n * its steps, and whatever comes to look like it.\n *\n * It is a sibling of `Item` rather than a variant of it: the row reports where a stage stands\n * rather than navigating, so its icon is status-coloured, its label does not grow, and a dashed\n * connector runs to the trailing edge between the stages.\n *\n * Always a `<button>`, and always interactive — it carries the shared row's pointer cursor and\n * hover background, so a row without an `onClick` looks actionable and is not. `Item`'s\n * button-or-anchor union is deliberately not here: a stage is selected within the page it is\n * already on rather than navigated to.\n */\nconst BitkitPageSidebarProgressItem = forwardRef<HTMLButtonElement, BitkitPageSidebarProgressItemProps>(\n (props, ref) => {\n const {\n badge,\n children,\n className,\n css,\n icon: Icon,\n iconColor,\n notRequired,\n secondaryText,\n selected,\n state,\n withConnector,\n ...rest\n } = props;\n\n const isDisabled = state === 'disabled';\n // Disabled is the whole state of the row, so the other two are dropped rather than merged: the\n // recipe resolves a combination in its own order, and a disabled row came out of it carrying\n // the selected icon colour. Nothing about a disabled stage is selected or not-required.\n const isSelected = selected && !isDisabled;\n // And `selected` wins over `notRequired`, which the design decides rather than declaration\n // order: its `selected=yes, notRequired=true` variant draws the selected row's icon and label\n // and keeps `not required` in the secondary text -- which is what dropping this produces.\n const isNotRequired = notRequired && !isDisabled && !isSelected;\n\n const statusColor = isDisabled || isNotRequired || isSelected ? undefined : iconColor;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ isDisabled, notRequired: isNotRequired, selected: isSelected });\n\n return (\n <chakra.button\n ref={ref}\n {...rest}\n // `step` rather than the `page` an `Item` carries: these are stages of one thing, not\n // separate pages.\n aria-current={isSelected ? 'step' : undefined}\n className={className ? `group ${className}` : 'group'}\n css={[styles.item, styles.progressRow, css]}\n disabled={isDisabled}\n type=\"button\"\n >\n <Box as=\"span\" css={[styles.contentBlock, styles.progressContentBlock]}>\n {/* Two icons, one per size, for the reason `Item` has two -- see `showAtDesktop`.\n The status colour applies while the row is ordinary: `selected`, `notRequired` and\n disabled are states of the row rather than of the status, and the design recolours the\n icon in all three, so the recipe takes it back there. */}\n <Icon color={statusColor} css={[styles.progressIcon, showAtDesktop]} size=\"16\" />\n <Icon color={statusColor} css={[styles.progressIcon, showAtMobile]} size=\"24\" />\n <Box as=\"span\" css={styles.progressTextBlock}>\n <Text as=\"span\" css={styles.progressLabel}>\n {children}\n </Text>\n {secondaryText && (\n <Text as=\"span\" css={styles.progressSecondaryText}>\n {`\\u00b7 ${secondaryText}`}\n </Text>\n )}\n </Box>\n {(badge || withConnector) && (\n <Box as=\"span\" css={styles.progressBlocker}>\n {badge}\n {/* Decorative: it ties the stages together visually and has nothing to separate in\n the button's accessibility tree. */}\n {withConnector && <Separator aria-hidden css={styles.progressConnector} />}\n </Box>\n )}\n </Box>\n {isSelected && <Box as=\"span\" css={styles.selectionMarker} />}\n </chakra.button>\n );\n },\n);\n\nBitkitPageSidebarProgressItem.displayName = 'BitkitPageSidebarProgressItem';\n\n// ----- BitkitPageSidebar.Title -----\n\ninterface BitkitPageSidebarTitleCommonProps extends BoxProps {\n backLabel?: string;\n children: ReactNode;\n}\n\ninterface BitkitPageSidebarTitleLinkProps extends BitkitPageSidebarTitleCommonProps {\n backHref: string;\n onBackClick?: never;\n}\n\ninterface BitkitPageSidebarTitleButtonProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick: () => void;\n}\n\ninterface BitkitPageSidebarTitlePlainProps extends BitkitPageSidebarTitleCommonProps {\n backHref?: never;\n onBackClick?: never;\n}\n\nexport type BitkitPageSidebarTitleProps =\n BitkitPageSidebarTitleButtonProps | BitkitPageSidebarTitleLinkProps | BitkitPageSidebarTitlePlainProps;\n\nconst BitkitPageSidebarTitle = forwardRef<HTMLDivElement, BitkitPageSidebarTitleProps>((props, ref) => {\n const { backHref, backLabel = 'Back', children, css, onBackClick, ...rest } = props;\n\n const hasBack = backHref !== undefined || onBackClick !== undefined;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasBack });\n\n return (\n <Box ref={ref} css={[styles.title, css]} {...rest}>\n <Box css={styles.titleBlock}>\n {/* The label tooltip opens to the right. Its default `top` has nowhere to go here — the\n button sits at the very top of the sidebar, so the tooltip jams against the viewport\n edge and covers the header instead of flipping. */}\n {hasBack &&\n (backHref !== undefined ? (\n <BitkitControlButton\n href={backHref}\n icon={IconChevronLeft}\n label={backLabel}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ) : (\n <BitkitControlButton\n icon={IconChevronLeft}\n label={backLabel}\n onClick={onBackClick}\n size=\"xs\"\n tooltipProps={{ placement: 'right' }}\n />\n ))}\n <Text as=\"span\" css={styles.titleText}>\n {children}\n </Text>\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarTitle.displayName = 'BitkitPageSidebarTitle';\n\n// ----- BitkitPageSidebar.Body -----\n\nexport interface BitkitPageSidebarBodyProps extends BoxProps {\n children: ReactNode;\n}\n\n/**\n * Holds the navigation items. It absorbs the space left between `Title` and `Footer`, so the footer\n * sits at the bottom of the viewport on a short navigation, and keeps a minimum gap above the\n * footer so the two blocks stay visually separate however long the list gets.\n *\n * Next to a `Section` it keeps its natural height instead and leaves the free space to the section.\n * When the sidebar runs out of room, it scrolls on its own, with a fade at the bottom while there is\n * more below. The rule reaches `Body` even when it is wrapped, e.g. in an element that animates it,\n * but then the wrapper is what has to shrink: give it `flex=\"0 1 auto\"` and `minHeight={0}`, and make\n * it a flex column so `Body` can shrink inside it. Otherwise the wrapper keeps its content height,\n * `Body` never scrolls, and the sidebar overflows.\n */\nconst BitkitPageSidebarBody = forwardRef<HTMLDivElement, BitkitPageSidebarBodyProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} {...pageSidebarPart('body')} css={[styles.body, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarBody.displayName = 'BitkitPageSidebarBody';\n\n// ----- BitkitPageSidebar.Section -----\n\nexport interface BitkitPageSidebarSectionProps extends Omit<BoxProps, 'title'> {\n children: ReactNode;\n /** Shown above the content and kept in view while the content scrolls. */\n title?: string;\n /**\n * The title's heading level. The look stays `heading/h4` at every level: the level comes from\n * where the section sits in the page's outline, so pick the one that follows the page's own\n * headings.\n */\n titleAs?: 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n /**\n * The full-width rule along the top, which separates the section from the navigation above it.\n * Turn it off when nothing is shown above the section, e.g. while the page hides its navigation.\n * That also drops the title's top padding, since the sidebar's own top padding then makes the gap.\n */\n withDivider?: boolean;\n}\n\n/**\n * A second area of the sidebar, between `Body` and `Footer`, for content that is not navigation: a\n * file tree, a list, filters. It takes the space left under the navigation and scrolls inside\n * itself on both axes, so wide content scrolls sideways instead of wrapping.\n *\n * ```tsx\n * <BitkitPageSidebar>\n * <BitkitPageSidebar.Body>…</BitkitPageSidebar.Body>\n * <BitkitPageSidebar.Section minHeight=\"128\" title=\"Configuration modules\">…</BitkitPageSidebar.Section>\n * <BitkitPageSidebar.Footer>…</BitkitPageSidebar.Footer>\n * </BitkitPageSidebar>\n * ```\n *\n * When space runs out, the section gives up its height first, down to its `minHeight`, and only then\n * does `Body` start to scroll. How small it may get depends on the content, so `minHeight` is a\n * plain style prop rather than a recipe value.\n */\nconst BitkitPageSidebarSection = forwardRef<HTMLDivElement, BitkitPageSidebarSectionProps>((props, ref) => {\n const { children, css, title, titleAs = 'h2', withDivider = true, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ withDivider });\n\n return (\n <Box ref={ref} {...pageSidebarPart('section')} css={[styles.section, css]} {...rest}>\n {title && (\n <Text as={titleAs} css={styles.sectionTitle}>\n {title}\n </Text>\n )}\n <Box css={styles.sectionContent}>{children}</Box>\n </Box>\n );\n});\n\nBitkitPageSidebarSection.displayName = 'BitkitPageSidebarSection';\n\n// ----- BitkitPageSidebar.Footer -----\n\nexport interface BitkitPageSidebarFooterProps extends BoxProps {\n children: ReactNode;\n}\n\nconst BitkitPageSidebarFooter = forwardRef<HTMLDivElement, BitkitPageSidebarFooterProps>((props, ref) => {\n const { children, css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return (\n <Box ref={ref} css={[styles.footer, css]} {...rest}>\n {children}\n </Box>\n );\n});\n\nBitkitPageSidebarFooter.displayName = 'BitkitPageSidebarFooter';\n\n// ----- BitkitPageSidebar.Project -----\n\nexport interface BitkitPageSidebarProjectProps extends BoxProps {\n label: string;\n value: string;\n}\n\nconst BitkitPageSidebarProject = forwardRef<HTMLDivElement, BitkitPageSidebarProjectProps>((props, ref) => {\n const { css, label, value, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n const { isTruncated, ref: valueRef } = useIsTruncated<HTMLSpanElement>(value);\n\n return (\n <Box ref={ref} css={[styles.project, css]} {...rest}>\n <Text as=\"span\" css={styles.projectLabel}>\n {label}\n </Text>\n {/* Wrapper for the same reason as in Item: the trigger cannot be the element being measured. */}\n <BitkitOverflowTooltip disabled={!isTruncated} text={value}>\n <Box css={styles.projectValueWrapper}>\n <Text as=\"span\" css={styles.projectValue} ref={valueRef}>\n {value}\n </Text>\n </Box>\n </BitkitOverflowTooltip>\n </Box>\n );\n});\n\nBitkitPageSidebarProject.displayName = 'BitkitPageSidebarProject';\n\n// ----- BitkitPageSidebar.GroupHeading -----\n\nexport type BitkitPageSidebarGroupHeadingProps = BitkitGroupHeadingProps;\n\nconst BitkitPageSidebarGroupHeading = forwardRef<HTMLDivElement, BitkitPageSidebarGroupHeadingProps>((props, ref) => {\n return <BitkitGroupHeading ref={ref} paddingBlockEnd=\"8\" paddingBlockStart=\"16\" paddingInline=\"24\" {...props} />;\n});\n\nBitkitPageSidebarGroupHeading.displayName = 'BitkitPageSidebarGroupHeading';\n\n// ----- BitkitPageSidebar.DrawerHeader -----\n\nexport interface BitkitPageSidebarDrawerHeaderProps extends Omit<BoxProps, 'title'> {\n /** App icon or user avatar before the title — a 32px `BitkitAvatar`. */\n avatar?: ReactNode;\n /** The entity's secondary line, an app's bundle id or a user's email. Its presence selects the entity layout. */\n secondaryText?: string;\n /** What the navigation belongs to: the page, app or user. */\n title: string;\n}\n\n/**\n * Header of the sidebar's mobile drawer (Figma `mobilePageSidebarHeader`). Pass it as the\n * sidebar's `drawerHeader`; it is what the panel opens with, above the navigation.\n */\nconst BitkitPageSidebarDrawerHeader = forwardRef<HTMLDivElement, BitkitPageSidebarDrawerHeaderProps>((props, ref) => {\n const { avatar, css, secondaryText, title, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe({ hasSecondaryText: secondaryText !== undefined });\n\n return (\n <Box ref={ref} css={[styles.drawerHeader, css]} {...rest}>\n {avatar !== undefined && <Box css={styles.drawerHeaderAvatar}>{avatar}</Box>}\n <Box css={styles.drawerHeaderTextBlock}>\n <Text css={styles.drawerHeaderTitle}>{title}</Text>\n {secondaryText !== undefined && <Text css={styles.drawerHeaderSecondaryText}>{secondaryText}</Text>}\n </Box>\n </Box>\n );\n});\n\nBitkitPageSidebarDrawerHeader.displayName = 'BitkitPageSidebarDrawerHeader';\n\n// ----- BitkitPageSidebar.Divider -----\n\nexport type BitkitPageSidebarDividerProps = SeparatorProps;\n\nconst BitkitPageSidebarDivider = forwardRef<HTMLDivElement, BitkitPageSidebarDividerProps>((props, ref) => {\n const { css, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'pageSidebar' });\n const styles = recipe();\n\n return <Separator ref={ref} css={[styles.divider, css]} {...rest} />;\n});\n\nBitkitPageSidebarDivider.displayName = 'BitkitPageSidebarDivider';\n\nexport default withSubComponents(BitkitPageSidebar, {\n Body: BitkitPageSidebarBody,\n Divider: BitkitPageSidebarDivider,\n DrawerHeader: BitkitPageSidebarDrawerHeader,\n Footer: BitkitPageSidebarFooter,\n GroupHeading: BitkitPageSidebarGroupHeading,\n Item: BitkitPageSidebarItem,\n ProgressItem: BitkitPageSidebarProgressItem,\n Project: BitkitPageSidebarProject,\n Section: BitkitPageSidebarSection,\n Title: BitkitPageSidebarTitle,\n});\n"],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `data-scope` / `data-part` pair on the sidebar parts the root's recipe has to find, so the
|
|
3
|
+
* "is there a `Section`?" rule can address them without a generated class name. The same marker
|
|
4
|
+
* Chakra and Ark put on their own parts, and the one `BitkitUIHeader` uses. Spread it before `...rest`.
|
|
5
|
+
*/
|
|
6
|
+
declare const pageSidebarPart: (name: string) => {
|
|
7
|
+
'data-part': string;
|
|
8
|
+
'data-scope': string;
|
|
9
|
+
};
|
|
10
|
+
export default pageSidebarPart;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
//#region lib/components/BitkitPageSidebar/pageSidebarPart.ts
|
|
2
|
+
/**
|
|
3
|
+
* The `data-scope` / `data-part` pair on the sidebar parts the root's recipe has to find, so the
|
|
4
|
+
* "is there a `Section`?" rule can address them without a generated class name. The same marker
|
|
5
|
+
* Chakra and Ark put on their own parts, and the one `BitkitUIHeader` uses. Spread it before `...rest`.
|
|
6
|
+
*/
|
|
7
|
+
var pageSidebarPart = (name) => ({
|
|
8
|
+
"data-part": name,
|
|
9
|
+
"data-scope": "page-sidebar"
|
|
10
|
+
});
|
|
11
|
+
//#endregion
|
|
12
|
+
export { pageSidebarPart as default };
|
|
13
|
+
|
|
14
|
+
//# sourceMappingURL=pageSidebarPart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pageSidebarPart.js","names":[],"sources":["../../../lib/components/BitkitPageSidebar/pageSidebarPart.ts"],"sourcesContent":["/**\n * The `data-scope` / `data-part` pair on the sidebar parts the root's recipe has to find, so the\n * \"is there a `Section`?\" rule can address them without a generated class name. The same marker\n * Chakra and Ark put on their own parts, and the one `BitkitUIHeader` uses. Spread it before `...rest`.\n */\nconst pageSidebarPart = (name: string) => ({ 'data-part': name, 'data-scope': 'page-sidebar' });\n\nexport default pageSidebarPart;\n"],"mappings":";;;;;;AAKA,IAAM,mBAAmB,UAAkB;CAAE,aAAa;CAAM,cAAc;AAAe"}
|
|
@@ -59,7 +59,7 @@ export { default as BitkitOverflowContent, type BitkitOverflowContentProps, } fr
|
|
|
59
59
|
export { default as BitkitOverflowTooltip, type BitkitOverflowTooltipProps, } from './BitkitOverflowTooltip/BitkitOverflowTooltip';
|
|
60
60
|
export { default as BitkitPageFooter, type BitkitPageFooterItemProps, type BitkitPageFooterProps, } from './BitkitPageFooter/BitkitPageFooter';
|
|
61
61
|
export { default as BitkitPageHeader, type BitkitPageHeaderProps } from './BitkitPageHeader/BitkitPageHeader';
|
|
62
|
-
export { default as BitkitPageSidebar, type BitkitPageSidebarBodyProps, type BitkitPageSidebarDividerProps, type BitkitPageSidebarDrawerHeaderProps, type BitkitPageSidebarFooterProps, type BitkitPageSidebarGroupHeadingProps, type BitkitPageSidebarItemProps, type BitkitPageSidebarProgressItemProps, type BitkitPageSidebarProjectProps, type BitkitPageSidebarProps, type BitkitPageSidebarTitleProps, } from './BitkitPageSidebar/BitkitPageSidebar';
|
|
62
|
+
export { default as BitkitPageSidebar, type BitkitPageSidebarBodyProps, type BitkitPageSidebarDividerProps, type BitkitPageSidebarDrawerHeaderProps, type BitkitPageSidebarFooterProps, type BitkitPageSidebarGroupHeadingProps, type BitkitPageSidebarItemProps, type BitkitPageSidebarProgressItemProps, type BitkitPageSidebarProjectProps, type BitkitPageSidebarProps, type BitkitPageSidebarSectionProps, type BitkitPageSidebarTitleProps, } from './BitkitPageSidebar/BitkitPageSidebar';
|
|
63
63
|
export { default as BitkitPageSubheader, type BitkitPageSubheaderProps, } from './BitkitPageSubheader/BitkitPageSubheader';
|
|
64
64
|
export { default as BitkitPagination, type BitkitPaginationLabels, type BitkitPaginationProps, } from './BitkitPagination/BitkitPagination';
|
|
65
65
|
export { default as BitkitPaginationLoadMore, type BitkitPaginationLoadMoreProps, } from './BitkitPaginationLoadMore/BitkitPaginationLoadMore';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "suffixIcon" | "titleText" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "drawerHeader" | "divider" | "drawerBackdrop" | "drawerCloseButton" | "drawerContent" | "drawerHeaderAvatar" | "drawerHeaderSecondaryText" | "drawerHeaderTextBlock" | "drawerHeaderTitle" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
|
|
1
|
+
declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "section" | "title" | "root" | "item" | "suffixIcon" | "titleText" | "titleBlock" | "itemLabel" | "itemIcon" | "sectionTitle" | "contentBlock" | "drawerHeader" | "divider" | "drawerBackdrop" | "drawerCloseButton" | "drawerContent" | "drawerHeaderAvatar" | "drawerHeaderSecondaryText" | "drawerHeaderTextBlock" | "drawerHeaderTitle" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "sectionContent" | "selectionMarker", {
|
|
2
2
|
/**
|
|
3
3
|
* `drawer` is the sidebar inside its mobile drawer panel: the panel carries the edge and the
|
|
4
4
|
* width, so the navigation itself gives up its own and scrolls within the panel.
|
|
@@ -179,5 +179,16 @@ declare const pageSidebarSlotRecipe: import('@chakra-ui/react').SlotRecipeDefini
|
|
|
179
179
|
};
|
|
180
180
|
false: {};
|
|
181
181
|
};
|
|
182
|
+
withDivider: {
|
|
183
|
+
true: {};
|
|
184
|
+
false: {
|
|
185
|
+
section: {
|
|
186
|
+
borderBlockStartWidth: number;
|
|
187
|
+
};
|
|
188
|
+
sectionTitle: {
|
|
189
|
+
paddingBlockStart: number;
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
};
|
|
182
193
|
}>;
|
|
183
194
|
export default pageSidebarSlotRecipe;
|
|
@@ -32,6 +32,9 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
32
32
|
"projectValue",
|
|
33
33
|
"projectValueWrapper",
|
|
34
34
|
"root",
|
|
35
|
+
"section",
|
|
36
|
+
"sectionContent",
|
|
37
|
+
"sectionTitle",
|
|
35
38
|
"selectionMarker",
|
|
36
39
|
"suffixIcon",
|
|
37
40
|
"title",
|
|
@@ -56,7 +59,12 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
56
59
|
width: {
|
|
57
60
|
base: "full",
|
|
58
61
|
tablet: rem(240)
|
|
59
|
-
}
|
|
62
|
+
},
|
|
63
|
+
"&:has(> [data-scope=page-sidebar][data-part=section])": { "& [data-scope=page-sidebar][data-part=body]": {
|
|
64
|
+
flex: "0 1 auto",
|
|
65
|
+
minHeight: 0,
|
|
66
|
+
overflowY: "auto"
|
|
67
|
+
} }
|
|
60
68
|
},
|
|
61
69
|
drawerBackdrop: { background: "utilities/overlay-dark" },
|
|
62
70
|
drawerContent: {
|
|
@@ -112,7 +120,13 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
112
120
|
flex: 1,
|
|
113
121
|
flexDirection: "column",
|
|
114
122
|
marginBlockEnd: "8",
|
|
115
|
-
width: "full"
|
|
123
|
+
width: "full",
|
|
124
|
+
"@supports (animation-timeline: scroll())": {
|
|
125
|
+
animationFillMode: "both",
|
|
126
|
+
animationName: "page-sidebar-more-below",
|
|
127
|
+
animationTimeline: "scroll(self)",
|
|
128
|
+
animationTimingFunction: "linear"
|
|
129
|
+
}
|
|
116
130
|
},
|
|
117
131
|
title: {
|
|
118
132
|
alignItems: "center",
|
|
@@ -222,6 +236,27 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
222
236
|
marginBlockStart: "8",
|
|
223
237
|
paddingBlock: "8"
|
|
224
238
|
},
|
|
239
|
+
section: {
|
|
240
|
+
borderBlockStart: "1px solid",
|
|
241
|
+
borderColor: "border/minimal",
|
|
242
|
+
display: "flex",
|
|
243
|
+
flex: "1 1 0",
|
|
244
|
+
flexDirection: "column",
|
|
245
|
+
minHeight: 0
|
|
246
|
+
},
|
|
247
|
+
sectionContent: {
|
|
248
|
+
flex: 1,
|
|
249
|
+
minHeight: 0,
|
|
250
|
+
overflow: "auto"
|
|
251
|
+
},
|
|
252
|
+
sectionTitle: {
|
|
253
|
+
color: "text/primary",
|
|
254
|
+
flexShrink: 0,
|
|
255
|
+
paddingBlockEnd: "8",
|
|
256
|
+
paddingBlockStart: "16",
|
|
257
|
+
paddingInline: "24",
|
|
258
|
+
textStyle: "heading/h4"
|
|
259
|
+
},
|
|
225
260
|
/**
|
|
226
261
|
* The progress item's own text, rather than `itemLabel`: that slot grows to fill the row, which
|
|
227
262
|
* here belongs to the blocker so the connector can run to the trailing edge.
|
|
@@ -475,6 +510,13 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
475
510
|
}
|
|
476
511
|
},
|
|
477
512
|
false: {}
|
|
513
|
+
},
|
|
514
|
+
withDivider: {
|
|
515
|
+
true: {},
|
|
516
|
+
false: {
|
|
517
|
+
section: { borderBlockStartWidth: 0 },
|
|
518
|
+
sectionTitle: { paddingBlockStart: 0 }
|
|
519
|
+
}
|
|
478
520
|
}
|
|
479
521
|
},
|
|
480
522
|
defaultVariants: {
|
|
@@ -483,7 +525,8 @@ var pageSidebarSlotRecipe = defineSlotRecipe({
|
|
|
483
525
|
isDisabled: false,
|
|
484
526
|
layout: "static",
|
|
485
527
|
notRequired: false,
|
|
486
|
-
selected: false
|
|
528
|
+
selected: false,
|
|
529
|
+
withDivider: true
|
|
487
530
|
}
|
|
488
531
|
});
|
|
489
532
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageSidebar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/PageSidebar.recipe.ts"],"sourcesContent":["import { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nconst pageSidebarSlotRecipe = defineSlotRecipe({\n className: 'page-sidebar',\n slots: [\n 'body',\n 'contentBlock',\n 'divider',\n 'drawerBackdrop',\n 'drawerCloseButton',\n 'drawerContent',\n 'drawerHeader',\n 'drawerHeaderAvatar',\n 'drawerHeaderSecondaryText',\n 'drawerHeaderTextBlock',\n 'drawerHeaderTitle',\n 'footer',\n 'item',\n 'itemIcon',\n 'itemLabel',\n 'progressBlocker',\n 'progressConnector',\n 'progressContentBlock',\n 'progressIcon',\n 'progressLabel',\n 'progressRow',\n 'progressSecondaryText',\n 'progressTextBlock',\n 'project',\n 'projectLabel',\n 'projectValue',\n 'projectValueWrapper',\n 'root',\n 'selectionMarker',\n 'suffixIcon',\n 'title',\n 'titleBlock',\n 'titleText',\n ],\n base: {\n root: {\n background: 'background/primary',\n // Longhands, not the `borderInlineEnd: '1px solid'` shorthand: that shorthand carries no\n // colour, so it resets it to `currentColor` if it lands after `borderColor` — which is what\n // sorting these keys alphabetically did, turning the rule dark.\n borderInlineEndColor: 'border/regular',\n borderInlineEndStyle: 'solid',\n borderInlineEndWidth: '1',\n display: 'flex',\n flexDirection: 'column',\n // `minHeight` rather than `height`: on a short navigation the sidebar still reaches the\n // bottom of the viewport, but a long one grows past it and scrolls with the page as one\n // block — the footer is part of that scroll, not pinned to the bottom.\n minHeight: '100dvh',\n // Below `tablet` the sidebar is the whole view — Figma's mobile frame (`23056:50745`) is the\n // full 375 of the phone, not a 240 column beside a page.\n maxWidth: { base: 'none', tablet: rem(320) },\n minWidth: rem(240),\n paddingBlockStart: '16',\n width: { base: 'full', tablet: rem(240) },\n },\n // The mobile drawer (Figma `PageSidebar - mobile`, `23512:27095`). The `Drawer.*` parts carry\n // the registered `drawer` recipe — motion, layering, the trailing-edge positioner — so only\n // what differs from it lives here.\n drawerBackdrop: {\n background: 'utilities/overlay-dark',\n },\n drawerContent: {\n boxShadow: 'elevation/lg',\n // The close button hangs off the leading edge, so the panel must not clip it.\n overflow: 'visible',\n width: rem(320),\n // 320 for the panel plus the 56 the close button column takes. Narrower phones give the panel\n // up, not the button — at a hard 320 the button would be the part pushed off-screen.\n maxWidth: 'calc(100vw - 56px)',\n },\n drawerCloseButton: {\n alignItems: 'center',\n display: 'flex',\n // As tall as the header row, so the button centres on it.\n height: rem(56),\n insetBlockStart: 0,\n insetInlineEnd: '100%',\n paddingInlineEnd: '8',\n position: 'absolute',\n },\n drawerHeader: {\n alignItems: 'center',\n borderBlockEndColor: 'border/regular',\n borderBlockEndStyle: 'solid',\n borderBlockEndWidth: '1',\n display: 'flex',\n flexShrink: 0,\n minHeight: rem(56),\n paddingBlockEnd: '12',\n paddingBlockStart: '12',\n paddingInlineEnd: '24',\n paddingInlineStart: '16',\n },\n drawerHeaderAvatar: {\n display: 'flex',\n flexShrink: 0,\n },\n drawerHeaderTextBlock: {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n minWidth: 0,\n },\n drawerHeaderTitle: {\n color: 'text/primary',\n textStyle: 'heading/mobile/h2',\n truncate: true,\n },\n drawerHeaderSecondaryText: {\n color: 'text/secondary',\n textStyle: 'body/md/regular',\n truncate: true,\n },\n body: {\n display: 'flex',\n // Absorbs the slack so the footer sits at the bottom when the navigation is short, and\n // simply grows when it is long.\n flex: 1,\n flexDirection: 'column',\n // Half of the gap to the footer block; the footer carries the other half. Split that way so\n // this one is also the sidebar's bottom padding when there is no footer -- 8 either way,\n // rather than the body's whole 16 becoming the bottom edge. It is a margin so it stays\n // outside the items' own box, and `flex: 1` above means any extra space lands in the body\n // rather than widening the gap. Margins do not collapse in a flex column, so the two add up.\n marginBlockEnd: '8',\n width: 'full',\n },\n title: {\n alignItems: 'center',\n color: 'text/primary',\n display: 'flex',\n flexShrink: 0,\n overflow: 'clip',\n paddingInlineEnd: '32',\n },\n titleBlock: {\n alignItems: 'center',\n display: 'flex',\n minWidth: 0,\n },\n titleText: {\n textStyle: 'heading/h3',\n whiteSpace: 'nowrap',\n },\n item: {\n alignItems: 'center',\n cursor: 'pointer',\n display: 'flex',\n focusVisibleRing: 'inside',\n gap: '12',\n overflow: 'clip',\n // 48 tall on mobile against 40 on desktop — the row is a touch target there.\n paddingBlock: { base: '12', tablet: '8' },\n paddingInline: '24',\n position: 'relative',\n width: 'full',\n // Mobile reaches for `background/hover` / `background/active` where desktop uses the\n // `secondary` / `tertiary` surfaces. The two happen to resolve close, but they are separate\n // tokens in the design and the mobile item (`9221:4406`) binds these.\n _hover: {\n background: { base: 'background/hover', tablet: 'background/secondary' },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n // `focusVisibleRing: 'inside'` still resolves to `outline-offset: 0`, which draws the ring\n // just outside the border box. The item spans the sidebar's full width, so that would bleed\n // past the sidebar's edges — pull the whole ring inside the item instead.\n _focusVisible: {\n outlineOffset: 'calc(var(--focus-ring-width) * -1)',\n },\n },\n contentBlock: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 0,\n // Pads the 16px icon out to the 24px line box on desktop. The mobile icon is already 24, so\n // there is nothing to make up — the row would just grow past 48.\n paddingBlock: { base: '0', tablet: '2' },\n },\n itemIcon: {\n color: 'icon/secondary',\n flexShrink: 0,\n _groupHover: {\n color: 'icon/primary',\n },\n },\n itemLabel: {\n color: 'text/primary',\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textAlign: 'start',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n suffixIcon: {\n color: 'icon/tertiary',\n flexShrink: 0,\n },\n selectionMarker: {\n background: 'border/selected',\n // Mobile draws the marker as a plain 4px edge (`9221:4417`); desktop as a 2px rounded rule.\n borderEndStartRadius: { base: '0', tablet: '2' },\n borderStartStartRadius: { base: '0', tablet: '2' },\n height: 'full',\n insetBlockStart: 0,\n insetInlineEnd: 0,\n position: 'absolute',\n width: { base: '4', tablet: '2' },\n },\n footer: {\n borderBlockStart: '1px solid',\n borderColor: 'border/minimal',\n display: 'flex',\n flexDirection: 'column',\n // The body above absorbs the free space, so the footer needs no positioning of its own —\n // it just must not be squashed by a long list.\n flexShrink: 0,\n // The other half of the gap to the body — see its `marginBlockEnd`.\n marginBlockStart: '8',\n paddingBlock: '8',\n },\n /**\n * The progress item's own text, rather than `itemLabel`: that slot grows to fill the row, which\n * here belongs to the blocker so the connector can run to the trailing edge.\n */\n progressLabel: {\n color: 'text/primary',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /** Follows the label after a middle dot, which the component renders. */\n progressSecondaryText: {\n color: 'text/tertiary',\n flexShrink: 0,\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /**\n * Badge and connector as one unit, taking the width the text leaves.\n *\n * `fit-content` rather than 0: the flex basis is 0, so with a shrinking text block beside it\n * there is no free space to grow into and the block would be handed the whole row -- leaving\n * the badge, which does not shrink, hanging off the trailing edge. The floor is the badge; the\n * connector inside is basis 0 and contributes nothing to it.\n */\n progressBlocker: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 'fit-content',\n },\n /**\n * The status icon's own slot rather than `itemIcon`: that one brightens to `icon/primary` with\n * the row, which is right for navigation and wrong here -- hovering a stage would drop the\n * colour that says where it stands.\n */\n progressIcon: {\n // The colour a status-less icon takes -- the approvals step's, which the design draws in the\n // same `icon/secondary` as the navigation icons. `iconColor` overrides it per stage.\n color: 'icon/secondary',\n flexShrink: 0,\n // Its own slot rather than `itemIcon`, but it does brighten with the row: the design moves the\n // icon to `icon/primary` on hover and active. That only ever reaches a colour this recipe\n // supplied -- a consumer's `iconColor` is an inline, unlayered `color` and beats it -- so a\n // stage's status survives the hover while a status-less icon follows the row.\n _groupHover: {\n color: 'icon/primary',\n },\n },\n /**\n * Label and secondary text read as one line, so they sit closer than the row's own 12 gap.\n *\n * It shrinks before the blocker does: `item` clips its overflow, so without this a long stage\n * name is cut mid-word and pushes the secondary text and the connector off the row. The\n * blocker keeps `flex: 1`, so it still takes the slack whenever the text is short enough.\n */\n progressTextBlock: {\n alignItems: 'center',\n display: 'flex',\n flexShrink: 1,\n gap: '4',\n minWidth: 0,\n },\n /**\n * The progress row's block padding, which does not follow the navigation row's to 12 on mobile:\n * the design keeps this row on 8 at both widths, so it is 44 tall on mobile against a nav row's\n * 48. Layered over `item` rather than replacing it -- everything else about the row is shared.\n */\n progressRow: {\n paddingBlock: '8',\n },\n /** With the row above: 2 either side of the line box at both widths, so the block is 28. */\n progressContentBlock: {\n paddingBlock: '2',\n },\n progressConnector: {\n borderColor: 'border/minimal',\n borderStyle: 'dashed',\n flex: 1,\n },\n project: {\n display: 'flex',\n flexDirection: 'column',\n gap: '4',\n justifyContent: 'center',\n overflow: 'clip',\n paddingBlockEnd: { base: '12', tablet: '8' },\n paddingBlockStart: '8',\n paddingInlineEnd: { base: '24', tablet: '32' },\n paddingInlineStart: '24',\n whiteSpace: 'nowrap',\n },\n projectLabel: {\n color: 'text/tertiary',\n textStyle: 'heading/h6',\n },\n projectValue: {\n color: 'text/body',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: 'body/lg/semibold',\n },\n projectValueWrapper: {\n display: 'flex',\n minWidth: 0,\n },\n divider: {\n // Both of the sidebar's separator roles are `border/minimal` — the group header\n // (`20014:6508`) and this plain rule (`20014:6511`) — against `border/regular` for the general\n // Separator component. The override is per-slot for that reason, not to limit blast radius.\n borderColor: 'border/minimal',\n // Mobile's separator row is 40 tall, which centres the rule at 19.5 a side; 20 is the token\n // next to it and the resulting 1px lands nowhere the eye can find it.\n marginBlock: { base: '20', tablet: '16' },\n marginInline: '24',\n width: 'auto',\n },\n },\n variants: {\n /**\n * `drawer` is the sidebar inside its mobile drawer panel: the panel carries the edge and the\n * width, so the navigation itself gives up its own and scrolls within the panel.\n */\n layout: {\n // `useResponsive` reports desktop until it has measured, so an opted-in sidebar would paint\n // in the flow on a phone and then jump into the drawer. Hidden below `tablet` instead: the\n // drawer branch takes over as soon as the measurement lands, with nothing to remove.\n hidden: {\n root: {\n display: { base: 'none', tablet: 'flex' },\n },\n },\n drawer: {\n root: {\n borderInlineEndWidth: 0,\n flex: 1,\n maxWidth: 'none',\n minHeight: 'auto',\n minWidth: 0,\n overflowY: 'auto',\n width: 'full',\n },\n },\n static: {},\n },\n /**\n * The drawer header's two shapes (Figma `mobilePageSidebarHeader`): a page title on its own, or\n * an entity — app or user — whose name steps down a size to make room for its secondary text.\n */\n hasSecondaryText: {\n true: {\n drawerHeader: { gap: '12' },\n drawerHeaderTitle: { textStyle: 'heading/mobile/h3' },\n },\n false: {\n drawerHeader: { gap: '8' },\n drawerHeaderTextBlock: { paddingInlineStart: '4' },\n },\n },\n hasBack: {\n // Redlines on the sub view (Figma `- page sidebar - interactions`): the title block sits at\n // x/y 16, is 40 tall, and the 32px back button sits at y 20 — i.e. the 4px padding belongs to\n // the block wrapping button + text, not to the text. Header totals 16 + 40 + 8 = 64.\n true: {\n title: {\n paddingBlockEnd: '8',\n paddingInlineStart: '16',\n },\n titleBlock: {\n gap: '4',\n paddingBlock: '4',\n },\n },\n // Main view: no button, so the text alone is the block — 6 + 28 + 6 = 40, header 16+40+16 = 72.\n false: {\n title: {\n paddingBlockEnd: '16',\n paddingInlineStart: '24',\n },\n titleBlock: {\n paddingBlock: '6',\n },\n },\n },\n isDisabled: {\n true: {\n item: {\n cursor: 'not-allowed',\n _hover: {\n background: 'transparent',\n _active: {\n background: 'transparent',\n },\n },\n _active: {\n background: 'transparent',\n },\n },\n itemIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n itemLabel: {\n color: 'text/disabled',\n },\n progressIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n progressLabel: {\n color: 'text/disabled',\n },\n progressSecondaryText: {\n color: 'text/disabled',\n },\n },\n false: {},\n },\n selected: {\n true: {\n item: {\n background: 'background/selected',\n _hover: {\n background: 'background/selected-hover',\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n itemIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n itemLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n progressIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n progressLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n },\n false: {},\n },\n /**\n * A stage the release does not have to clear. Everything steps down one level -- the icon to\n * tertiary, the label to secondary -- so the row reads as present but not awaited. Hover and\n * active take both back to the row's ordinary colours, as they do for a required stage.\n *\n * `selected` wins over it, resolved in the component rather than here. The design draws the\n * pair (`selected=yes, notRequired=true`) and gives it the selected row's icon and label with\n * the `not required` secondary text kept, which is what dropping this variant produces.\n */\n notRequired: {\n true: {\n progressIcon: {\n color: 'icon/tertiary',\n _groupHover: { color: 'icon/primary' },\n },\n progressLabel: {\n color: 'text/secondary',\n _groupHover: { color: 'text/primary' },\n },\n },\n false: {},\n },\n },\n defaultVariants: {\n hasBack: false,\n hasSecondaryText: false,\n isDisabled: false,\n layout: 'static',\n notRequired: false,\n selected: false,\n },\n});\n\nexport default pageSidebarSlotRecipe;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PageSidebar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/PageSidebar.recipe.ts"],"sourcesContent":["import { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nconst pageSidebarSlotRecipe = defineSlotRecipe({\n className: 'page-sidebar',\n slots: [\n 'body',\n 'contentBlock',\n 'divider',\n 'drawerBackdrop',\n 'drawerCloseButton',\n 'drawerContent',\n 'drawerHeader',\n 'drawerHeaderAvatar',\n 'drawerHeaderSecondaryText',\n 'drawerHeaderTextBlock',\n 'drawerHeaderTitle',\n 'footer',\n 'item',\n 'itemIcon',\n 'itemLabel',\n 'progressBlocker',\n 'progressConnector',\n 'progressContentBlock',\n 'progressIcon',\n 'progressLabel',\n 'progressRow',\n 'progressSecondaryText',\n 'progressTextBlock',\n 'project',\n 'projectLabel',\n 'projectValue',\n 'projectValueWrapper',\n 'root',\n 'section',\n 'sectionContent',\n 'sectionTitle',\n 'selectionMarker',\n 'suffixIcon',\n 'title',\n 'titleBlock',\n 'titleText',\n ],\n base: {\n root: {\n background: 'background/primary',\n // Longhands, not the `borderInlineEnd: '1px solid'` shorthand: that shorthand carries no\n // colour, so it resets it to `currentColor` if it lands after `borderColor` — which is what\n // sorting these keys alphabetically did, turning the rule dark.\n borderInlineEndColor: 'border/regular',\n borderInlineEndStyle: 'solid',\n borderInlineEndWidth: '1',\n display: 'flex',\n flexDirection: 'column',\n // `minHeight` rather than `height`: on a short navigation the sidebar still reaches the\n // bottom of the viewport, but a long one grows past it and scrolls with the page as one\n // block — the footer is part of that scroll, not pinned to the bottom.\n minHeight: '100dvh',\n // Below `tablet` the sidebar is the whole view — Figma's mobile frame (`23056:50745`) is the\n // full 375 of the phone, not a 240 column beside a page.\n maxWidth: { base: 'none', tablet: rem(320) },\n minWidth: rem(240),\n paddingBlockStart: '16',\n width: { base: 'full', tablet: rem(240) },\n // With a `Section`, `Body` stops absorbing the free space and scrolls once the section is down\n // to its `minHeight`. Without one, nothing changes. A descendant selector for `Body`, so the\n // rule still reaches it when the consumer wraps it, e.g. to animate it. The wrapper is the\n // flex item then, so it needs `flex: 0 1 auto; min-height: 0` and a flex column inside, or\n // it keeps its content height and `Body` never scrolls.\n '&:has(> [data-scope=page-sidebar][data-part=section])': {\n '& [data-scope=page-sidebar][data-part=body]': {\n flex: '0 1 auto',\n minHeight: 0,\n overflowY: 'auto',\n },\n },\n },\n // The mobile drawer (Figma `PageSidebar - mobile`, `23512:27095`). The `Drawer.*` parts carry\n // the registered `drawer` recipe — motion, layering, the trailing-edge positioner — so only\n // what differs from it lives here.\n drawerBackdrop: {\n background: 'utilities/overlay-dark',\n },\n drawerContent: {\n boxShadow: 'elevation/lg',\n // The close button hangs off the leading edge, so the panel must not clip it.\n overflow: 'visible',\n width: rem(320),\n // 320 for the panel plus the 56 the close button column takes. Narrower phones give the panel\n // up, not the button — at a hard 320 the button would be the part pushed off-screen.\n maxWidth: 'calc(100vw - 56px)',\n },\n drawerCloseButton: {\n alignItems: 'center',\n display: 'flex',\n // As tall as the header row, so the button centres on it.\n height: rem(56),\n insetBlockStart: 0,\n insetInlineEnd: '100%',\n paddingInlineEnd: '8',\n position: 'absolute',\n },\n drawerHeader: {\n alignItems: 'center',\n borderBlockEndColor: 'border/regular',\n borderBlockEndStyle: 'solid',\n borderBlockEndWidth: '1',\n display: 'flex',\n flexShrink: 0,\n minHeight: rem(56),\n paddingBlockEnd: '12',\n paddingBlockStart: '12',\n paddingInlineEnd: '24',\n paddingInlineStart: '16',\n },\n drawerHeaderAvatar: {\n display: 'flex',\n flexShrink: 0,\n },\n drawerHeaderTextBlock: {\n display: 'flex',\n flex: 1,\n flexDirection: 'column',\n minWidth: 0,\n },\n drawerHeaderTitle: {\n color: 'text/primary',\n textStyle: 'heading/mobile/h2',\n truncate: true,\n },\n drawerHeaderSecondaryText: {\n color: 'text/secondary',\n textStyle: 'body/md/regular',\n truncate: true,\n },\n body: {\n display: 'flex',\n // Absorbs the slack so the footer sits at the bottom when the navigation is short, and\n // simply grows when it is long.\n flex: 1,\n flexDirection: 'column',\n // Half of the gap to the footer block; the footer carries the other half. Split that way so\n // this one is also the sidebar's bottom padding when there is no footer -- 8 either way,\n // rather than the body's whole 16 becoming the bottom edge. It is a margin so it stays\n // outside the items' own box, and `flex: 1` above means any extra space lands in the body\n // rather than widening the gap. Margins do not collapse in a flex column, so the two add up.\n marginBlockEnd: '8',\n width: 'full',\n // The fade at the bottom while there is more to scroll to, driven by the body's own scroll\n // position: a body that doesn't scroll has an inactive timeline, which applies nothing.\n // Browsers without scroll-driven animations show no fade.\n '@supports (animation-timeline: scroll())': {\n animationFillMode: 'both',\n animationName: 'page-sidebar-more-below',\n animationTimeline: 'scroll(self)',\n animationTimingFunction: 'linear',\n },\n },\n title: {\n alignItems: 'center',\n color: 'text/primary',\n display: 'flex',\n flexShrink: 0,\n overflow: 'clip',\n paddingInlineEnd: '32',\n },\n titleBlock: {\n alignItems: 'center',\n display: 'flex',\n minWidth: 0,\n },\n titleText: {\n textStyle: 'heading/h3',\n whiteSpace: 'nowrap',\n },\n item: {\n alignItems: 'center',\n cursor: 'pointer',\n display: 'flex',\n focusVisibleRing: 'inside',\n gap: '12',\n overflow: 'clip',\n // 48 tall on mobile against 40 on desktop — the row is a touch target there.\n paddingBlock: { base: '12', tablet: '8' },\n paddingInline: '24',\n position: 'relative',\n width: 'full',\n // Mobile reaches for `background/hover` / `background/active` where desktop uses the\n // `secondary` / `tertiary` surfaces. The two happen to resolve close, but they are separate\n // tokens in the design and the mobile item (`9221:4406`) binds these.\n _hover: {\n background: { base: 'background/hover', tablet: 'background/secondary' },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n },\n _active: {\n background: { base: 'background/active', tablet: 'background/tertiary' },\n },\n // `focusVisibleRing: 'inside'` still resolves to `outline-offset: 0`, which draws the ring\n // just outside the border box. The item spans the sidebar's full width, so that would bleed\n // past the sidebar's edges — pull the whole ring inside the item instead.\n _focusVisible: {\n outlineOffset: 'calc(var(--focus-ring-width) * -1)',\n },\n },\n contentBlock: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 0,\n // Pads the 16px icon out to the 24px line box on desktop. The mobile icon is already 24, so\n // there is nothing to make up — the row would just grow past 48.\n paddingBlock: { base: '0', tablet: '2' },\n },\n itemIcon: {\n color: 'icon/secondary',\n flexShrink: 0,\n _groupHover: {\n color: 'icon/primary',\n },\n },\n itemLabel: {\n color: 'text/primary',\n flex: 1,\n minWidth: 0,\n overflow: 'hidden',\n textAlign: 'start',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n suffixIcon: {\n color: 'icon/tertiary',\n flexShrink: 0,\n },\n selectionMarker: {\n background: 'border/selected',\n // Mobile draws the marker as a plain 4px edge (`9221:4417`); desktop as a 2px rounded rule.\n borderEndStartRadius: { base: '0', tablet: '2' },\n borderStartStartRadius: { base: '0', tablet: '2' },\n height: 'full',\n insetBlockStart: 0,\n insetInlineEnd: 0,\n position: 'absolute',\n width: { base: '4', tablet: '2' },\n },\n footer: {\n borderBlockStart: '1px solid',\n borderColor: 'border/minimal',\n display: 'flex',\n flexDirection: 'column',\n // The body above absorbs the free space, so the footer needs no positioning of its own —\n // it just must not be squashed by a long list.\n flexShrink: 0,\n // The other half of the gap to the body — see its `marginBlockEnd`.\n marginBlockStart: '8',\n paddingBlock: '8',\n },\n section: {\n borderBlockStart: '1px solid',\n borderColor: 'border/minimal',\n display: 'flex',\n // Basis 0: the section takes only the space left under `Body`, which keeps its natural height\n // until this one is down to its `minHeight`.\n flex: '1 1 0',\n flexDirection: 'column',\n // A flex item won't shrink below its content otherwise. The consumer's `minHeight` replaces it.\n minHeight: 0,\n },\n sectionContent: {\n flex: 1,\n minHeight: 0,\n overflow: 'auto',\n },\n sectionTitle: {\n color: 'text/primary',\n flexShrink: 0,\n paddingBlockEnd: '8',\n paddingBlockStart: '16',\n paddingInline: '24',\n textStyle: 'heading/h4',\n },\n /**\n * The progress item's own text, rather than `itemLabel`: that slot grows to fill the row, which\n * here belongs to the blocker so the connector can run to the trailing edge.\n */\n progressLabel: {\n color: 'text/primary',\n minWidth: 0,\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /** Follows the label after a middle dot, which the component renders. */\n progressSecondaryText: {\n color: 'text/tertiary',\n flexShrink: 0,\n textStyle: { base: 'body/lg/regular', tablet: 'body/md/regular' },\n whiteSpace: 'nowrap',\n },\n /**\n * Badge and connector as one unit, taking the width the text leaves.\n *\n * `fit-content` rather than 0: the flex basis is 0, so with a shrinking text block beside it\n * there is no free space to grow into and the block would be handed the whole row -- leaving\n * the badge, which does not shrink, hanging off the trailing edge. The floor is the badge; the\n * connector inside is basis 0 and contributes nothing to it.\n */\n progressBlocker: {\n alignItems: 'center',\n display: 'flex',\n flex: 1,\n gap: '12',\n minWidth: 'fit-content',\n },\n /**\n * The status icon's own slot rather than `itemIcon`: that one brightens to `icon/primary` with\n * the row, which is right for navigation and wrong here -- hovering a stage would drop the\n * colour that says where it stands.\n */\n progressIcon: {\n // The colour a status-less icon takes -- the approvals step's, which the design draws in the\n // same `icon/secondary` as the navigation icons. `iconColor` overrides it per stage.\n color: 'icon/secondary',\n flexShrink: 0,\n // Its own slot rather than `itemIcon`, but it does brighten with the row: the design moves the\n // icon to `icon/primary` on hover and active. That only ever reaches a colour this recipe\n // supplied -- a consumer's `iconColor` is an inline, unlayered `color` and beats it -- so a\n // stage's status survives the hover while a status-less icon follows the row.\n _groupHover: {\n color: 'icon/primary',\n },\n },\n /**\n * Label and secondary text read as one line, so they sit closer than the row's own 12 gap.\n *\n * It shrinks before the blocker does: `item` clips its overflow, so without this a long stage\n * name is cut mid-word and pushes the secondary text and the connector off the row. The\n * blocker keeps `flex: 1`, so it still takes the slack whenever the text is short enough.\n */\n progressTextBlock: {\n alignItems: 'center',\n display: 'flex',\n flexShrink: 1,\n gap: '4',\n minWidth: 0,\n },\n /**\n * The progress row's block padding, which does not follow the navigation row's to 12 on mobile:\n * the design keeps this row on 8 at both widths, so it is 44 tall on mobile against a nav row's\n * 48. Layered over `item` rather than replacing it -- everything else about the row is shared.\n */\n progressRow: {\n paddingBlock: '8',\n },\n /** With the row above: 2 either side of the line box at both widths, so the block is 28. */\n progressContentBlock: {\n paddingBlock: '2',\n },\n progressConnector: {\n borderColor: 'border/minimal',\n borderStyle: 'dashed',\n flex: 1,\n },\n project: {\n display: 'flex',\n flexDirection: 'column',\n gap: '4',\n justifyContent: 'center',\n overflow: 'clip',\n paddingBlockEnd: { base: '12', tablet: '8' },\n paddingBlockStart: '8',\n paddingInlineEnd: { base: '24', tablet: '32' },\n paddingInlineStart: '24',\n whiteSpace: 'nowrap',\n },\n projectLabel: {\n color: 'text/tertiary',\n textStyle: 'heading/h6',\n },\n projectValue: {\n color: 'text/body',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n textStyle: 'body/lg/semibold',\n },\n projectValueWrapper: {\n display: 'flex',\n minWidth: 0,\n },\n divider: {\n // Both of the sidebar's separator roles are `border/minimal` — the group header\n // (`20014:6508`) and this plain rule (`20014:6511`) — against `border/regular` for the general\n // Separator component. The override is per-slot for that reason, not to limit blast radius.\n borderColor: 'border/minimal',\n // Mobile's separator row is 40 tall, which centres the rule at 19.5 a side; 20 is the token\n // next to it and the resulting 1px lands nowhere the eye can find it.\n marginBlock: { base: '20', tablet: '16' },\n marginInline: '24',\n width: 'auto',\n },\n },\n variants: {\n /**\n * `drawer` is the sidebar inside its mobile drawer panel: the panel carries the edge and the\n * width, so the navigation itself gives up its own and scrolls within the panel.\n */\n layout: {\n // `useResponsive` reports desktop until it has measured, so an opted-in sidebar would paint\n // in the flow on a phone and then jump into the drawer. Hidden below `tablet` instead: the\n // drawer branch takes over as soon as the measurement lands, with nothing to remove.\n hidden: {\n root: {\n display: { base: 'none', tablet: 'flex' },\n },\n },\n drawer: {\n root: {\n borderInlineEndWidth: 0,\n flex: 1,\n maxWidth: 'none',\n minHeight: 'auto',\n minWidth: 0,\n overflowY: 'auto',\n width: 'full',\n },\n },\n static: {},\n },\n /**\n * The drawer header's two shapes (Figma `mobilePageSidebarHeader`): a page title on its own, or\n * an entity — app or user — whose name steps down a size to make room for its secondary text.\n */\n hasSecondaryText: {\n true: {\n drawerHeader: { gap: '12' },\n drawerHeaderTitle: { textStyle: 'heading/mobile/h3' },\n },\n false: {\n drawerHeader: { gap: '8' },\n drawerHeaderTextBlock: { paddingInlineStart: '4' },\n },\n },\n hasBack: {\n // Redlines on the sub view (Figma `- page sidebar - interactions`): the title block sits at\n // x/y 16, is 40 tall, and the 32px back button sits at y 20 — i.e. the 4px padding belongs to\n // the block wrapping button + text, not to the text. Header totals 16 + 40 + 8 = 64.\n true: {\n title: {\n paddingBlockEnd: '8',\n paddingInlineStart: '16',\n },\n titleBlock: {\n gap: '4',\n paddingBlock: '4',\n },\n },\n // Main view: no button, so the text alone is the block — 6 + 28 + 6 = 40, header 16+40+16 = 72.\n false: {\n title: {\n paddingBlockEnd: '16',\n paddingInlineStart: '24',\n },\n titleBlock: {\n paddingBlock: '6',\n },\n },\n },\n isDisabled: {\n true: {\n item: {\n cursor: 'not-allowed',\n _hover: {\n background: 'transparent',\n _active: {\n background: 'transparent',\n },\n },\n _active: {\n background: 'transparent',\n },\n },\n itemIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n itemLabel: {\n color: 'text/disabled',\n },\n progressIcon: {\n color: 'icon/disabled',\n _groupHover: {\n color: 'icon/disabled',\n },\n },\n progressLabel: {\n color: 'text/disabled',\n },\n progressSecondaryText: {\n color: 'text/disabled',\n },\n },\n false: {},\n },\n selected: {\n true: {\n item: {\n background: 'background/selected',\n _hover: {\n background: 'background/selected-hover',\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n _active: {\n background: { base: 'background/selected-hover', tablet: 'background/selected-active' },\n },\n },\n itemIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n itemLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n progressIcon: {\n color: 'icon/interactive',\n _groupHover: {\n color: 'icon/interactive-hover',\n },\n },\n progressLabel: {\n textStyle: { base: 'body/lg/semibold', tablet: 'body/md/semibold' },\n },\n },\n false: {},\n },\n /**\n * A stage the release does not have to clear. Everything steps down one level -- the icon to\n * tertiary, the label to secondary -- so the row reads as present but not awaited. Hover and\n * active take both back to the row's ordinary colours, as they do for a required stage.\n *\n * `selected` wins over it, resolved in the component rather than here. The design draws the\n * pair (`selected=yes, notRequired=true`) and gives it the selected row's icon and label with\n * the `not required` secondary text kept, which is what dropping this variant produces.\n */\n notRequired: {\n true: {\n progressIcon: {\n color: 'icon/tertiary',\n _groupHover: { color: 'icon/primary' },\n },\n progressLabel: {\n color: 'text/secondary',\n _groupHover: { color: 'text/primary' },\n },\n },\n false: {},\n },\n withDivider: {\n true: {},\n false: {\n section: { borderBlockStartWidth: 0 },\n sectionTitle: { paddingBlockStart: 0 },\n },\n },\n },\n defaultVariants: {\n hasBack: false,\n hasSecondaryText: false,\n isDisabled: false,\n layout: 'static',\n notRequired: false,\n selected: false,\n withDivider: true,\n },\n});\n\nexport default pageSidebarSlotRecipe;\n"],"mappings":"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"}
|
|
@@ -1945,7 +1945,7 @@ declare const slotRecipes: {
|
|
|
1945
1945
|
false: {};
|
|
1946
1946
|
};
|
|
1947
1947
|
}>;
|
|
1948
|
-
pageSidebar: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "title" | "root" | "item" | "suffixIcon" | "titleText" | "titleBlock" | "itemLabel" | "itemIcon" | "contentBlock" | "drawerHeader" | "divider" | "drawerBackdrop" | "drawerCloseButton" | "drawerContent" | "drawerHeaderAvatar" | "drawerHeaderSecondaryText" | "drawerHeaderTextBlock" | "drawerHeaderTitle" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "selectionMarker", {
|
|
1948
|
+
pageSidebar: import('@chakra-ui/react').SlotRecipeDefinition<"body" | "footer" | "section" | "title" | "root" | "item" | "suffixIcon" | "titleText" | "titleBlock" | "itemLabel" | "itemIcon" | "sectionTitle" | "contentBlock" | "drawerHeader" | "divider" | "drawerBackdrop" | "drawerCloseButton" | "drawerContent" | "drawerHeaderAvatar" | "drawerHeaderSecondaryText" | "drawerHeaderTextBlock" | "drawerHeaderTitle" | "progressBlocker" | "progressConnector" | "progressContentBlock" | "progressIcon" | "progressLabel" | "progressRow" | "progressSecondaryText" | "progressTextBlock" | "project" | "projectLabel" | "projectValue" | "projectValueWrapper" | "sectionContent" | "selectionMarker", {
|
|
1949
1949
|
layout: {
|
|
1950
1950
|
hidden: {
|
|
1951
1951
|
root: {
|
|
@@ -2109,6 +2109,17 @@ declare const slotRecipes: {
|
|
|
2109
2109
|
};
|
|
2110
2110
|
false: {};
|
|
2111
2111
|
};
|
|
2112
|
+
withDivider: {
|
|
2113
|
+
true: {};
|
|
2114
|
+
false: {
|
|
2115
|
+
section: {
|
|
2116
|
+
borderBlockStartWidth: number;
|
|
2117
|
+
};
|
|
2118
|
+
sectionTitle: {
|
|
2119
|
+
paddingBlockStart: number;
|
|
2120
|
+
};
|
|
2121
|
+
};
|
|
2122
|
+
};
|
|
2112
2123
|
}>;
|
|
2113
2124
|
pageSubheader: import('@chakra-ui/react').SlotRecipeDefinition<"title" | "tabs" | "root" | "secondaryText" | "headerBlock" | "contentBlock" | "textBlock" | "actionBlock", {
|
|
2114
2125
|
isCapped: {
|
|
@@ -24,6 +24,10 @@ var keyframes = defineKeyframes({
|
|
|
24
24
|
from: { backgroundPosition: "var(--animate-from, 1rem) 0" },
|
|
25
25
|
to: { backgroundPosition: "var(--animate-to, 0) 0" }
|
|
26
26
|
},
|
|
27
|
+
"page-sidebar-more-below": {
|
|
28
|
+
"from, 99%": { maskImage: "linear-gradient(to bottom, black calc(100% - 2rem), transparent)" },
|
|
29
|
+
to: { maskImage: "none" }
|
|
30
|
+
},
|
|
27
31
|
"skeleton-shimmer": {
|
|
28
32
|
from: { transform: "translateX(-100%)" },
|
|
29
33
|
to: { transform: "translateX(100%)" }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"keyframes.js","names":[],"sources":["../../../lib/theme/tokens/keyframes.ts"],"sourcesContent":["import { defineKeyframes } from '@chakra-ui/react/styled-system';\n\nconst keyframes = defineKeyframes({\n spin: {\n '0%': { transform: 'rotate(0deg)' },\n '100%': { transform: 'rotate(360deg)' },\n },\n\n pulse: {\n '50%': { opacity: '0.5' },\n },\n\n ping: {\n '75%, 100%': {\n transform: 'scale(2)',\n opacity: '0',\n },\n },\n\n bounce: {\n '0%, 100%': {\n transform: 'translateY(-25%)',\n animationTimingFunction: 'cubic-bezier(0.8,0,1,1)',\n },\n '50%': {\n transform: 'none',\n animationTimingFunction: 'cubic-bezier(0,0,0.2,1)',\n },\n },\n\n 'bg-position': {\n from: { backgroundPosition: 'var(--animate-from, 1rem) 0' },\n to: { backgroundPosition: 'var(--animate-to, 0) 0' },\n },\n\n 'skeleton-shimmer': {\n from: { transform: 'translateX(-100%)' },\n to: { transform: 'translateX(100%)' },\n },\n\n position: {\n from: {\n insetInlineStart: 'var(--animate-from-x)',\n insetBlockStart: 'var(--animate-from-y)',\n },\n to: {\n insetInlineStart: 'var(--animate-to-x)',\n insetBlockStart: 'var(--animate-to-y)',\n },\n },\n\n 'circular-progress': {\n '0%': {\n strokeDasharray: '1, 400',\n strokeDashoffset: '0',\n },\n '50%': {\n strokeDasharray: '400, 400',\n strokeDashoffset: '-100%',\n },\n '100%': {\n strokeDasharray: '400, 400',\n strokeDashoffset: '-260%',\n },\n },\n\n // collapse\n 'expand-height': {\n from: { height: 'var(--collapsed-height, 0)' },\n to: { height: 'var(--height)' },\n },\n 'collapse-height': {\n from: { height: 'var(--height)' },\n to: { height: 'var(--collapsed-height, 0)' },\n },\n 'expand-width': {\n from: { width: 'var(--collapsed-width, 0)' },\n to: { width: 'var(--width)' },\n },\n 'collapse-width': {\n from: { height: 'var(--width)' },\n to: { height: 'var(--collapsed-width, 0)' },\n },\n\n // fade\n 'fade-in': {\n from: { opacity: 0 },\n to: { opacity: 1 },\n },\n 'fade-out': {\n from: { opacity: 1 },\n to: { opacity: 0 },\n },\n\n // slide from (full)\n 'slide-from-left-full': {\n from: { translate: '-100% 0' },\n to: { translate: '0 0' },\n },\n 'slide-from-right-full': {\n from: { translate: '100% 0' },\n to: { translate: '0 0' },\n },\n 'slide-from-top-full': {\n from: { translate: '0 -100%' },\n to: { translate: '0 0' },\n },\n 'slide-from-bottom-full': {\n from: { translate: '0 100%' },\n to: { translate: '0 0' },\n },\n\n // slide to (full)\n 'slide-to-left-full': {\n from: { translate: '0 0' },\n to: { translate: '-100% 0' },\n },\n 'slide-to-right-full': {\n from: { translate: '0 0' },\n to: { translate: '100% 0' },\n },\n 'slide-to-top-full': {\n from: { translate: '0 0' },\n to: { translate: '0 -100%' },\n },\n 'slide-to-bottom-full': {\n from: { translate: '0 0' },\n to: { translate: '0 100%' },\n },\n\n // slide from\n 'slide-from-top': {\n '0%': { translate: '0 -0.5rem' },\n to: { translate: '0' },\n },\n 'slide-from-bottom': {\n '0%': { translate: '0 0.5rem' },\n to: { translate: '0' },\n },\n 'slide-from-left': {\n '0%': { translate: '-0.5rem 0' },\n to: { translate: '0' },\n },\n 'slide-from-right': {\n '0%': { translate: '0.5rem 0' },\n to: { translate: '0' },\n },\n\n // slide to\n 'slide-to-top': {\n '0%': { translate: '0' },\n to: { translate: '0 -0.5rem' },\n },\n 'slide-to-bottom': {\n '0%': { translate: '0' },\n to: { translate: '0 0.5rem' },\n },\n 'slide-to-left': {\n '0%': { translate: '0' },\n to: { translate: '-0.5rem 0' },\n },\n 'slide-to-right': {\n '0%': { translate: '0' },\n to: { translate: '0.5rem 0' },\n },\n\n // scale\n 'scale-in': {\n from: { scale: '0.95' },\n to: { scale: '1' },\n },\n 'scale-out': {\n from: { scale: '1' },\n to: { scale: '0.95' },\n },\n});\n\nexport default keyframes;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"keyframes.js","names":[],"sources":["../../../lib/theme/tokens/keyframes.ts"],"sourcesContent":["import { defineKeyframes } from '@chakra-ui/react/styled-system';\n\nconst keyframes = defineKeyframes({\n spin: {\n '0%': { transform: 'rotate(0deg)' },\n '100%': { transform: 'rotate(360deg)' },\n },\n\n pulse: {\n '50%': { opacity: '0.5' },\n },\n\n ping: {\n '75%, 100%': {\n transform: 'scale(2)',\n opacity: '0',\n },\n },\n\n bounce: {\n '0%, 100%': {\n transform: 'translateY(-25%)',\n animationTimingFunction: 'cubic-bezier(0.8,0,1,1)',\n },\n '50%': {\n transform: 'none',\n animationTimingFunction: 'cubic-bezier(0,0,0.2,1)',\n },\n },\n\n 'bg-position': {\n from: { backgroundPosition: 'var(--animate-from, 1rem) 0' },\n to: { backgroundPosition: 'var(--animate-to, 0) 0' },\n },\n\n // `BitkitPageSidebar.Body`'s fade, run on its scroll timeline: on until the end is reached.\n 'page-sidebar-more-below': {\n 'from, 99%': { maskImage: 'linear-gradient(to bottom, black calc(100% - 2rem), transparent)' },\n to: { maskImage: 'none' },\n },\n\n 'skeleton-shimmer': {\n from: { transform: 'translateX(-100%)' },\n to: { transform: 'translateX(100%)' },\n },\n\n position: {\n from: {\n insetInlineStart: 'var(--animate-from-x)',\n insetBlockStart: 'var(--animate-from-y)',\n },\n to: {\n insetInlineStart: 'var(--animate-to-x)',\n insetBlockStart: 'var(--animate-to-y)',\n },\n },\n\n 'circular-progress': {\n '0%': {\n strokeDasharray: '1, 400',\n strokeDashoffset: '0',\n },\n '50%': {\n strokeDasharray: '400, 400',\n strokeDashoffset: '-100%',\n },\n '100%': {\n strokeDasharray: '400, 400',\n strokeDashoffset: '-260%',\n },\n },\n\n // collapse\n 'expand-height': {\n from: { height: 'var(--collapsed-height, 0)' },\n to: { height: 'var(--height)' },\n },\n 'collapse-height': {\n from: { height: 'var(--height)' },\n to: { height: 'var(--collapsed-height, 0)' },\n },\n 'expand-width': {\n from: { width: 'var(--collapsed-width, 0)' },\n to: { width: 'var(--width)' },\n },\n 'collapse-width': {\n from: { height: 'var(--width)' },\n to: { height: 'var(--collapsed-width, 0)' },\n },\n\n // fade\n 'fade-in': {\n from: { opacity: 0 },\n to: { opacity: 1 },\n },\n 'fade-out': {\n from: { opacity: 1 },\n to: { opacity: 0 },\n },\n\n // slide from (full)\n 'slide-from-left-full': {\n from: { translate: '-100% 0' },\n to: { translate: '0 0' },\n },\n 'slide-from-right-full': {\n from: { translate: '100% 0' },\n to: { translate: '0 0' },\n },\n 'slide-from-top-full': {\n from: { translate: '0 -100%' },\n to: { translate: '0 0' },\n },\n 'slide-from-bottom-full': {\n from: { translate: '0 100%' },\n to: { translate: '0 0' },\n },\n\n // slide to (full)\n 'slide-to-left-full': {\n from: { translate: '0 0' },\n to: { translate: '-100% 0' },\n },\n 'slide-to-right-full': {\n from: { translate: '0 0' },\n to: { translate: '100% 0' },\n },\n 'slide-to-top-full': {\n from: { translate: '0 0' },\n to: { translate: '0 -100%' },\n },\n 'slide-to-bottom-full': {\n from: { translate: '0 0' },\n to: { translate: '0 100%' },\n },\n\n // slide from\n 'slide-from-top': {\n '0%': { translate: '0 -0.5rem' },\n to: { translate: '0' },\n },\n 'slide-from-bottom': {\n '0%': { translate: '0 0.5rem' },\n to: { translate: '0' },\n },\n 'slide-from-left': {\n '0%': { translate: '-0.5rem 0' },\n to: { translate: '0' },\n },\n 'slide-from-right': {\n '0%': { translate: '0.5rem 0' },\n to: { translate: '0' },\n },\n\n // slide to\n 'slide-to-top': {\n '0%': { translate: '0' },\n to: { translate: '0 -0.5rem' },\n },\n 'slide-to-bottom': {\n '0%': { translate: '0' },\n to: { translate: '0 0.5rem' },\n },\n 'slide-to-left': {\n '0%': { translate: '0' },\n to: { translate: '-0.5rem 0' },\n },\n 'slide-to-right': {\n '0%': { translate: '0' },\n to: { translate: '0.5rem 0' },\n },\n\n // scale\n 'scale-in': {\n from: { scale: '0.95' },\n to: { scale: '1' },\n },\n 'scale-out': {\n from: { scale: '1' },\n to: { scale: '0.95' },\n },\n});\n\nexport default keyframes;\n"],"mappings":"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"}
|