@trackunit/react-components 1.17.22 → 1.17.24

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.
Files changed (58) hide show
  1. package/index.cjs.js +1321 -195
  2. package/index.esm.js +1321 -195
  3. package/package.json +1 -1
  4. package/src/components/Badge/Badge.d.ts +13 -6
  5. package/src/components/Card/CardBody.d.ts +38 -3
  6. package/src/components/Card/CardFooter.d.ts +44 -3
  7. package/src/components/Card/CardHeader.d.ts +43 -2
  8. package/src/components/CompletionStatusIndicator/CompletionStatusIndicator.d.ts +19 -10
  9. package/src/components/CopyableText/CopyableText.d.ts +28 -2
  10. package/src/components/DetailsList/DetailsList.d.ts +28 -7
  11. package/src/components/EmptyState/EmptyState.d.ts +24 -0
  12. package/src/components/EmptyValue/EmptyValue.d.ts +19 -1
  13. package/src/components/ExternalLink/ExternalLink.d.ts +35 -4
  14. package/src/components/Heading/Heading.d.ts +22 -1
  15. package/src/components/Highlight/Highlight.d.ts +32 -7
  16. package/src/components/HorizontalOverflowScroller/HorizontalOverflowScroller.d.ts +24 -9
  17. package/src/components/Icon/Icon.d.ts +19 -2
  18. package/src/components/KPI/KPISkeleton.d.ts +23 -2
  19. package/src/components/KPICard/KPICardSkeleton.d.ts +23 -2
  20. package/src/components/ListItem/ListItem.d.ts +25 -3
  21. package/src/components/ListItem/ListItemSkeleton.d.ts +24 -2
  22. package/src/components/Menu/MenuDivider/MenuDivider.d.ts +22 -1
  23. package/src/components/Menu/MenuItem/MenuItem.d.ts +30 -1
  24. package/src/components/Menu/MoreMenu/MoreMenu.d.ts +56 -2
  25. package/src/components/Notice/Notice.d.ts +33 -3
  26. package/src/components/Page/Page.d.ts +38 -2
  27. package/src/components/Page/PageContent.d.ts +34 -5
  28. package/src/components/PageHeader/PageHeader.d.ts +8 -4
  29. package/src/components/Pagination/Pagination.d.ts +31 -2
  30. package/src/components/Polygon/Polygon.d.ts +38 -3
  31. package/src/components/Popover/Popover.d.ts +8 -6
  32. package/src/components/Popover/PopoverContent.d.ts +29 -3
  33. package/src/components/Popover/PopoverTitle.d.ts +36 -2
  34. package/src/components/Popover/PopoverTrigger.d.ts +35 -4
  35. package/src/components/Portal/Portal.d.ts +35 -4
  36. package/src/components/PreferenceCard/PreferenceCard.d.ts +25 -3
  37. package/src/components/PreferenceCard/PreferenceCardSkeleton.d.ts +23 -2
  38. package/src/components/Prompt/Prompt.d.ts +42 -8
  39. package/src/components/SectionHeader/SectionHeader.d.ts +23 -3
  40. package/src/components/Sidebar/Sidebar.d.ts +12 -5
  41. package/src/components/Skeleton/SkeletonBlock/SkeletonBlock.d.ts +21 -5
  42. package/src/components/Skeleton/SkeletonLabel/SkeletonLabel.d.ts +21 -5
  43. package/src/components/SkeletonLines/SkeletonLines.d.ts +8 -6
  44. package/src/components/Spacer/Spacer.d.ts +17 -10
  45. package/src/components/Spinner/Spinner.d.ts +27 -6
  46. package/src/components/Tabs/Tab.d.ts +29 -2
  47. package/src/components/Tabs/TabContent.d.ts +46 -1
  48. package/src/components/Tabs/TabList.d.ts +29 -1
  49. package/src/components/Tabs/Tabs.d.ts +14 -1
  50. package/src/components/Tag/Tag.d.ts +13 -6
  51. package/src/components/Text/Text.d.ts +28 -3
  52. package/src/components/ToggleGroup/ToggleGroup.d.ts +30 -1
  53. package/src/components/ValueBar/ValueBar.d.ts +38 -2
  54. package/src/components/ValueBar/ValueBar.shared.d.ts +4 -0
  55. package/src/components/ValueBar/ValueBar.variants.d.ts +0 -3
  56. package/src/components/ZStack/ZStack.d.ts +23 -4
  57. package/src/components/buttons/Button/Button.d.ts +1 -1
  58. package/src/components/buttons/StarButton/StarButton.d.ts +24 -1
package/index.cjs.js CHANGED
@@ -120,10 +120,27 @@ const isSafari = () => {
120
120
  return ua.includes("safari") && !ua.includes("chrome");
121
121
  };
122
122
  /**
123
- * Icons help in making the interface more intuitive by providing visual cues for various actions or elements. They're used to enhance usability, and depending on the context, they can be used alone or paired with text to increase comprehension.
123
+ * Icon renders SVG icons from the icon sprite sheets. All [HeroIcons](https://heroicons.com/) as well as custom Trackunit icons are available.
124
+ * Icons support three sizes (small=16px, medium=20px, large=24px) and theme-based colors.
124
125
  *
125
- * All the [HeroIcons](https://heroicons.com/) as well as custom Trackunit icons are available.
126
+ * ### When to use
127
+ * Use Icon to provide visual cues for actions, statuses, or navigation. Icons can be used standalone or paired with text (e.g., inside Buttons, MenuItems, Tags).
128
+ *
129
+ * ### When not to use
130
+ * Do not use Icon alone for critical actions without an accessible label. Always provide `ariaLabel` or pair with visible text.
131
+ *
132
+ * @example Icons at different sizes
133
+ * ```tsx
134
+ * import { Icon } from "@trackunit/react-components";
126
135
  *
136
+ * const IconExamples = () => (
137
+ * <div className="flex items-center gap-4">
138
+ * <Icon name="MapPin" size="small" color="danger" />
139
+ * <Icon name="Truck" size="medium" color="primary" />
140
+ * <Icon name="Cog6Tooth" size="large" type="outline" />
141
+ * </div>
142
+ * );
143
+ * ```
127
144
  * @param {IconProps} props - The props for the Icon component
128
145
  * @returns {ReactElement} Icon component
129
146
  */
@@ -247,14 +264,21 @@ const cvaTagIcon = cssClassVarianceUtilities.cvaMerge(["cursor-pointer", "transi
247
264
 
248
265
  const TAG_TEXT_MIN_WIDTH_PX = sharedUtils.parseTailwindArbitraryValue(TAG_TEXT_MIN_WIDTH_CLASS);
249
266
  /**
250
- * The Tag component is used for labeling or categorizing items in the UI.
251
- * It's commonly used to indicate the status of an asset, mark a feature as Beta,
252
- * or display selected options in multi-select inputs.
267
+ * Tag is used for labeling or categorizing items in the UI. Common use cases include indicating asset status,
268
+ * marking features as Beta, or displaying selected options in multi-select inputs.
269
+ * Tags support dismissal (close button), icons, and multiple color variants.
253
270
  *
254
- * How to choose between Tag, Badge and Highlight?
271
+ * ### When to use
272
+ * Use Tag to label statuses, categories, or user selections. It supports colors for intent (success, warning, danger) and activity states.
273
+ *
274
+ * ### When not to use
275
+ * Do not use Tag for numeric counts — use `Badge`.
276
+ * Do not use Tag for highlighting data values — use `Highlight`.
277
+ *
278
+ * How to choose between Tag, `Badge` and `Highlight`?
255
279
  * - Use a Tag for labeling statuses, categories, or selections.
256
- * - Use a [Badge](https://design.iris.trackunit.com/?path=/docs/react-components-badge--docs) to indicate notifications or counts of applied elements, such as filters.
257
- * - Use a [Highlight](https://design.iris.trackunit.com/?path=/docs/react-components-highlight--docs) to draw attention to values in plain text that require special attention or have crossed a threshold.
280
+ * - Use a `Badge` to indicate notifications or counts of applied elements, such as filters.
281
+ * - Use a `Highlight` to draw attention to values in plain text that require special attention or have crossed a threshold.
258
282
  *
259
283
  * @example Status tags with different colors
260
284
  * ```tsx
@@ -501,12 +525,37 @@ const cvaText = cssClassVarianceUtilities.cvaMerge(["text-black", "m-0", "relati
501
525
  });
502
526
 
503
527
  /**
504
- * The Text component is used to apply Trackunit default typography styles to text.
528
+ * Text applies Trackunit default typography styles to body text. It renders as a `<p>`, `<span>`, or `<div>` element
529
+ * and supports size, weight, alignment, and style variants (subtle, inverted, uppercase, etc.).
530
+ *
531
+ * ### When to use
532
+ * Use Text for body content, descriptions, labels, and any non-heading text. It ensures consistent typography across the application.
533
+ *
534
+ * ### When not to use
535
+ * Do not use Text for page or section headings — use `Heading` instead.
505
536
  *
506
- * ### When to use
537
+ * @example Text with different sizes and weights
538
+ * ```tsx
539
+ * import { Text } from "@trackunit/react-components";
507
540
  *
508
- * Use Text when you want to show a text section, use Heading if you want to show a heading.
541
+ * const TextExamples = () => (
542
+ * <div>
543
+ * <Text size="large" weight="bold">Large bold text</Text>
544
+ * <Text size="medium">Default body text</Text>
545
+ * <Text size="small" subtle>Small subtle caption</Text>
546
+ * </div>
547
+ * );
548
+ * ```
549
+ * @example Inline text using span
550
+ * ```tsx
551
+ * import { Text } from "@trackunit/react-components";
509
552
  *
553
+ * const InlineExample = () => (
554
+ * <Text>
555
+ * Asset status: <Text type="span" weight="bold">Active</Text>
556
+ * </Text>
557
+ * );
558
+ * ```
510
559
  * @param {TextProps} props - The props for the Text component
511
560
  * @returns {ReactElement} Text component
512
561
  */
@@ -569,16 +618,37 @@ const cvaSpinnerContainer = cssClassVarianceUtilities.cvaMerge(["box-border", "p
569
618
  const cvaSpinnerLabel = cssClassVarianceUtilities.cvaMerge(["self-center", "text-center", "text-current"]);
570
619
 
571
620
  /**
572
- * The spinner component provides visual feedback that data is being processed.
621
+ * Spinner provides visual feedback that data is being processed. It reassures users that their action is being handled
622
+ * during short operations (1-5 seconds) such as saving, loading, or refreshing data.
623
+ *
624
+ * ### When to use
625
+ * Use Spinner for short-duration loading states: button actions, table refreshes, inline data fetches, or modal content loading.
573
626
  *
574
- * Spinners are used when performing actions. They notify to the user that their request is being processed. Although they do not provide details about what is occurring on the back-end, they reassure the user that their action is being processed.
627
+ * ### When not to use
628
+ * Do not use Spinner for long loading states where content structure is known — use `SkeletonBlock` or `SkeletonLabel` instead.
629
+ * Do not use Spinner for full-page loading — use `EmptyState` with `loading` prop.
575
630
  *
576
- * Common actions that benefit from spinners include any create, update, or delete actions that may have a lot of data to process. It can be used in a table, after a primary or secondary button click, or even in a modal.
631
+ * @example Centered spinner during data load
632
+ * ```tsx
633
+ * import { Spinner } from "@trackunit/react-components";
577
634
  *
578
- * Use a spinner component for any action that cannot be performed instantly and will only require a short time (between 1 to 5 seconds) to process.
635
+ * const LoadingContent = () => (
636
+ * <div className="h-64">
637
+ * <Spinner centering="centered" label="Loading assets..." />
638
+ * </div>
639
+ * );
640
+ * ```
641
+ * @example Small inline spinner
642
+ * ```tsx
643
+ * import { Spinner } from "@trackunit/react-components";
579
644
  *
580
- * Use when retrieving or refreshing small data amounts, such as status.
581
-
645
+ * const InlineLoading = () => (
646
+ * <div className="flex items-center gap-2">
647
+ * <Spinner size="small" centering="vertically" />
648
+ * <span>Saving...</span>
649
+ * </div>
650
+ * );
651
+ * ```
582
652
  * @param {SpinnerProps} props - The props for the Spinner component
583
653
  * @returns {ReactElement} Spinner component
584
654
  */
@@ -864,7 +934,7 @@ const cvaIconButton = cssClassVarianceUtilities.cvaMerge([], {
864
934
  * Use buttons to communicate actions users can take and to allow users to interact with the page. Each page should have one primary button, and any remaining calls to action should be represented as lower emphasis buttons.
865
935
  *
866
936
  * ### When not to use
867
- * Do not use buttons as navigational elements. Instead, use [Links](?path=/docs/components-link--docs) when the desired action is to take the user to a new page.
937
+ * Do not use buttons as navigational elements. Instead, use `Links` when the desired action is to take the user to a new page.
868
938
  *
869
939
  * @example Basic button with click handler
870
940
  * ```tsx
@@ -1214,14 +1284,21 @@ const cvaBadge = cssClassVarianceUtilities.cvaMerge([
1214
1284
  });
1215
1285
 
1216
1286
  /**
1217
- * The Badge component is used to indicate notifications or counts of applied elements.
1218
- * It's typically used to display numbers on elements like filters, tabs, or buttons.
1287
+ * Badge displays a numeric count or a small colored dot to indicate notifications or applied elements.
1288
+ * It is typically placed on buttons, tabs, or filters to draw attention to new or pending items.
1289
+ *
1290
+ * ### When to use
1291
+ * Use Badge to indicate a count (e.g., unread notifications, active filters) or as a compact status dot.
1292
+ *
1293
+ * ### When not to use
1294
+ * Do not use Badge for labeling statuses or categories — use `Tag` instead.
1295
+ * Do not use Badge for highlighting data values — use `Highlight`.
1219
1296
  *
1220
- * How to choose between Badge and Tag?
1297
+ * How to choose between Badge and `Tag`?
1221
1298
  * - Use a Badge to indicate notifications or counts of applied elements.
1222
- * - Use a [Tag](https://design.iris.trackunit.com/?path=/docs/react-components-tag--docs) for labeling statuses, categories, or selections.
1299
+ * - Use a `Tag` for labeling statuses, categories, or selections.
1223
1300
  *
1224
- * @example Badge with count and max value
1301
+ * @example Badge with count and max — Use `count` and `max` to show a capped notification count. Values above `max` display as "9+".
1225
1302
  * ```tsx
1226
1303
  * import { Badge, Button } from "@trackunit/react-components";
1227
1304
  *
@@ -1231,7 +1308,7 @@ const cvaBadge = cssClassVarianceUtilities.cvaMerge([
1231
1308
  * </Button>
1232
1309
  * );
1233
1310
  * ```
1234
- * @example Compact badge as status dot
1311
+ * @example Compact status dot Set `compact` to render a small colored dot without any count, useful for online/offline indicators.
1235
1312
  * ```tsx
1236
1313
  * import { Badge } from "@trackunit/react-components";
1237
1314
  *
@@ -1480,8 +1557,25 @@ const BreadcrumbContainer = ({ "data-testid": dataTestId, breadcrumbItems, }) =>
1480
1557
  };
1481
1558
 
1482
1559
  /**
1483
- * The StarButton component is used for favorite actions or similar.
1560
+ * StarButton renders a clickable star icon for toggling favorite/starred state.
1561
+ * The star appears in the primary color when starred and neutral when unstarred.
1484
1562
  *
1563
+ * ### When to use
1564
+ * Use StarButton for favorite or bookmark actions on list items, cards, or tables.
1565
+ *
1566
+ * ### When not to use
1567
+ * Do not use StarButton for primary actions — use `Button` or `IconButton`.
1568
+ *
1569
+ * @example Star button for favoriting an asset
1570
+ * ```tsx
1571
+ * import { StarButton } from "@trackunit/react-components";
1572
+ * import { useState } from "react";
1573
+ *
1574
+ * const FavoriteToggle = () => {
1575
+ * const [starred, setStarred] = useState(false);
1576
+ * return <StarButton starred={starred} onClick={() => setStarred(s => !s)} />;
1577
+ * };
1578
+ * ```
1485
1579
  * @param {StarButtonProps} props - The props for the StarButton component
1486
1580
  * @returns {ReactElement} StarButton component
1487
1581
  */
@@ -1629,10 +1723,45 @@ const Card = ({ children, onClick, fullHeight = false, onMouseEnter, onMouseLeav
1629
1723
  Card.displayName = "Card";
1630
1724
 
1631
1725
  /**
1632
- * The CardBody component should be used to inform the user of important information.
1726
+ * CardBody is the main content area of a Card. It provides consistent padding and gap between child elements.
1727
+ * Padding is applied here rather than on the Card itself to avoid insetting the scrollbar when content overflows.
1728
+ *
1729
+ * Use CardBody inside a Card to wrap the primary content.
1730
+ * It works alongside CardHeader and CardFooter.
1731
+ *
1732
+ * ### When to use
1733
+ * Use CardBody to wrap the main content area of a `Card`. It handles padding, gap, and flex direction so content is laid out consistently.
1633
1734
  *
1634
- * @summary For applying padding and gap to a Card.
1635
- * @description The padding must live here, and not on the Card itself, as to not inset the scrollbar in case of overflow
1735
+ * ### When not to use
1736
+ * Do not use CardBody outside of a `Card`. For standalone content layout, use standard flex or grid containers.
1737
+ *
1738
+ * @example Basic card body inside a card
1739
+ * ```tsx
1740
+ * import { Card, CardHeader, CardBody, Text } from "@trackunit/react-components";
1741
+ *
1742
+ * const AssetInfo = () => (
1743
+ * <Card>
1744
+ * <CardHeader heading="Asset Details" />
1745
+ * <CardBody>
1746
+ * <Text>Operating hours: 1,234</Text>
1747
+ * <Text>Status: Active</Text>
1748
+ * </CardBody>
1749
+ * </Card>
1750
+ * );
1751
+ * ```
1752
+ * @example Card body with custom direction and no gap
1753
+ * ```tsx
1754
+ * import { Card, CardBody } from "@trackunit/react-components";
1755
+ *
1756
+ * const HorizontalLayout = () => (
1757
+ * <Card>
1758
+ * <CardBody direction="row" gap="none" padding="none">
1759
+ * <div>Left section</div>
1760
+ * <div>Right section</div>
1761
+ * </CardBody>
1762
+ * </Card>
1763
+ * );
1764
+ * ```
1636
1765
  * @param {CardBodyProps} props - The props for the CardBody component
1637
1766
  * @returns {ReactElement} CardBody component
1638
1767
  */
@@ -1646,10 +1775,51 @@ const CardBody = ({ children, "data-testid": dataTestId, className, direction =
1646
1775
  };
1647
1776
 
1648
1777
  /**
1649
- * A simple footer intended to use with Cards and Modals.
1650
- * Currently only intended to contain Buttons.
1651
- * The buttons justifies to the right, but if you style a button with "margin-right: auto" it will move to the left
1778
+ * CardFooter provides a consistent footer section for a Card, typically containing action buttons.
1779
+ * Buttons are right-justified by default. To push a button to the left, apply `margin-right: auto` to it.
1780
+ *
1781
+ * Use CardFooter as the last child inside a Card, below CardBody.
1782
+ *
1783
+ * ### When to use
1784
+ * Use CardFooter to add action buttons (e.g., Save, Cancel, View Details) at the bottom of a `Card` or Modal.
1785
+ *
1786
+ * ### When not to use
1787
+ * Do not use CardFooter for content display. It is designed specifically for action buttons and controls.
1652
1788
  *
1789
+ * @example Card with footer actions
1790
+ * ```tsx
1791
+ * import { Card, CardHeader, CardBody, CardFooter, Button, Text } from "@trackunit/react-components";
1792
+ *
1793
+ * const ConfirmationCard = () => (
1794
+ * <Card>
1795
+ * <CardHeader heading="Confirm Action" />
1796
+ * <CardBody>
1797
+ * <Text>Are you sure you want to proceed?</Text>
1798
+ * </CardBody>
1799
+ * <CardFooter>
1800
+ * <Button variant="secondary">Cancel</Button>
1801
+ * <Button variant="primary">Confirm</Button>
1802
+ * </CardFooter>
1803
+ * </Card>
1804
+ * );
1805
+ * ```
1806
+ * @example Footer with left-aligned and right-aligned buttons
1807
+ * ```tsx
1808
+ * import { Card, CardBody, CardFooter, Button, Text } from "@trackunit/react-components";
1809
+ *
1810
+ * const FormCard = () => (
1811
+ * <Card>
1812
+ * <CardBody>
1813
+ * <Text>Form content here</Text>
1814
+ * </CardBody>
1815
+ * <CardFooter>
1816
+ * <Button variant="secondary-danger" className="mr-auto">Delete</Button>
1817
+ * <Button variant="secondary">Cancel</Button>
1818
+ * <Button variant="primary">Save</Button>
1819
+ * </CardFooter>
1820
+ * </Card>
1821
+ * );
1822
+ * ```
1653
1823
  * @param {CardFooterProps} props - The props for the CardFooter component
1654
1824
  * @returns {ReactElement} CardFooter component
1655
1825
  */
@@ -1693,8 +1863,29 @@ const cvaHeading = cssClassVarianceUtilities.cvaMerge(["m-0", "leading-normal",
1693
1863
  });
1694
1864
 
1695
1865
  /**
1696
- * The Heading is used for a heading of a section (h1,h2,h3,h4).
1866
+ * Heading renders semantic heading elements (h1, h2, h3, h4) with Trackunit typography styles.
1867
+ * The `variant` prop maps to the semantic heading level: "primary" = h1, "secondary" = h2, "tertiary" = h3, "subtitle" = h4.
1868
+ *
1869
+ * ### When to use
1870
+ * Use Heading for page titles, section titles, and any hierarchical heading. Choose the variant based on the semantic level of the heading.
1871
+ *
1872
+ * ### When not to use
1873
+ * Do not use Heading for body text — use `Text` instead.
1874
+ * Do not use Heading for page-level headers with actions — use `PageHeader` or `SectionHeader`.
1697
1875
  *
1876
+ * @example Heading variants
1877
+ * ```tsx
1878
+ * import { Heading } from "@trackunit/react-components";
1879
+ *
1880
+ * const HeadingExamples = () => (
1881
+ * <div>
1882
+ * <Heading variant="primary">Page Title (h1)</Heading>
1883
+ * <Heading variant="secondary">Section Title (h2)</Heading>
1884
+ * <Heading variant="tertiary">Subsection (h3)</Heading>
1885
+ * <Heading variant="subtitle" subtle>Subtitle (h4)</Heading>
1886
+ * </div>
1887
+ * );
1888
+ * ```
1698
1889
  * @param {HeadingProps} props - The props for the Heading component
1699
1890
  * @returns {ReactElement} Heading component
1700
1891
  */
@@ -1714,8 +1905,49 @@ const Heading = ({ variant = "primary", inverted = false, subtle = false, classN
1714
1905
  };
1715
1906
 
1716
1907
  /**
1717
- * Header for Cards.
1908
+ * CardHeader provides a consistent header section for a Card, including a heading, optional subheading, accessories, and action buttons.
1909
+ * It is designed to be used as the first child inside a Card, above CardBody.
1910
+ *
1911
+ * ### When to use
1912
+ * Use CardHeader when a `Card` needs a title and optional actions (e.g., close button, edit button). It handles heading layout, separator lines, and action placement.
1913
+ *
1914
+ * ### When not to use
1915
+ * Do not use CardHeader outside of a `Card`. For standalone section titles, use `SectionHeader` or `Heading` instead.
1718
1916
  *
1917
+ * @example Card header with heading and actions
1918
+ * ```tsx
1919
+ * import { Card, CardHeader, CardBody, Button, Text } from "@trackunit/react-components";
1920
+ *
1921
+ * const AssetCard = () => (
1922
+ * <Card>
1923
+ * <CardHeader
1924
+ * heading="Excavator #1234"
1925
+ * subHeading="Last updated: 2 hours ago"
1926
+ * actions={<Button variant="ghost" size="small">Edit</Button>}
1927
+ * />
1928
+ * <CardBody>
1929
+ * <Text>Operating hours: 1,234</Text>
1930
+ * </CardBody>
1931
+ * </Card>
1932
+ * );
1933
+ * ```
1934
+ * @example Card header with accessories and no separator
1935
+ * ```tsx
1936
+ * import { Card, CardHeader, CardBody, Badge, Text } from "@trackunit/react-components";
1937
+ *
1938
+ * const NotificationsCard = () => (
1939
+ * <Card>
1940
+ * <CardHeader
1941
+ * heading="Notifications"
1942
+ * accessories={<Badge count={5} color="primary" />}
1943
+ * hideSeparator
1944
+ * />
1945
+ * <CardBody>
1946
+ * <Text>Notification list here</Text>
1947
+ * </CardBody>
1948
+ * </Card>
1949
+ * );
1950
+ * ```
1719
1951
  * @param {CardHeaderProps} props - The props for the CardHeader component
1720
1952
  * @returns {ReactElement} CardHeader component
1721
1953
  */
@@ -2012,17 +2244,26 @@ const Collapsible = ({ children, expanded, id, variant, extraPadding }) => {
2012
2244
  };
2013
2245
 
2014
2246
  /**
2015
- * A component that displays a visual indicator based on the completion status.
2247
+ * CompletionStatusIndicator displays a visual icon or spinner based on a process completion status:
2248
+ * loading (spinner), success (green check circle), or error (red X circle). Returns null if no status flag is set.
2016
2249
  *
2017
- * @example
2018
- * <CompletionStatusIndicator loading={true} />
2019
- * <CompletionStatusIndicator error={true} />
2020
- * <CompletionStatusIndicator success={true} />
2021
- * @param {CompletionStatusIndicatorProps} props - The properties for the indicator.
2022
- * @param {boolean} props.loading - Indicates if the process is in a loading state.
2023
- * @param {boolean} props.error - Indicates if an error has occurred.
2024
- * @param {boolean} props.warning - Indicates if the process has a warning.
2025
- * @param {boolean} props.success - Indicates if the process was successful.
2250
+ * ### When to use
2251
+ * Use CompletionStatusIndicator to show inline feedback for async operations (e.g., form submissions, save actions, data syncs).
2252
+ *
2253
+ * ### When not to use
2254
+ * Do not use for page-level loading use `Spinner`.
2255
+ * Do not use for persistent status labels use `Tag` or `Notice`.
2256
+ *
2257
+ * @example Completion status for a save action
2258
+ * ```tsx
2259
+ * import { CompletionStatusIndicator } from "@trackunit/react-components";
2260
+ *
2261
+ * const SaveStatus = ({ saving, saved, failed }: { saving: boolean; saved: boolean; failed: boolean }) => (
2262
+ * <CompletionStatusIndicator loading={saving} success={saved} error={failed} />
2263
+ * );
2264
+ * ```
2265
+ * @param {CompletionStatusIndicatorProps} props - The props for the CompletionStatusIndicator component
2266
+ * @returns {ReactElement | null} CompletionStatusIndicator component, or null when no status flag is set
2026
2267
  */
2027
2268
  const CompletionStatusIndicator = ({ loading = false, error, success, ...rest }) => {
2028
2269
  if (loading) {
@@ -2131,8 +2372,34 @@ const cvaCopyableText = cssClassVarianceUtilities.cvaMerge([
2131
2372
  });
2132
2373
 
2133
2374
  /**
2134
- * The CopyableText component is used where the user should have easy access to copy information.
2135
-
2375
+ * CopyableText displays a text value that the user can click to copy to the clipboard.
2376
+ * It shows a brief animation on copy to provide visual feedback. The copied value can differ from the displayed text via `alternativeText`.
2377
+ *
2378
+ * ### When to use
2379
+ * Use CopyableText for identifiers, serial numbers, URLs, or any value the user may want to copy (e.g., asset IDs, error codes).
2380
+ *
2381
+ * ### When not to use
2382
+ * Do not use CopyableText for long paragraphs or content that doesn't need to be copied.
2383
+ *
2384
+ * @example Copyable serial number
2385
+ * ```tsx
2386
+ * import { CopyableText } from "@trackunit/react-components";
2387
+ *
2388
+ * const AssetSerial = () => (
2389
+ * <CopyableText text="SN-2024-00142" data-testid="serial-number" />
2390
+ * );
2391
+ * ```
2392
+ * @example Copyable text with alternative clipboard value
2393
+ * ```tsx
2394
+ * import { CopyableText } from "@trackunit/react-components";
2395
+ *
2396
+ * const AssetLink = () => (
2397
+ * <CopyableText
2398
+ * text="Excavator #1234"
2399
+ * alternativeText="https://app.trackunit.com/assets/1234"
2400
+ * />
2401
+ * );
2402
+ * ```
2136
2403
  * @param {CopyableTextProps} props - The props for the CopyableText component
2137
2404
  * @returns {ReactElement} CopyableText component
2138
2405
  */
@@ -2160,14 +2427,35 @@ const cvaDetailsList = cssClassVarianceUtilities.cvaMerge(["flex", "w-full", "mi
2160
2427
  const cvaDetailsListItem = cssClassVarianceUtilities.cvaMerge(["last:truncate"]);
2161
2428
 
2162
2429
  /**
2163
- * Renders a one-line list of details separated by a Slash icon.
2430
+ * DetailsList renders a one-line list of text values separated by slash icons.
2431
+ * It is used to display compact metadata such as model, serial number, or location in a single row.
2432
+ *
2433
+ * ### When to use
2434
+ * Use DetailsList to display a compact, horizontal list of metadata values (e.g., in a card subtitle or list item description).
2435
+ *
2436
+ * ### When not to use
2437
+ * Do not use DetailsList for key-value pairs — use a standard layout with labels. Do not use for long text — values should be short strings.
2438
+ *
2439
+ * @example Displaying asset metadata
2440
+ * ```tsx
2441
+ * import { DetailsList } from "@trackunit/react-components";
2442
+ *
2443
+ * const AssetMeta = () => (
2444
+ * <DetailsList details={["Excavator", "CAT 320", "SN-00142"]} />
2445
+ * );
2446
+ * ```
2447
+ * @example DetailsList inside a linked context
2448
+ * ```tsx
2449
+ * import { DetailsList } from "@trackunit/react-components";
2164
2450
  *
2165
- * @param {object} props - Component props.
2166
- * @param {string[]} props.details - Values to render.
2167
- * @param {string} [props.className] - Optional CSS class for customization.
2168
- * @param {boolean} [props.hasLink=false] - Whether the parent component contains a link.
2169
- * @param [props.ref] - Ref forwarded to the root element.
2170
- * @returns {ReactElement} The details list element.
2451
+ * const LinkedAssetMeta = () => (
2452
+ * <a href="/assets/123">
2453
+ * <DetailsList details={["Site: Oslo", "Group: Heavy"]} hasLink />
2454
+ * </a>
2455
+ * );
2456
+ * ```
2457
+ * @param {DetailsListProps} props - The props for the DetailsList component
2458
+ * @returns {ReactElement} DetailsList component
2171
2459
  */
2172
2460
  const DetailsList = ({ details, className, hasLink = false, ref }) => {
2173
2461
  return (jsxRuntime.jsx("div", { className: cvaDetailsList({ className, hasLink }), ref: ref, children: details.map((value, index, array) => (jsxRuntime.jsxs(react.Fragment, { children: [jsxRuntime.jsx("span", { className: cvaDetailsListItem({ className }), children: value }), index < array.length - 1 && (jsxRuntime.jsx("div", { className: "mx-0.5 flex items-center", children: jsxRuntime.jsx(Icon, { className: "w-4 text-neutral-300", color: "neutral", name: "Slash", size: "small" }) }))] }, index))) }));
@@ -2303,13 +2591,29 @@ const cvaSkeleton = cssClassVarianceUtilities.cvaMerge([
2303
2591
  });
2304
2592
 
2305
2593
  /**
2306
- * Display a single placeholder line for text content before data gets loaded to reduce load-time frustration.
2594
+ * SkeletonLabel renders a single animated placeholder line for text content. It uses text-size keys (text-xs, text-sm, text-base, etc.)
2595
+ * to match the visual cap-height of actual text, with appropriate vertical margins to maintain line-height alignment.
2596
+ *
2597
+ * ### When to use
2598
+ * Use SkeletonLabel as a loading placeholder for single text lines: labels, titles, descriptions, values.
2599
+ *
2600
+ * ### When not to use
2601
+ * For multiple text lines, use `SkeletonLines`.
2602
+ * For shape-based elements (images, icons, avatars), use `SkeletonBlock`.
2307
2603
  *
2308
- * Reduces height and adds vertical margins to match the visual space text occupies within its line-height.
2309
- * Uses text-size keys (text-xs, text-sm, text-base, etc.) for height to match actual text elements.
2604
+ * @example Skeleton label for a title and description
2605
+ * ```tsx
2606
+ * import { SkeletonLabel } from "@trackunit/react-components";
2310
2607
  *
2311
- * For multiple text lines, use SkeletonLines component instead.
2312
- * For shape-based elements (images, badges, buttons), use SkeletonBlock component instead.
2608
+ * const TextSkeleton = () => (
2609
+ * <div className="flex flex-col gap-1">
2610
+ * <SkeletonLabel textSize="text-lg" width={200} />
2611
+ * <SkeletonLabel textSize="text-sm" width="80%" />
2612
+ * </div>
2613
+ * );
2614
+ * ```
2615
+ * @param {SkeletonLabelProps} props - The props for the SkeletonLabel component
2616
+ * @returns {ReactElement} SkeletonLabel component
2313
2617
  */
2314
2618
  const SkeletonLabel = react.memo((props) => {
2315
2619
  const { width = "100%", textSize = "text-base", flexibleWidth = true, className, "data-testid": dataTestId, children, ref, } = props;
@@ -2459,8 +2763,26 @@ const EmptyState = ({ description, altText, image = "SEARCH_DOCUMENT", customIma
2459
2763
  const cvaEmptyValue = cssClassVarianceUtilities.cvaMerge(["text-neutral-400"]);
2460
2764
 
2461
2765
  /**
2462
- * The EmptyValue component renders a consistent "–" symbol to represent empty, null, undefined, or not applicable values in tables.
2766
+ * EmptyValue renders a consistent dash symbol ("–") to represent missing, null, undefined, or not applicable values.
2767
+ * It is primarily used in tables and detail lists to maintain visual consistency when data is absent.
2768
+ *
2769
+ * ### When to use
2770
+ * Use EmptyValue as a placeholder in table cells, detail lists, or any data display where values may be missing.
2771
+ *
2772
+ * ### When not to use
2773
+ * Do not use EmptyValue for empty pages or sections — use `EmptyState` instead.
2774
+ *
2775
+ * @example Empty value in a details row
2776
+ * ```tsx
2777
+ * import { EmptyValue, Text } from "@trackunit/react-components";
2463
2778
  *
2779
+ * const AssetDetail = ({ value }: { value?: string }) => (
2780
+ * <div className="flex justify-between">
2781
+ * <Text weight="bold">Serial Number</Text>
2782
+ * {value ? <Text>{value}</Text> : <EmptyValue />}
2783
+ * </div>
2784
+ * );
2785
+ * ```
2464
2786
  * @param {EmptyValueProps} props - The props for the EmptyValue component
2465
2787
  * @returns {ReactElement} EmptyValue component
2466
2788
  */
@@ -2500,10 +2822,41 @@ const cvaExternalLink = cssClassVarianceUtilities.cvaMerge(["underline", "decora
2500
2822
  });
2501
2823
 
2502
2824
  /**
2503
- * Link is an interactive element that allows users to navigate between different parts of an application or to external resources. Links are used to indicate clickable text.
2504
-
2505
- * @param {ExternalLinkProps} props - The props for the external link component
2506
- * @returns {ReactElement} External Link component
2825
+ * ExternalLink renders an anchor element for navigating to external URLs. It opens in a new tab by default with `rel="noreferrer"` for security.
2826
+ * If no children are provided, the href URL is displayed as the link text.
2827
+ *
2828
+ * ### When to use
2829
+ * Use ExternalLink for any links that navigate to external resources outside the application (e.g., documentation, support pages, vendor sites).
2830
+ *
2831
+ * ### When not to use
2832
+ * Do not use ExternalLink for in-app navigation. Use `Link` from `@tanstack/react-router` for internal routes.
2833
+ *
2834
+ * @example Basic external link
2835
+ * ```tsx
2836
+ * import { ExternalLink } from "@trackunit/react-components";
2837
+ *
2838
+ * const SupportLink = () => (
2839
+ * <ExternalLink href="https://support.trackunit.com">
2840
+ * Visit Support Center
2841
+ * </ExternalLink>
2842
+ * );
2843
+ * ```
2844
+ * @example Neutral colored link opening in same window
2845
+ * ```tsx
2846
+ * import { ExternalLink } from "@trackunit/react-components";
2847
+ *
2848
+ * const DocumentLink = () => (
2849
+ * <ExternalLink
2850
+ * href="https://docs.trackunit.com/api"
2851
+ * color="neutral"
2852
+ * target="_self"
2853
+ * >
2854
+ * API Documentation
2855
+ * </ExternalLink>
2856
+ * );
2857
+ * ```
2858
+ * @param {ExternalLinkProps} props - The props for the ExternalLink component
2859
+ * @returns {ReactElement} ExternalLink component
2507
2860
  */
2508
2861
  const ExternalLink = ({ rel = "noreferrer", target = "_blank", href, className, children = href, title = href, "data-testid": dataTestId, onClick, color = "primary", ref, }) => {
2509
2862
  return (jsxRuntime.jsx("a", { className: cvaExternalLink({ className, color }), "data-testid": dataTestId, href: href, onClick: onClick, ref: ref, rel: rel, target: target, title: title, children: children }));
@@ -3295,15 +3648,40 @@ const cvaHighlight = cssClassVarianceUtilities.cvaMerge([
3295
3648
  const cvaHighlightText = cssClassVarianceUtilities.cvaMerge(["truncate"]);
3296
3649
 
3297
3650
  /**
3298
- * The Highlight component is used to draw attention to data values that may require user action, monitoring, or investigation.
3299
- * It visually emphasizes out-of-range or critical values using color cues (e.g. danger or warning) to support quick scanning and awareness.
3651
+ * Highlight draws visual attention to data values that may require user action, monitoring, or investigation.
3652
+ * It uses color cues (e.g., danger, warning, success) to emphasize out-of-range or critical values for quick scanning.
3653
+ *
3654
+ * ### When to use
3655
+ * Use Highlight to emphasize numeric or text values inline that have crossed a threshold or need attention (e.g., temperature warnings, low battery).
3656
+ *
3657
+ * ### When not to use
3658
+ * Do not use Highlight for labeling statuses or categories — use `Tag`.
3659
+ * Do not use Highlight for notification counts — use `Badge`.
3660
+ *
3661
+ * @example Highlighting a warning value
3662
+ * ```tsx
3663
+ * import { Highlight, Text } from "@trackunit/react-components";
3300
3664
  *
3301
- * How to choose between Highlight and Tag?
3302
- * - Use Highlight to draw attention to values in plain text that require special attention or have crossed a threshold.
3303
- * - Use a [Tag](https://design.iris.trackunit.com/?path=/docs/react-components-tag--docs) for labeling statuses, categories, or selections.
3665
+ * const TemperatureDisplay = () => (
3666
+ * <Text>
3667
+ * Engine temperature: <Highlight color="warning">92°C</Highlight>
3668
+ * </Text>
3669
+ * );
3670
+ * ```
3671
+ * @example Different highlight colors for thresholds
3672
+ * ```tsx
3673
+ * import { Highlight } from "@trackunit/react-components";
3304
3674
  *
3305
- * @param {HighlightProps} props - The props for the highlight component
3306
- * @returns {ReactElement} highlight component
3675
+ * const BatteryStatus = () => (
3676
+ * <div className="flex gap-2">
3677
+ * <Highlight color="success">85%</Highlight>
3678
+ * <Highlight color="warning">32%</Highlight>
3679
+ * <Highlight color="danger">8%</Highlight>
3680
+ * </div>
3681
+ * );
3682
+ * ```
3683
+ * @param {HighlightProps} props - The props for the Highlight component
3684
+ * @returns {ReactElement} Highlight component
3307
3685
  */
3308
3686
  const Highlight = ({ className, "data-testid": dataTestId, children, size = "small", color = "warning", ref, }) => {
3309
3687
  return (jsxRuntime.jsx("div", { className: cvaHighlight({ className, size, color }), "data-testid": dataTestId, ref: ref, children: jsxRuntime.jsx("span", { className: cvaHighlightText(), children: children }) }));
@@ -3565,11 +3943,30 @@ const cvaZStackContainer = cssClassVarianceUtilities.cvaMerge(["grid", "grid-col
3565
3943
  const cvaZStackItem = cssClassVarianceUtilities.cvaMerge(["col-start-1", "col-end-1", "row-start-1", "row-end-2"]);
3566
3944
 
3567
3945
  /**
3568
- * ZStack is a component that stacks its children on the z-axis.
3569
- * Is a good alternative to "position: absolute" that avoids some of the unfortunate side effects of absolute positioning.
3946
+ * ZStack stacks its children on the z-axis (overlaying them on top of each other).
3947
+ * It is a CSS grid-based alternative to `position: absolute` that avoids side effects like elements being removed from the document flow.
3948
+ *
3949
+ * ### When to use
3950
+ * Use ZStack when you need to overlay elements on top of each other (e.g., an image with a badge overlay, or a scroll container with fade indicators).
3951
+ *
3952
+ * ### When not to use
3953
+ * Do not use ZStack for standard stacking/layout — use flex or grid containers instead.
3570
3954
  *
3571
- * @param { ZStackProps} props - The props for the ZStack component
3572
- * @returns {Element} ZStack component
3955
+ * @example Overlaying a badge on a thumbnail
3956
+ * ```tsx
3957
+ * import { ZStack, Badge, Icon } from "@trackunit/react-components";
3958
+ *
3959
+ * const ThumbnailWithBadge = () => (
3960
+ * <ZStack>
3961
+ * <Icon name="Truck" size="large" />
3962
+ * <div className="self-start justify-self-end">
3963
+ * <Badge count={3} color="danger" />
3964
+ * </div>
3965
+ * </ZStack>
3966
+ * );
3967
+ * ```
3968
+ * @param {ZStackProps} props - The props for the ZStack component
3969
+ * @returns {ReactElement} ZStack component
3573
3970
  */
3574
3971
  const ZStack = ({ children, className, "data-testid": dataTestId, ref }) => {
3575
3972
  return (jsxRuntime.jsx("div", { className: cvaZStackContainer({ className }), "data-testid": dataTestId, ref: ref, children: react.Children.map(children, (child, index) => {
@@ -3635,16 +4032,31 @@ const OverflowIndicator = ({ className, "data-testid": dataTestId, direction, on
3635
4032
  };
3636
4033
 
3637
4034
  /**
3638
- * Container for displaying components in a horizontal layout with overflow detection.
3639
- * Provides visual indicators when content overflows and can be scrolled.
4035
+ * HorizontalOverflowScroller displays child elements in a horizontal row with automatic overflow detection.
4036
+ * When content overflows, it shows left/right scroll indicators with click-to-scroll functionality.
3640
4037
  *
3641
- * @param props - Component properties
3642
- * @param props.children - The content to display in the horizontal scroller
3643
- * @param props.className - Optional CSS class name for styling
3644
- * @param props."data-testid" - Optional test ID for testing purposes
3645
- * @param props.onScrollStateChange - Optional callback fired when scroll state changes
3646
- * @param [props.ref] - Ref forwarded to the root element
3647
- * @returns {ReactElement} A horizontal overflow scroller component with visual indicators
4038
+ * ### When to use
4039
+ * Use HorizontalOverflowScroller to display a row of items (cards, tags, buttons) that may overflow on smaller screens, with visual cues that more content is available.
4040
+ *
4041
+ * ### When not to use
4042
+ * Do not use HorizontalOverflowScroller for tab navigation — use `TabList` which has its own scroll handling.
4043
+ *
4044
+ * @example Horizontal scroller for KPI cards
4045
+ * ```tsx
4046
+ * import { HorizontalOverflowScroller, Tag } from "@trackunit/react-components";
4047
+ *
4048
+ * const TagRow = () => (
4049
+ * <HorizontalOverflowScroller>
4050
+ * <Tag color="success">Active</Tag>
4051
+ * <Tag color="warning">Idle</Tag>
4052
+ * <Tag color="danger">Offline</Tag>
4053
+ * <Tag color="info">Maintenance</Tag>
4054
+ * <Tag color="neutral">Archived</Tag>
4055
+ * </HorizontalOverflowScroller>
4056
+ * );
4057
+ * ```
4058
+ * @param {HorizontalOverflowScrollerProps} props - The props for the HorizontalOverflowScroller component
4059
+ * @returns {ReactElement} HorizontalOverflowScroller component
3648
4060
  */
3649
4061
  const HorizontalOverflowScroller = ({ className, "data-testid": dataTestId, children, onScrollStateChange, ref, }) => {
3650
4062
  const childrenArray = react.Children.toArray(children);
@@ -3888,14 +4300,16 @@ const usePopoverContext = () => {
3888
4300
  return context;
3889
4301
  };
3890
4302
  /**
3891
- * The popover component.
3892
- * - This component should wrap all the popover components.
3893
- * - It returns a context that is used by the popover components.
3894
- * - The context is used to share the state of the popover, such as the open state and the reference element.
4303
+ * Popover is a floating overlay that appears relative to a trigger element. It provides a context for
4304
+ * PopoverTrigger and PopoverContent children,
4305
+ * managing open/close state, positioning, and focus management.
3895
4306
  *
3896
- * To open the popover, use the `<PopoverTrigger />` component.
4307
+ * ### When to use
4308
+ * Use Popover for contextual information, menus, or forms that should appear near a trigger element without navigating away.
3897
4309
  *
3898
- * To render the content of the popover, use the `<PopoverContent />` component.
4310
+ * ### When not to use
4311
+ * Do not use Popover for simple text hints — use `Tooltip` instead.
4312
+ * For full-screen overlays or blocking dialogs, use a Modal.
3899
4313
  *
3900
4314
  * @example Basic popover with trigger
3901
4315
  * ```tsx
@@ -3964,10 +4378,41 @@ const getDefaultPortalContainer = () => {
3964
4378
  };
3965
4379
 
3966
4380
  /**
3967
- * Portals the floating element into a given container element
3968
- * By default they're portalled into an z-index isolated div in
3969
- * document body -> div#portal-container.
3970
- * alongside other portalled elements.
4381
+ * Portal renders its children into a separate DOM node, outside the normal React tree hierarchy.
4382
+ * By default, content is portalled into a z-index-isolated `div#portal-container` in the document body.
4383
+ * This is used internally by Popover, Tooltip, and other overlay components.
4384
+ *
4385
+ * ### When to use
4386
+ * Use Portal when you need to render content (modals, popovers, tooltips) outside its parent's DOM hierarchy to avoid z-index or overflow clipping issues.
4387
+ *
4388
+ * ### When not to use
4389
+ * Do not use Portal for regular content rendering. Most overlay components (`Popover`, `Tooltip`) already use Portal internally.
4390
+ *
4391
+ * @example Rendering into a specific container
4392
+ * ```tsx
4393
+ * import { Portal } from "@trackunit/react-components";
4394
+ *
4395
+ * const PortalledContent = () => (
4396
+ * <Portal root={document.getElementById('sidebar-container')}>
4397
+ * <div className="p-4">This content renders in #sidebar-container</div>
4398
+ * </Portal>
4399
+ * );
4400
+ * ```
4401
+ * @example Default portal into document body
4402
+ * ```tsx
4403
+ * import { Portal } from "@trackunit/react-components";
4404
+ *
4405
+ * const FloatingContent = ({ isVisible }: { isVisible: boolean }) => (
4406
+ * isVisible ? (
4407
+ * <Portal>
4408
+ * <div className="fixed bottom-4 right-4 bg-white p-4 rounded-lg shadow-lg">
4409
+ * Toast notification content
4410
+ * </div>
4411
+ * </Portal>
4412
+ * ) : null
4413
+ * );
4414
+ * @param {PortalProps} props - The props for the Portal component
4415
+ * @returns {ReactElement} Portal component
3971
4416
  */
3972
4417
  const Portal = (props) => {
3973
4418
  return jsxRuntime.jsx(react$1.FloatingPortal, { ...props, root: props.root ?? getDefaultPortalContainer() });
@@ -3985,11 +4430,37 @@ const cvaPopoverTitleContainer = cssClassVarianceUtilities.cvaMerge(["flex", "it
3985
4430
  const cvaPopoverTitleText = cssClassVarianceUtilities.cvaMerge(["flex-1", "text-neutral-500"]);
3986
4431
 
3987
4432
  /**
3988
- * The PopoverContent component displays the content inside a popover overlay.
4433
+ * PopoverContent displays the floating content inside a Popover.
4434
+ * It renders in a portal and manages focus, positioning, and accessibility. Must be a child of a Popover.
3989
4435
  *
3990
- * This component must be used within a `<Popover>` component. It renders the content
3991
- * in a portal and manages focus, positioning, and accessibility features.
4436
+ * The `children` prop can be a ReactNode or a render function that receives a `close` callback to programmatically dismiss the popover.
3992
4437
  *
4438
+ * ### When to use
4439
+ * Use PopoverContent inside a `Popover` to define what appears in the floating overlay.
4440
+ *
4441
+ * ### When not to use
4442
+ * Do not use PopoverContent outside of a `Popover` context. It relies on `Popover`'s context for positioning and state.
4443
+ *
4444
+ * @example PopoverContent with close callback
4445
+ * ```tsx
4446
+ * import { Popover, PopoverTrigger, PopoverContent, Button, Text } from "@trackunit/react-components";
4447
+ *
4448
+ * const DismissablePopover = () => (
4449
+ * <Popover>
4450
+ * <PopoverTrigger>
4451
+ * <Button variant="secondary">Open</Button>
4452
+ * </PopoverTrigger>
4453
+ * <PopoverContent>
4454
+ * {(close) => (
4455
+ * <div className="p-4">
4456
+ * <Text>Popover content here</Text>
4457
+ * <Button onClick={close} size="small">Done</Button>
4458
+ * </div>
4459
+ * )}
4460
+ * </PopoverContent>
4461
+ * </Popover>
4462
+ * );
4463
+ * ```
3993
4464
  * @param {PopoverContentProps} props - The props for the PopoverContent component
3994
4465
  * @returns {ReactElement} The popover content element
3995
4466
  */
@@ -4006,8 +4477,34 @@ const PopoverContent = function PopoverContent({ className, "data-testid": dataT
4006
4477
  };
4007
4478
 
4008
4479
  /**
4009
- * The PopoverTrigger component is used to trigger the popover.
4480
+ * PopoverTrigger is the clickable element that opens or closes a Popover.
4481
+ * It must be used as a direct child of a Popover component. By default, it clones the child element and attaches popover behavior.
4482
+ * Set `renderButton` to true to wrap children in a default Button.
4483
+ *
4484
+ * ### When to use
4485
+ * Use PopoverTrigger inside a `Popover` to designate which element opens the popover overlay.
4486
+ *
4487
+ * ### When not to use
4488
+ * Do not use PopoverTrigger outside of a `Popover` context. It relies on `Popover`'s context for state management.
4489
+ *
4490
+ * @example PopoverTrigger with a custom button
4491
+ * ```tsx
4492
+ * import { Popover, PopoverTrigger, PopoverContent, IconButton, Icon } from "@trackunit/react-components";
4010
4493
  *
4494
+ * const IconPopover = () => (
4495
+ * <Popover placement="bottom">
4496
+ * <PopoverTrigger>
4497
+ * <IconButton
4498
+ * icon={<Icon name="InformationCircle" size="small" />}
4499
+ * variant="ghost"
4500
+ * />
4501
+ * </PopoverTrigger>
4502
+ * <PopoverContent>
4503
+ * <div className="p-3">Helpful information</div>
4504
+ * </PopoverContent>
4505
+ * </Popover>
4506
+ * );
4507
+ * ```
4011
4508
  * @param {PopoverTriggerProps} props - The props for the PopoverTrigger component
4012
4509
  * @returns {ReactElement} PopoverTrigger component
4013
4510
  */
@@ -4464,8 +4961,29 @@ const KPI = ({ title, value, unit, className, "data-testid": dataTestId, tooltip
4464
4961
  };
4465
4962
 
4466
4963
  /**
4467
- * Skeleton loading indicator that mimics the KPI component structure.
4468
- * Uses the same layout, spacing, and visual hierarchy as KPI.
4964
+ * KPISkeleton is a loading placeholder that mimics the layout of a KPI component.
4965
+ * It renders skeleton lines for the title and value with randomized widths for a natural appearance.
4966
+ *
4967
+ * ### When to use
4968
+ * Use KPISkeleton while `KPI` data is loading to maintain layout stability and reduce perceived load time.
4969
+ *
4970
+ * ### When not to use
4971
+ * Do not use KPISkeleton for generic text loading — use `SkeletonLabel`.
4972
+ *
4973
+ * @example KPI skeleton in a dashboard
4974
+ * ```tsx
4975
+ * import { KPISkeleton } from "@trackunit/react-components";
4976
+ *
4977
+ * const LoadingDashboard = () => (
4978
+ * <div className="flex gap-4">
4979
+ * <KPISkeleton variant="default" />
4980
+ * <KPISkeleton variant="default" />
4981
+ * <KPISkeleton variant="small" />
4982
+ * </div>
4983
+ * );
4984
+ * ```
4985
+ * @param {KPISkeletonProps} props - The props for the KPISkeleton component
4986
+ * @returns {ReactElement} KPISkeleton component
4469
4987
  */
4470
4988
  const KPISkeleton = ({ variant = "default", className, "data-testid": dataTestId, style, ref, ...rest }) => {
4471
4989
  const isSmallVariant = variant === "small";
@@ -4494,32 +5012,34 @@ const TrendIndicators = ({ trends, "data-testid": dataTestId, className, ref, })
4494
5012
  return (jsxRuntime.jsx("span", { className: tailwindMerge.twMerge("flex flex-row items-center gap-1", className), "data-testid": dataTestId, ref: ref, children: trends.map((trend, index) => (jsxRuntime.jsx(TrendIndicator, { "data-testid": dataTestId ? `${dataTestId}-trend-indicator-${index}` : undefined, ...trend }, index))) }));
4495
5013
  };
4496
5014
 
4497
- const cvaValueBar = cssClassVarianceUtilities.cvaMerge([
4498
- "w-full",
4499
- "overflow-hidden",
4500
- "rounded",
4501
- "bg-neutral-100",
4502
- "appearance-none",
4503
- "[&::-webkit-progress-bar]:bg-transparent",
4504
- "[&::-webkit-progress-value]:bg-current",
4505
- "[&::-moz-progress-bar]:bg-current",
4506
- ], {
5015
+ const valueBarContainerClassName = "relative flex w-full items-center gap-2";
5016
+ const cvaValueBarText = cssClassVarianceUtilities.cvaMerge(["whitespace-nowrap"], {
4507
5017
  variants: {
4508
5018
  size: {
4509
- extraSmall: "h-1",
4510
- small: "h-3",
4511
- large: "h-9",
5019
+ small: "leading-xs text-xs font-medium text-neutral-600",
5020
+ large: "absolute pl-3 text-base text-white drop-shadow-lg",
4512
5021
  },
4513
5022
  },
4514
5023
  defaultVariants: {
4515
5024
  size: "small",
4516
5025
  },
4517
5026
  });
4518
- const cvaValueBarText = cssClassVarianceUtilities.cvaMerge(["whitespace-nowrap"], {
5027
+
5028
+ const cvaValueBar = cssClassVarianceUtilities.cvaMerge([
5029
+ "w-full",
5030
+ "overflow-hidden",
5031
+ "rounded",
5032
+ "bg-neutral-100",
5033
+ "appearance-none",
5034
+ "[&::-webkit-progress-bar]:bg-transparent",
5035
+ "[&::-webkit-progress-value]:bg-current",
5036
+ "[&::-moz-progress-bar]:bg-current",
5037
+ ], {
4519
5038
  variants: {
4520
5039
  size: {
4521
- small: "leading-xs text-xs font-medium text-neutral-600",
4522
- large: "absolute pl-3 text-base text-white drop-shadow-lg",
5040
+ extraSmall: "h-1",
5041
+ small: "h-3",
5042
+ large: "h-9",
4523
5043
  },
4524
5044
  },
4525
5045
  defaultVariants: {
@@ -4595,8 +5115,44 @@ const getValueBarColorByValue = (value, min, max, levelColors) => {
4595
5115
  };
4596
5116
 
4597
5117
  /**
4598
- * ValueBar component is used to display value on a colorful bar within provided range.
4599
-
5118
+ * ValueBar displays a numeric value as a colored progress bar within a defined range.
5119
+ * The bar color changes based on the score (value relative to min/max) using either default or custom level colors.
5120
+ * It can optionally display the numeric value and unit alongside the bar.
5121
+ *
5122
+ * ### When to use
5123
+ * Use ValueBar to visualize a metric relative to a range (e.g., battery level, fuel percentage, utilization rate, temperature).
5124
+ *
5125
+ * ### When not to use
5126
+ * Do not use ValueBar for progress through a multi-step process. Use a stepper or progress indicator instead.
5127
+ *
5128
+ * @example Basic value bar with percentage
5129
+ * ```tsx
5130
+ * import { ValueBar } from "@trackunit/react-components";
5131
+ *
5132
+ * const BatteryLevel = () => (
5133
+ * <ValueBar value={72} min={0} max={100} unit="%" showValue />
5134
+ * );
5135
+ * ```
5136
+ * @example Value bar with custom level colors
5137
+ * ```tsx
5138
+ * import { ValueBar } from "@trackunit/react-components";
5139
+ *
5140
+ * const TemperatureBar = () => (
5141
+ * <ValueBar
5142
+ * value={85}
5143
+ * min={0}
5144
+ * max={120}
5145
+ * unit="°C"
5146
+ * showValue
5147
+ * size="large"
5148
+ * levelColors={[
5149
+ * { min: 0, max: 0.5, color: "#22c55e" },
5150
+ * { min: 0.5, max: 0.75, color: "#f59e0b" },
5151
+ * { min: 0.75, max: 1, color: "#ef4444" },
5152
+ * ]}
5153
+ * />
5154
+ * );
5155
+ * ```
4600
5156
  * @param {ValueBarProps} props - The props for the ValueBar component
4601
5157
  * @returns {ReactElement} ValueBar component
4602
5158
  */
@@ -4604,7 +5160,7 @@ const ValueBar = ({ value, min = 0, max = 100, unit, size = "small", levelColors
4604
5160
  const score = getScore(value, min, max, zeroScoreAllowed);
4605
5161
  const barFillColor = levelColors ? getFillColor(score, levelColors) : getDefaultFillColor(score);
4606
5162
  const valueText = `${Number(value.toFixed(1))}${sharedUtils.nonNullable(unit) ? unit : ""}`;
4607
- return (jsxRuntime.jsxs("span", { className: "relative flex items-center gap-2", "data-testid": dataTestId, ref: ref, children: [jsxRuntime.jsx("progress", { "aria-label": valueText, className: cvaValueBar({ className, size }), max: 100, style: { color: barFillColor }, value: score * 100 }), showValue && (size === "small" || size === "large") ? (jsxRuntime.jsx(Text, { className: cvaValueBarText({ size }), "data-testid": dataTestId ? `${dataTestId}-value` : undefined, children: jsxRuntime.jsx("span", { style: valueColor ? { color: valueColor } : undefined, children: valueText }) })) : null] }));
5163
+ return (jsxRuntime.jsxs("span", { className: valueBarContainerClassName, "data-testid": dataTestId, ref: ref, children: [jsxRuntime.jsx("progress", { "aria-label": valueText, className: cvaValueBar({ className, size }), max: 100, style: { color: barFillColor }, value: score * 100 }), showValue && (size === "small" || size === "large") ? (jsxRuntime.jsx(Text, { className: cvaValueBarText({ size }), "data-testid": dataTestId ? `${dataTestId}-value` : undefined, children: jsxRuntime.jsx("span", { style: valueColor ? { color: valueColor } : undefined, children: valueText }) })) : null] }));
4608
5164
  };
4609
5165
 
4610
5166
  const cvaKPICard = cssClassVarianceUtilities.cvaMerge([
@@ -4705,13 +5261,29 @@ const KPICard = ({ isActive = false, onClick, className, "data-testid": dataTest
4705
5261
  };
4706
5262
 
4707
5263
  /**
4708
- * Display a single placeholder block for shape-based elements before data gets loaded to reduce load-time frustration.
5264
+ * SkeletonBlock renders a single animated placeholder block for shape-based elements (images, icons, buttons, avatars)
5265
+ * before data is loaded. It uses exact height and width values to match the element it replaces.
4709
5266
  *
4710
- * Fills the full height for images, badges, buttons, avatars, and other shape-based elements.
4711
- * Uses numbers or CSS length values for height.
5267
+ * ### When to use
5268
+ * Use SkeletonBlock for loading placeholders of shape-based UI elements: images, icons, badges, buttons, avatars, thumbnails.
5269
+ *
5270
+ * ### When not to use
5271
+ * For text content, use `SkeletonLabel` which accounts for text line-height margins.
5272
+ * For multiple text lines, use `SkeletonLines`.
5273
+ *
5274
+ * @example Skeleton block for an avatar and button
5275
+ * ```tsx
5276
+ * import { SkeletonBlock } from "@trackunit/react-components";
4712
5277
  *
4713
- * For text content, use SkeletonLabel component instead.
4714
- * For multiple text lines, use SkeletonLines component instead.
5278
+ * const AvatarSkeleton = () => (
5279
+ * <div className="flex items-center gap-3">
5280
+ * <SkeletonBlock height={40} width={40} className="rounded-full" />
5281
+ * <SkeletonBlock height={32} width={120} className="rounded-md" />
5282
+ * </div>
5283
+ * );
5284
+ * ```
5285
+ * @param {SkeletonBlockProps} props - The props for the SkeletonBlock component
5286
+ * @returns {ReactElement} SkeletonBlock component
4715
5287
  */
4716
5288
  const SkeletonBlock = react.memo((props) => {
4717
5289
  const { width = "100%", height = 16, flexibleWidth = false, className, "data-testid": dataTestId, children, ref, } = props;
@@ -4726,8 +5298,29 @@ const SkeletonBlock = react.memo((props) => {
4726
5298
  SkeletonBlock.displayName = "SkeletonBlock";
4727
5299
 
4728
5300
  /**
4729
- * Skeleton loading indicator that mimics the KPICard component structure.
4730
- * Uses the same layout, spacing, and visual hierarchy as KPICard.
5301
+ * KPICardSkeleton is a loading placeholder that mimics the layout of a KPICard.
5302
+ * It renders skeleton lines for the KPI title/value, and optional icon, trends, value bar, and notice slots.
5303
+ *
5304
+ * ### When to use
5305
+ * Use KPICardSkeleton while `KPICard` data is loading to maintain layout stability in dashboards and metric displays.
5306
+ *
5307
+ * ### When not to use
5308
+ * Do not use KPICardSkeleton for generic card loading — use a `Card` with `SkeletonLabel` inside.
5309
+ *
5310
+ * @example KPICard skeletons in a dashboard row
5311
+ * ```tsx
5312
+ * import { KPICardSkeleton } from "@trackunit/react-components";
5313
+ *
5314
+ * const LoadingMetrics = () => (
5315
+ * <div className="grid grid-cols-3 gap-4">
5316
+ * <KPICardSkeleton hasIcon hasTrends />
5317
+ * <KPICardSkeleton hasIcon hasValueBar />
5318
+ * <KPICardSkeleton hasNotice />
5319
+ * </div>
5320
+ * );
5321
+ * ```
5322
+ * @param {KPICardSkeletonProps} props - The props for the KPICardSkeleton component
5323
+ * @returns {ReactElement} KPICardSkeleton component
4731
5324
  */
4732
5325
  const KPICardSkeleton = ({ hasIcon = false, hasTrends = false, hasValueBar = false, hasNotice = false, children, className, "data-testid": dataTestId, style, ref, ...rest }) => {
4733
5326
  return (jsxRuntime.jsx(Card, { className: cvaKPICard({ className }), "data-testid": dataTestId, ref: ref, style: style, ...rest, children: jsxRuntime.jsxs(CardBody, { className: cvaKPICardBody(), gap: "none", padding: "none", children: [jsxRuntime.jsxs("div", { className: cvaKPICardHeader(), children: [jsxRuntime.jsx(KPISkeleton, { className: "p-0", "data-testid": dataTestId ? `${dataTestId}-kpi` : undefined }), hasIcon ? (jsxRuntime.jsx(SkeletonBlock, { "data-testid": dataTestId ? `${dataTestId}-icon-loading` : undefined, height: 28, width: 28 })) : null] }), hasTrends ? (jsxRuntime.jsx(SkeletonLabel, { "data-testid": dataTestId ? `${dataTestId}-trend-indicator-loading` : undefined, textSize: "text-xs", width: "100%" })) : null, hasValueBar ? (jsxRuntime.jsx(SkeletonLabel, { "data-testid": dataTestId ? `${dataTestId}-value-bar-loading` : undefined, textSize: "text-xs", width: "100%" })) : null, hasNotice ? (jsxRuntime.jsx(SkeletonLabel, { "data-testid": dataTestId ? `${dataTestId}-notice-loading` : undefined, textSize: "text-xs", width: "100%" })) : null, children] }) }));
@@ -4807,8 +5400,30 @@ const DEFAULT_SKELETON_LIST_ITEM_PROPS = {
4807
5400
  hasDetails: false,
4808
5401
  };
4809
5402
  /**
4810
- * Skeleton loading indicator that mimics the ListItem component structure.
4811
- * Uses the same layout, spacing, and visual hierarchy as ListItem.
5403
+ * ListItemSkeleton is a loading placeholder that mimics the layout of a ListItem.
5404
+ * It renders skeleton lines for the title, description, meta, thumbnail, and details slots.
5405
+ * Use it inside a List to indicate that list data is loading.
5406
+ *
5407
+ * ### When to use
5408
+ * Use ListItemSkeleton as the loading state inside a `List` when data is being fetched. Configure it to match the shape of your actual ListItems.
5409
+ *
5410
+ * ### When not to use
5411
+ * Do not use ListItemSkeleton for non-list loading states. Use `SkeletonBlock` or `SkeletonLabel` for generic loading placeholders.
5412
+ *
5413
+ * @example ListItemSkeleton matching a typical asset list item
5414
+ * ```tsx
5415
+ * import { ListItemSkeleton } from "@trackunit/react-components";
5416
+ *
5417
+ * const LoadingList = () => (
5418
+ * <div>
5419
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5420
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5421
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5422
+ * </div>
5423
+ * );
5424
+ * ```
5425
+ * @param {ListItemSkeletonProps} props - The props for the ListItemSkeleton component
5426
+ * @returns {ReactElement} ListItemSkeleton component
4812
5427
  */
4813
5428
  const ListItemSkeleton = ({ hasThumbnail = DEFAULT_SKELETON_LIST_ITEM_PROPS.hasThumbnail, thumbnailShape = "circle", hasDescription = DEFAULT_SKELETON_LIST_ITEM_PROPS.hasDescription, hasMeta = DEFAULT_SKELETON_LIST_ITEM_PROPS.hasMeta, hasDetails = DEFAULT_SKELETON_LIST_ITEM_PROPS.hasDetails, }) => {
4814
5429
  // Generate stable random widths once and never change them
@@ -5294,10 +5909,32 @@ const getResolvedLoadingIndicator = (loadingIndicator) => {
5294
5909
  };
5295
5910
 
5296
5911
  /**
5297
- * The ListItem is designed to present a concise set of items for quick scanning and navigation. It supports multiple content types and actions, and its flexible layout allows for customization based on the type of data being shown - assets, events, users, etc.
5912
+ * ListItem presents a concise row of information for quick scanning and navigation. It supports a title, description, meta text, thumbnail,
5913
+ * and a details slot. When `onClick` is provided, the item becomes interactive with a chevron indicator.
5298
5914
  *
5299
- * @param { ListItemProps} props - The props for the ListItem component
5300
- * @returns {Element} ListItem component
5915
+ * ### When to use
5916
+ * Use ListItem inside a `List` to display items such as assets, events, users, or notifications with consistent layout.
5917
+ *
5918
+ * ### When not to use
5919
+ * Do not use ListItem outside of a `List` component for standalone clickable elements — use `Card` or `Button`.
5920
+ *
5921
+ * @example ListItem with thumbnail and details
5922
+ * ```tsx
5923
+ * import { ListItem, Icon, Tag } from "@trackunit/react-components";
5924
+ *
5925
+ * const AssetListItem = () => (
5926
+ * <ListItem
5927
+ * title="Excavator CAT 320"
5928
+ * description="Serial: SN-2024-00142"
5929
+ * meta="Last seen: 2 hours ago"
5930
+ * thumbnail={<Icon name="Truck" size="small" />}
5931
+ * details={<Tag color="success" size="small">Active</Tag>}
5932
+ * onClick={() => console.log("Navigate to asset")}
5933
+ * />
5934
+ * );
5935
+ * ```
5936
+ * @param {ListItemProps} props - The props for the ListItem component
5937
+ * @returns {ReactElement} ListItem component
5301
5938
  */
5302
5939
  const ListItem = ({ className, "data-testid": dataTestId, onClick, details, title, description, meta, thumbnail, thumbnailColor = "info-600", thumbnailBackground = "info-100", ...rest }) => {
5303
5940
  const baseClass = cvaListItem({ className });
@@ -5401,7 +6038,28 @@ const cvaMenuListMultiSelect = cssClassVarianceUtilities.cvaMerge([
5401
6038
  const cvaMenuListItem = cssClassVarianceUtilities.cvaMerge("max-w-full");
5402
6039
 
5403
6040
  /**
5404
- * The MenuDivider component is used to separate items in a menu list.
6041
+ * MenuDivider renders a horizontal line to visually separate groups of items within a MenuList.
6042
+ *
6043
+ * ### When to use
6044
+ * Use MenuDivider between groups of related `MenuItem` elements to create logical sections within a menu.
6045
+ *
6046
+ * ### When not to use
6047
+ * Do not use MenuDivider outside of a `MenuList`. For general-purpose dividers, use `Spacer` with `border`.
6048
+ *
6049
+ * @example Menu with grouped sections
6050
+ * ```tsx
6051
+ * import { MenuList, MenuItem, MenuDivider, Icon } from "@trackunit/react-components";
6052
+ *
6053
+ * const GroupedMenu = () => (
6054
+ * <MenuList>
6055
+ * <MenuItem id="edit" label="Edit" prefix={<Icon name="PencilSquare" size="small" />} />
6056
+ * <MenuItem id="duplicate" label="Duplicate" prefix={<Icon name="DocumentDuplicate" size="small" />} />
6057
+ * <MenuDivider />
6058
+ * <MenuItem id="delete" label="Delete" variant="danger" prefix={<Icon name="Trash" size="small" />} />
6059
+ * </MenuList>
6060
+ * );
6061
+ * ```
6062
+ * @returns {ReactElement} MenuDivider component
5405
6063
  */
5406
6064
  const MenuDivider = () => {
5407
6065
  return jsxRuntime.jsx("div", { className: cvaMenuListDivider(), "data-testid": "menu-divider" });
@@ -5527,8 +6185,37 @@ const cvaMenuItemSuffix = cssClassVarianceUtilities.cvaMerge(["text-neutral-400"
5527
6185
  });
5528
6186
 
5529
6187
  /**
5530
- * The MenuItem component is used to display a menu, primarily meant to be used in a list form.
6188
+ * MenuItem represents a single actionable item within a MenuList.
6189
+ * It supports labels, icons (prefix/suffix), selected and focused states, and danger variants.
6190
+ *
6191
+ * ### When to use
6192
+ * Use MenuItem inside a `MenuList` for individual actions (edit, delete, duplicate) or selectable options.
6193
+ *
6194
+ * ### When not to use
6195
+ * Do not use MenuItem outside of a `MenuList` context. For standalone clickable items, use `Button` or `ListItem`.
5531
6196
  *
6197
+ * @example MenuItem with icon prefix
6198
+ * ```tsx
6199
+ * import { MenuList, MenuItem, Icon } from "@trackunit/react-components";
6200
+ *
6201
+ * const ActionMenu = () => (
6202
+ * <MenuList>
6203
+ * <MenuItem
6204
+ * id="edit"
6205
+ * label="Edit asset"
6206
+ * prefix={<Icon name="PencilSquare" size="small" />}
6207
+ * onClick={() => console.log("Edit clicked")}
6208
+ * />
6209
+ * <MenuItem
6210
+ * id="delete"
6211
+ * label="Delete asset"
6212
+ * prefix={<Icon name="Trash" size="small" />}
6213
+ * variant="danger"
6214
+ * onClick={() => console.log("Delete clicked")}
6215
+ * />
6216
+ * </MenuList>
6217
+ * );
6218
+ * ```
5532
6219
  * @param {MenuItemProps} props - The props for the MenuItem component
5533
6220
  * @returns {ReactElement} MenuItem component
5534
6221
  */
@@ -5658,9 +6345,45 @@ const MenuList = ({ "data-testid": dataTestId, className, children, isMulti = fa
5658
6345
  const cvaMoreMenu = cssClassVarianceUtilities.cvaMerge(["p-0"]);
5659
6346
 
5660
6347
  /**
5661
- * A kebab menu component.
5662
- * Advice: fill it with MenuList
6348
+ * MoreMenu (kebab menu) renders a three-dot button that opens a popover with a list of actions.
6349
+ * It is typically filled with a MenuList containing MenuItem elements.
6350
+ *
6351
+ * ### When to use
6352
+ * Use MoreMenu when you have overflow actions that don't fit in the main UI. Common for row-level actions in tables, card headers, or list items.
6353
+ *
6354
+ * ### When not to use
6355
+ * Do not use MoreMenu for primary actions that should always be visible. Use `Button` instead.
5663
6356
  *
6357
+ * @example Action items with render prop — Pass a function as `children` to receive the `close` callback and dismiss the menu after an action.
6358
+ * ```tsx
6359
+ * import { MoreMenu, MenuList, MenuItem, Icon } from "@trackunit/react-components";
6360
+ *
6361
+ * const AssetActions = () => (
6362
+ * <MoreMenu>
6363
+ * {(close) => (
6364
+ * <MenuList onClick={close}>
6365
+ * <MenuItem id="edit" label="Edit" prefix={<Icon name="PencilSquare" size="small" />} />
6366
+ * <MenuItem id="delete" label="Delete" variant="danger" prefix={<Icon name="Trash" size="small" />} />
6367
+ * </MenuList>
6368
+ * )}
6369
+ * </MoreMenu>
6370
+ * );
6371
+ * ```
6372
+ * @example Custom trigger button — Use `customButton` to replace the default kebab icon with any element, like a labeled Button.
6373
+ * ```tsx
6374
+ * import { MoreMenu, MenuList, MenuItem, Button } from "@trackunit/react-components";
6375
+ *
6376
+ * const CustomTriggerMenu = () => (
6377
+ * <MoreMenu customButton={<Button variant="secondary" size="small">Actions</Button>}>
6378
+ * {(close) => (
6379
+ * <MenuList onClick={close}>
6380
+ * <MenuItem id="export" label="Export" />
6381
+ * <MenuItem id="archive" label="Archive" />
6382
+ * </MenuList>
6383
+ * )}
6384
+ * </MoreMenu>
6385
+ * );
6386
+ * ```
5664
6387
  * @param {MoreMenuProps} props - The props for the MoreMenu component
5665
6388
  * @returns {ReactElement} MoreMenu component
5666
6389
  */
@@ -5713,12 +6436,42 @@ const cvaNoticeIcon = cssClassVarianceUtilities.cvaMerge(["rounded-full", "items
5713
6436
  });
5714
6437
 
5715
6438
  /**
5716
- * Notices are non-interactive elements that communicate information that the user needs to see, without directly prompting an action button.
6439
+ * Notice is a non-interactive element that communicates informational messages the user should see, without prompting an action.
6440
+ * It displays an optional icon and text label, with optional tooltip support.
5717
6441
  *
5718
- * _**Do use** notices to communicate non-essential information that does not necessarily require action to be taken._
6442
+ * ### When to use
6443
+ * Use Notice to communicate non-essential, contextual information that does not require action (e.g., status notes, informational hints).
5719
6444
  *
5720
- * _**Do not use** notices for essential information (use `<Alert/>` instead), or to communicate information related to the state of an asset (use `<Indicator/>` instead)._
6445
+ * ### When not to use
6446
+ * Do not use Notice for essential information that requires user action — use `Alert` instead.
6447
+ * Do not use Notice for asset state indicators — use `Indicator` instead.
5721
6448
  *
6449
+ * @example Notice with icon and label
6450
+ * ```tsx
6451
+ * import { Notice } from "@trackunit/react-components";
6452
+ *
6453
+ * const InfoNotice = () => (
6454
+ * <Notice
6455
+ * iconName="InformationCircle"
6456
+ * label="Last synced 5 minutes ago"
6457
+ * color="info"
6458
+ * />
6459
+ * );
6460
+ * ```
6461
+ * @example Warning notice with tooltip
6462
+ * ```tsx
6463
+ * import { Notice } from "@trackunit/react-components";
6464
+ *
6465
+ * const WarningNotice = () => (
6466
+ * <Notice
6467
+ * iconName="ExclamationTriangle"
6468
+ * label="Low battery"
6469
+ * color="warning"
6470
+ * withTooltip
6471
+ * tooltipLabel="Battery level is below 20%"
6472
+ * />
6473
+ * );
6474
+ * ```
5722
6475
  * @param {NoticeProps} props - The props for the Notice component
5723
6476
  * @returns {ReactElement} Notice component
5724
6477
  */
@@ -5753,18 +6506,68 @@ const cvaPageContent = cssClassVarianceUtilities.cvaMerge(["overflow-auto", "pag
5753
6506
  });
5754
6507
 
5755
6508
  /**
5756
- * Renders the page component. Adds padding and layout to the page.
6509
+ * Page is the top-level layout container that applies consistent padding and layout to page content.
6510
+ * Use it in combination with PageContent and PageHeader.
6511
+ *
6512
+ * ### When to use
6513
+ * Use Page as the outermost wrapper for a page view. It provides the base layout structure (padding, spacing) for the page.
6514
+ *
6515
+ * ### When not to use
6516
+ * Do not use Page for card-level or section-level layout. Use `Card` or standard flex/grid containers instead.
6517
+ *
6518
+ * @example Page with header and content
6519
+ * ```tsx
6520
+ * import { Page, PageContent, PageHeader } from "@trackunit/react-components";
6521
+ *
6522
+ * const AssetListPage = () => (
6523
+ * <Page layout="default">
6524
+ * <PageHeader
6525
+ * title="Assets"
6526
+ * accessoryType="actions"
6527
+ * primaryAction={{ actionText: "Add Asset", actionCallback: () => {} }}
6528
+ * />
6529
+ * <PageContent layout="default">
6530
+ * <p>Asset list content goes here</p>
6531
+ * </PageContent>
6532
+ * </Page>
6533
+ * );
6534
+ * ```
6535
+ * @param {PageProps} props - The props for the Page component
6536
+ * @returns {ReactElement} Page component
5757
6537
  */
5758
6538
  const Page = ({ layout, className, children, "data-testid": dataTestId, ref }) => {
5759
6539
  return (jsxRuntime.jsx("div", { className: cvaPage({ className, layout }), "data-testid": dataTestId ? dataTestId : "page", ref: ref, children: children }));
5760
6540
  };
5761
6541
 
5762
6542
  /**
5763
- * Renders the content of a page.
5764
- * Applies padding to content. To be used within a <Page/>
6543
+ * PageContent is the main content area inside a Page.
6544
+ * It applies consistent padding to the content section. Must be used within a Page component.
6545
+ *
6546
+ * ### When to use
6547
+ * Use PageContent to wrap the main content of a page, below a `PageHeader`. It provides consistent padding and layout.
6548
+ *
6549
+ * ### When not to use
6550
+ * Do not use PageContent outside of a `Page`. For standalone content wrappers, use `Card` or `CardBody`.
5765
6551
  *
5766
- * @param {PageContentProps} props - The component props.
5767
- * @returns {ReactNode} - The rendered component.
6552
+ * @example PageContent inside a Page
6553
+ * ```tsx
6554
+ * import { Page, PageContent, PageHeader, Card, CardBody, Text } from "@trackunit/react-components";
6555
+ *
6556
+ * const DetailPage = () => (
6557
+ * <Page layout="default">
6558
+ * <PageHeader title="Asset Details" />
6559
+ * <PageContent layout="default">
6560
+ * <Card>
6561
+ * <CardBody>
6562
+ * <Text>Asset information goes here</Text>
6563
+ * </CardBody>
6564
+ * </Card>
6565
+ * </PageContent>
6566
+ * </Page>
6567
+ * );
6568
+ * ```
6569
+ * @param {PageContentProps} props - The props for the PageContent component
6570
+ * @returns {ReactElement} PageContent component
5768
6571
  */
5769
6572
  const PageContent = ({ className, children, "data-testid": dataTestId, layout, ref, }) => {
5770
6573
  return (jsxRuntime.jsx("div", { className: cvaPageContent({ className, layout }), "data-testid": dataTestId ? dataTestId : "page-content", ref: ref, children: children }));
@@ -5848,14 +6651,16 @@ cssClassVarianceUtilities.cvaMerge([
5848
6651
  ]);
5849
6652
 
5850
6653
  /**
5851
- * Display multiple placeholder lines before data gets loaded to reduce load-time frustration.
6654
+ * SkeletonLines renders multiple animated placeholder text lines before data loads.
6655
+ * It supports three modes: uniform (identical lines), custom (per-line config), and preset (common patterns like paragraphs or articles).
6656
+ * Built on top of SkeletonLabel for text-specific margins and sizing.
5852
6657
  *
5853
- * Supports three modes:
5854
- * - **Uniform mode** (default): Display identical lines using `count` prop
5855
- * - **Custom mode**: Display customized lines with per-line configuration using `variant="custom"` and `lines` prop
5856
- * - **Preset mode**: Display common patterns using `variant="preset"` and `preset` name
6658
+ * ### When to use
6659
+ * Use SkeletonLines for loading placeholders of multi-line text content: paragraphs, descriptions, articles, or any text block.
5857
6660
  *
5858
- * Built on top of the [SkeletonLabel](?path=/docs/components-loading-states-skeletonlabel--docs) component for text-specific margins and sizing.
6661
+ * ### When not to use
6662
+ * For single text lines, use `SkeletonLabel`.
6663
+ * For shape-based elements, use `SkeletonBlock`.
5859
6664
  *
5860
6665
  * @example
5861
6666
  * // Uniform lines (simple mode)
@@ -6064,11 +6869,15 @@ const PageHeaderTitle = ({ title, "data-testid": dataTestId, className, ref: for
6064
6869
  };
6065
6870
 
6066
6871
  /**
6067
- * The PageHeader component is used to display the header of a page.
6872
+ * PageHeader displays the header of a page, providing context about the current location within the application.
6873
+ * It supports a title, optional description tooltip, tag, action buttons, KPI metrics, and tabs for in-page navigation.
6068
6874
  *
6069
- * It provides critical context by indicating the current location within the application or website.
6070
- * PageHeader can be used to highlight the page topic, display helpful information about the page, and carry the action items related to the current page.
6071
- * Tabs can be added to the PageHeader to allow users to navigate between different sections of the page.
6875
+ * ### When to use
6876
+ * Use PageHeader at the top of a `Page` to display the page title, description, and primary/secondary actions.
6877
+ *
6878
+ * ### When not to use
6879
+ * Do not use PageHeader for section-level headings within a page. Use `SectionHeader` instead.
6880
+ * Do not use for card-level headers — use `CardHeader`.
6072
6881
  *
6073
6882
  * @example Page header with actions
6074
6883
  * ```tsx
@@ -6137,8 +6946,37 @@ const cvaPagination = cssClassVarianceUtilities.cvaMerge(["flex", "items-center"
6137
6946
  const cvaPaginationText = cssClassVarianceUtilities.cvaMerge("whitespace-nowrap");
6138
6947
 
6139
6948
  /**
6140
- * Pagination Description. It could be used when you need navigation for your paging feature.
6141
-
6949
+ * Pagination provides previous/next page navigation with an optional page counter and jump-to-page input.
6950
+ * It supports both offset-based pagination (with `pageIndex` and `pageCount`) and cursor-based pagination (with `cursorBase`).
6951
+ *
6952
+ * ### When to use
6953
+ * Use Pagination below a table or list when data is split across multiple pages and the user needs to navigate between them.
6954
+ *
6955
+ * ### When not to use
6956
+ * Do not use Pagination for infinite scroll patterns. Use the `useInfiniteScroll` hook instead.
6957
+ *
6958
+ * @example Basic offset-based pagination
6959
+ * ```tsx
6960
+ * import { Pagination } from "@trackunit/react-components";
6961
+ * import { useState } from "react";
6962
+ *
6963
+ * const PaginatedList = () => {
6964
+ * const [page, setPage] = useState(0);
6965
+ * const totalPages = 10;
6966
+ *
6967
+ * return (
6968
+ * <Pagination
6969
+ * pageIndex={page}
6970
+ * pageCount={totalPages}
6971
+ * canPreviousPage={page > 0}
6972
+ * canNextPage={page < totalPages - 1}
6973
+ * previousPage={() => setPage(p => p - 1)}
6974
+ * nextPage={() => setPage(p => p + 1)}
6975
+ * getTranslatedCount={(count) => `of ${count}`}
6976
+ * />
6977
+ * );
6978
+ * };
6979
+ * ```
6142
6980
  * @param {PaginationProps} props - The props for the Pagination component
6143
6981
  * @returns {ReactElement} Pagination component
6144
6982
  */
@@ -6194,10 +7032,29 @@ const Pagination = ({ previousPage, nextPage, canPreviousPage = false, canNextPa
6194
7032
 
6195
7033
  const STROKE_WIDTH_THRESHOLD = 32;
6196
7034
  /**
6197
- * Draws an svg Polygon from a set of points.
7035
+ * Polygon renders an SVG polygon from a set of coordinate points. Points are automatically normalized to fit within the specified size.
7036
+ * It supports fill/stroke color options and optional opacity for overlay effects.
7037
+ *
7038
+ * ### When to use
7039
+ * Use Polygon for rendering geofence boundaries, map overlays, or any custom shape defined by coordinate points.
7040
+ *
7041
+ * ### When not to use
7042
+ * Do not use Polygon for standard UI elements — use the design system components instead.
7043
+ *
7044
+ * @example Rendering a triangle
7045
+ * ```tsx
7046
+ * import { Polygon } from "@trackunit/react-components";
6198
7047
  *
6199
- * @param { PolygonProps} props - The props for the Polygon component
6200
- * @returns {ReactElement} Polygon component
7048
+ * const Triangle = () => (
7049
+ * <Polygon
7050
+ * points={[[0, 100], [50, 0], [100, 100]]}
7051
+ * size={64}
7052
+ * color="black"
7053
+ * />
7054
+ * );
7055
+ * ```
7056
+ * @param {PolygonProps} props - The props for the Polygon component
7057
+ * @returns {ReactElement} Polygon component
6201
7058
  */
6202
7059
  const Polygon = ({ points, size, color = "black", opaque = true, className, "data-testid": dataTestId, ref, }) => {
6203
7060
  // Calculate the bounds of the points
@@ -6227,8 +7084,39 @@ const Polygon = ({ points, size, color = "black", opaque = true, className, "dat
6227
7084
  const normalize = ({ value, min, max, size }) => ((value - min) / (max - min)) * size;
6228
7085
 
6229
7086
  /**
6230
- * The PopoverTitle component.
7087
+ * PopoverTitle renders a styled title bar at the top of a PopoverContent panel.
7088
+ * It displays uppercase bold text with an optional action element and divider.
7089
+ *
7090
+ * ### When to use
7091
+ * Use PopoverTitle inside `PopoverContent` when the popover needs a labeled header, optionally with an action (e.g., a close button).
6231
7092
  *
7093
+ * ### When not to use
7094
+ * Do not use PopoverTitle outside of a `Popover` context. For standalone headings, use `Heading`.
7095
+ *
7096
+ * @example Popover with titled content
7097
+ * ```tsx
7098
+ * import { Popover, PopoverTrigger, PopoverContent, PopoverTitle, Button, Text } from "@trackunit/react-components";
7099
+ *
7100
+ * const TitledPopover = () => (
7101
+ * <Popover placement="bottom-start">
7102
+ * <PopoverTrigger>
7103
+ * <Button variant="secondary">Details</Button>
7104
+ * </PopoverTrigger>
7105
+ * <PopoverContent>
7106
+ * {(close) => (
7107
+ * <div className="w-64">
7108
+ * <PopoverTitle divider action={<Button variant="ghost" size="small" onClick={close}>Close</Button>}>
7109
+ * Asset Info
7110
+ * </PopoverTitle>
7111
+ * <div className="p-3">
7112
+ * <Text size="small">Additional information about this asset.</Text>
7113
+ * </div>
7114
+ * </div>
7115
+ * )}
7116
+ * </PopoverContent>
7117
+ * </Popover>
7118
+ * );
7119
+ * ```
6232
7120
  * @param {PopoverTitleProps} props - The props for the PopoverTitle component
6233
7121
  * @returns {ReactElement} PopoverTitle component
6234
7122
  */
@@ -6371,9 +7259,31 @@ const preferenceCardGrid = createGrid()
6371
7259
  })
6372
7260
  .build();
6373
7261
  /**
6374
- * PreferenceCard is a flexible component for displaying add-ons or settings configuration options
6375
- * with various states and visual treatments.
6376
- * It is recommended to be primarily used as an input component, as it supports checkboxes, radio buttons and toggles.
7262
+ * PreferenceCard is a flexible component for displaying add-on options or settings with an optional input control (checkbox, radio, toggle).
7263
+ * It supports icons/images, titles with tags, descriptions, and custom child content for advanced layouts.
7264
+ *
7265
+ * ### When to use
7266
+ * Use PreferenceCard for settings pages, feature toggles, or plan selection where each option needs a title, description, and an input control.
7267
+ *
7268
+ * ### When not to use
7269
+ * Do not use PreferenceCard for data display — use `Card`.
7270
+ * Do not use for simple toggle settings — use a standalone toggle switch.
7271
+ *
7272
+ * @example PreferenceCard with checkbox input
7273
+ * ```tsx
7274
+ * import { PreferenceCard } from "@trackunit/react-components";
7275
+ *
7276
+ * const FeatureToggle = () => (
7277
+ * <PreferenceCard
7278
+ * title="Email Notifications"
7279
+ * description="Receive email alerts for asset status changes"
7280
+ * icon={{ type: "icon", name: "EnvelopeOpen", containerClassName: "bg-primary-100" }}
7281
+ * input={<input type="checkbox" />}
7282
+ * />
7283
+ * );
7284
+ * ```
7285
+ * @param {PreferenceCardProps} props - The props for the PreferenceCard component
7286
+ * @returns {ReactNode} PreferenceCard component
6377
7287
  */
6378
7288
  const PreferenceCard = ({ title, description, icon, input, titleTag, cardTag, disabled = false, className, "data-testid": dataTestId, children, ref: forwardedRef, }) => {
6379
7289
  const { ref: measureRef, geometry } = useMeasure();
@@ -6423,8 +7333,29 @@ const getRandomWidth = (min, max) => {
6423
7333
  return Math.floor(Math.random() * (max - min + 1)) + min;
6424
7334
  };
6425
7335
  /**
6426
- * Skeleton loading indicator that mimics the PreferenceCard component structure.
6427
- * Uses the same grid layout, spacing, and visual hierarchy as PreferenceCard.
7336
+ * PreferenceCardSkeleton is a loading placeholder that mimics the layout of a PreferenceCard.
7337
+ * It renders skeleton lines for the title, description, and optional slots (icon, tags, input).
7338
+ * Configure the boolean flags to match the shape of your actual PreferenceCards.
7339
+ *
7340
+ * ### When to use
7341
+ * Use PreferenceCardSkeleton while preference/settings data is loading to maintain layout stability and reduce perceived load time.
7342
+ *
7343
+ * ### When not to use
7344
+ * Do not use PreferenceCardSkeleton for generic loading — use `SkeletonBlock` or `SkeletonLabel`.
7345
+ *
7346
+ * @example PreferenceCard skeleton with icon and input
7347
+ * ```tsx
7348
+ * import { PreferenceCardSkeleton } from "@trackunit/react-components";
7349
+ *
7350
+ * const LoadingSettings = () => (
7351
+ * <div className="flex flex-col gap-3">
7352
+ * <PreferenceCardSkeleton hasIcon hasInput />
7353
+ * <PreferenceCardSkeleton hasIcon hasInput />
7354
+ * </div>
7355
+ * );
7356
+ * ```
7357
+ * @param {PreferenceCardSkeletonProps} props - The props for the PreferenceCardSkeleton component
7358
+ * @returns {ReactElement} PreferenceCardSkeleton component
6428
7359
  */
6429
7360
  const PreferenceCardSkeleton = ({ hasIcon = DEFAULT_SKELETON_PREFERENCE_CARD_PROPS.hasIcon, hasTitleTag = DEFAULT_SKELETON_PREFERENCE_CARD_PROPS.hasTitleTag, hasCardTag = DEFAULT_SKELETON_PREFERENCE_CARD_PROPS.hasCardTag, hasInput = DEFAULT_SKELETON_PREFERENCE_CARD_PROPS.hasInput, ref, }) => {
6430
7361
  const gridAreas = useGridAreas(preferenceCardGrid);
@@ -6451,11 +7382,27 @@ function useConfirmExit(confirmExit, when = true) {
6451
7382
  reactRouter.useBlocker(confirmExit, when);
6452
7383
  }
6453
7384
  /**
6454
- * The usePrompt hook.
6455
-
6456
- * @param {string} message -
6457
- * @param {boolean} when -
6458
- * @returns {void} void
7385
+ * usePrompt displays a browser confirmation dialog when the user tries to navigate away from the current page.
7386
+ * It blocks both in-app navigation (via TanStack Router's `useBlocker`) and browser-level navigation (via `beforeunload`).
7387
+ *
7388
+ * ### When to use
7389
+ * Use usePrompt when the user has unsaved changes (e.g., in a form) and should be warned before navigating away.
7390
+ *
7391
+ * ### When not to use
7392
+ * Do not use usePrompt for non-destructive navigation. Only use when there is genuinely unsaved state that would be lost.
7393
+ *
7394
+ * @example Warn user about unsaved form changes
7395
+ * ```tsx
7396
+ * import { usePrompt } from "@trackunit/react-components";
7397
+ *
7398
+ * const EditForm = ({ isDirty }: { isDirty: boolean }) => {
7399
+ * usePrompt("You have unsaved changes. Are you sure you want to leave?", isDirty);
7400
+ * return <form>...</form>;
7401
+ * };
7402
+ * ```
7403
+ * @param {string} message - The confirmation message shown to the user
7404
+ * @param {boolean} when - Whether the prompt should be active. Defaults to true.
7405
+ * @returns {void}
6459
7406
  */
6460
7407
  const usePrompt = (message, when = true) => {
6461
7408
  react.useEffect(() => {
@@ -6478,10 +7425,28 @@ const usePrompt = (message, when = true) => {
6478
7425
  useConfirmExit(confirmExit, when);
6479
7426
  };
6480
7427
  /**
6481
- * The Prompt function.
7428
+ * Prompt is a declarative component wrapper around the `usePrompt` hook. It displays a browser confirmation dialog
7429
+ * when the user tries to navigate away while `when` is true.
6482
7430
  *
6483
- * @param {PromptProps} Props -
6484
- * @returns {void} void
7431
+ * ### When to use
7432
+ * Use Prompt when you prefer a declarative approach to navigation blocking (instead of the `usePrompt` hook).
7433
+ *
7434
+ * ### When not to use
7435
+ * Do not use Prompt when `when` is always false — simply omit it.
7436
+ *
7437
+ * @example Declarative prompt for unsaved changes
7438
+ * ```tsx
7439
+ * import { Prompt } from "@trackunit/react-components";
7440
+ *
7441
+ * const EditPage = ({ hasUnsavedChanges }: { hasUnsavedChanges: boolean }) => (
7442
+ * <>
7443
+ * <Prompt when={hasUnsavedChanges} message="Discard unsaved changes?" />
7444
+ * <form>...</form>
7445
+ * </>
7446
+ * );
7447
+ * ```
7448
+ * @param {PromptProps} props - The props for the Prompt component
7449
+ * @returns {null} Renders nothing; only activates the navigation prompt
6485
7450
  */
6486
7451
  const Prompt = ({ when, message }) => {
6487
7452
  usePrompt(message, when);
@@ -6507,18 +7472,25 @@ const cvaSpacer = cssClassVarianceUtilities.cvaMerge([], {
6507
7472
  });
6508
7473
 
6509
7474
  /**
6510
- * The Spacer component is used for adding a bit of space in the ui.
7475
+ * Spacer adds vertical whitespace between elements. It can optionally render a visible border line as a divider.
7476
+ *
7477
+ * ### When to use
7478
+ * Use Spacer to add consistent vertical gaps between sections or to render a horizontal divider line.
6511
7479
  *
6512
- * @example basic usage
7480
+ * ### When not to use
7481
+ * Do not use Spacer for horizontal gaps — use Tailwind flex/grid gap utilities. Do not use for structural layout — use CSS grid or flex.
7482
+ *
7483
+ * @example Spacer as a divider
6513
7484
  * ```tsx
6514
- * import { Spacer } from "@trackunit/react-components";
6515
- * const MySpacer = () => {
6516
- * return (
6517
- * <div>
6518
- * <Spacer size="small" border data-testid="my-spacer-testid" />
6519
- * </div>
6520
- * );
6521
- * };
7485
+ * import { Spacer, Text } from "@trackunit/react-components";
7486
+ *
7487
+ * const DividedSections = () => (
7488
+ * <div>
7489
+ * <Text>Section 1 content</Text>
7490
+ * <Spacer size="medium" border />
7491
+ * <Text>Section 2 content</Text>
7492
+ * </div>
7493
+ * );
6522
7494
  * ```
6523
7495
  * @param {SpacerProps} props - The props for the Spacer component
6524
7496
  * @returns {ReactElement} Spacer component
@@ -6528,9 +7500,29 @@ const Spacer = ({ size = "medium", border = false, "data-testid": dataTestId, cl
6528
7500
  };
6529
7501
 
6530
7502
  /**
6531
- * The SectionHeader component is used on sections to set the section title.
6532
-
6533
- * @param {SectionHeaderProps} props - The props for the section header component
7503
+ * SectionHeader renders a section title with an optional subtitle and addon elements (e.g., action buttons, status indicators).
7504
+ * It also sets the document title via React Helmet for SEO and browser tab labeling.
7505
+ *
7506
+ * ### When to use
7507
+ * Use SectionHeader to label a distinct section within a page, below a `PageHeader`. It provides consistent heading styles and an optional subtitle.
7508
+ *
7509
+ * ### When not to use
7510
+ * Do not use SectionHeader for the main page title — use `PageHeader`.
7511
+ * Do not use for card-level headers — use `CardHeader`.
7512
+ *
7513
+ * @example Section header with subtitle and addon
7514
+ * ```tsx
7515
+ * import { SectionHeader, Button } from "@trackunit/react-components";
7516
+ *
7517
+ * const AssetSection = () => (
7518
+ * <SectionHeader
7519
+ * title="Maintenance Schedule"
7520
+ * subtitle="Upcoming and past maintenance events"
7521
+ * addons={<Button variant="secondary" size="small">Add Event</Button>}
7522
+ * />
7523
+ * );
7524
+ * ```
7525
+ * @param {SectionHeaderProps} props - The props for the SectionHeader component
6534
7526
  * @returns {ReactElement} SectionHeader component
6535
7527
  */
6536
7528
  const SectionHeader = ({ title, subtitle, "data-testid": dataTestId, addons, ref, }) => {
@@ -6606,12 +7598,19 @@ const useOverflowItems = ({ threshold = 1, childUniqueIdentifierAttribute = "id"
6606
7598
  };
6607
7599
 
6608
7600
  /**
6609
- * The sidebar components is used to render a responsive sidebar.
6610
- * - The sidebar will be rendered horizontally until a given breakpoint where it will be stacked vertically.
6611
- * - The sidebar hides items that does not fit in the sidebar and show them in a more menu.
6612
- * - **_The sidebar is just a wrapper. You are responsible for styling the children._**
7601
+ * Sidebar renders a responsive horizontal/vertical navigation bar that automatically collapses overflowing items into a MoreMenu.
7602
+ * It is rendered horizontally until a given breakpoint, then stacks vertically.
7603
+ *
7604
+ * **Important:** The Sidebar is just a layout wrapper. You are responsible for styling the children.
7605
+ * For the overflow functionality, use `min-w-[*]` or `flex-shrink-0` on child elements.
7606
+ *
7607
+ * When testing, add `setupIntersectionObserver();` to your `jest.setup.ts` file.
7608
+ *
7609
+ * ### When to use
7610
+ * Use Sidebar for secondary in-page navigation (e.g., switching between views within a page). Works well with `Tabs` for page-level navigation.
6613
7611
  *
6614
- * When using this component make sure to add `setupIntersectionObserver();` to your jest.setup.ts file.
7612
+ * ### When not to use
7613
+ * Do not use Sidebar for primary app navigation (the main menu). For top-level navigation, use the app shell navigation.
6615
7614
  *
6616
7615
  * @example Responsive sidebar with navigation items
6617
7616
  * ```tsx
@@ -6717,8 +7716,35 @@ const cvaTab = cssClassVarianceUtilities.cvaMerge([
6717
7716
  });
6718
7717
 
6719
7718
  /**
6720
- * Wrapper for radix tab component.
6721
- * We add a custom implementation of the asChild prop to make it easy to make the child element look like other tabs.
7719
+ * Tab is an individual tab trigger within a TabList.
7720
+ * Each Tab requires a unique `value` prop that corresponds to a TabContent with the same value.
7721
+ * Supports optional icons, suffixes (e.g., badges), and rendering as a custom child element via `asChild`.
7722
+ *
7723
+ * ### When to use
7724
+ * Use Tab inside a `TabList` to create clickable tab triggers. Each Tab maps to a `TabContent` panel.
7725
+ *
7726
+ * ### When not to use
7727
+ * Do not use Tab outside of a `TabList`/`Tabs` context. For standalone buttons, use `Button`.
7728
+ *
7729
+ * @example Tab with icon and badge suffix
7730
+ * ```tsx
7731
+ * import { Tabs, TabList, Tab, TabContent, Badge } from "@trackunit/react-components";
7732
+ *
7733
+ * const TabsWithBadge = () => (
7734
+ * <Tabs defaultValue="alerts">
7735
+ * <TabList>
7736
+ * <Tab value="alerts" iconName="Bell" suffix={<Badge count={3} color="danger" />}>
7737
+ * Alerts
7738
+ * </Tab>
7739
+ * <Tab value="history" iconName="Clock">History</Tab>
7740
+ * </TabList>
7741
+ * <TabContent value="alerts">Active alerts</TabContent>
7742
+ * <TabContent value="history">Event history</TabContent>
7743
+ * </Tabs>
7744
+ * );
7745
+ * ```
7746
+ * @param {TabProps} props - The props for the Tab component
7747
+ * @returns {ReactElement} Tab component
6722
7748
  */
6723
7749
  const Tab = ({ value, isFullWidth = false, iconName = undefined, "data-testid": dataTestId, className, children, suffix, asChild = false, appendTabStylesToChildIfAsChild = true, ref, ...rest }) => {
6724
7750
  const renderContent = () => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [iconName !== undefined ? jsxRuntime.jsx(Icon, { name: iconName, size: "small" }) : null, react.isValidElement(children) ? children.props.children : children, suffix] }));
@@ -6733,14 +7759,72 @@ const Tab = ({ value, isFullWidth = false, iconName = undefined, "data-testid":
6733
7759
  };
6734
7760
 
6735
7761
  /**
6736
- * Wrapper for radix tab content component.
7762
+ * TabContent is the content panel displayed when its corresponding Tab is active.
7763
+ * Each TabContent must have a `value` prop that matches the `value` of its corresponding Tab trigger.
7764
+ * TabContent is only rendered when its tab is selected (unless `forceMount` is set).
7765
+ *
7766
+ * ### When to use
7767
+ * Use TabContent inside a `Tabs` component, one for each `Tab` trigger.
7768
+ *
7769
+ * ### When not to use
7770
+ * Do not use TabContent outside of a `Tabs` context. For conditionally shown content, use standard conditional rendering.
7771
+ *
7772
+ * @example Tabs with styled content panels
7773
+ * ```tsx
7774
+ * import { Tabs, TabList, Tab, TabContent, Text } from "@trackunit/react-components";
7775
+ *
7776
+ * const AssetTabs = () => (
7777
+ * <Tabs defaultValue="overview">
7778
+ * <TabList>
7779
+ * <Tab value="overview">Overview</Tab>
7780
+ * <Tab value="maintenance">Maintenance</Tab>
7781
+ * </TabList>
7782
+ * <TabContent value="overview">
7783
+ * <Text>Asset overview information</Text>
7784
+ * </TabContent>
7785
+ * <TabContent value="maintenance">
7786
+ * <Text>Maintenance schedule and history</Text>
7787
+ * </TabContent>
7788
+ * </Tabs>
7789
+ * );
7790
+ * ```
7791
+ * @param {TabContentProps} props - The props for the TabContent component
7792
+ * @returns {ReactElement} TabContent component
6737
7793
  */
6738
7794
  const TabContent = ({ className, "data-testid": dataTestId, children, ref, ...rest }) => {
6739
7795
  return (jsxRuntime.jsx(reactTabs.Content, { className: cvaTabContent({ className }), "data-testid": dataTestId ? `${dataTestId}-content` : undefined, ref: ref, ...rest, children: children }));
6740
7796
  };
6741
7797
 
6742
7798
  /**
6743
- * Wrapper for radix tab list component.
7799
+ * TabList is the container for Tab triggers inside a Tabs component.
7800
+ * It renders a horizontal row of tab triggers and handles horizontal scroll behavior when tabs overflow.
7801
+ * By default, it auto-scrolls the active tab into view.
7802
+ *
7803
+ * ### When to use
7804
+ * Use TabList as a direct child of `Tabs` to wrap the `Tab` triggers. It handles layout and scrolling.
7805
+ *
7806
+ * ### When not to use
7807
+ * Do not use TabList outside of a `Tabs` context. For horizontal navigation lists, use a standard nav element.
7808
+ *
7809
+ * @example TabList with auto-scroll disabled
7810
+ * ```tsx
7811
+ * import { Tabs, TabList, Tab, TabContent } from "@trackunit/react-components";
7812
+ *
7813
+ * const StaticTabs = () => (
7814
+ * <Tabs defaultValue="first">
7815
+ * <TabList autoScrollToActive={false}>
7816
+ * <Tab value="first">First</Tab>
7817
+ * <Tab value="second">Second</Tab>
7818
+ * <Tab value="third">Third</Tab>
7819
+ * </TabList>
7820
+ * <TabContent value="first">First panel</TabContent>
7821
+ * <TabContent value="second">Second panel</TabContent>
7822
+ * <TabContent value="third">Third panel</TabContent>
7823
+ * </Tabs>
7824
+ * );
7825
+ * ```
7826
+ * @param {TabListProps} props - The props for the TabList component
7827
+ * @returns {ReactElement} TabList component
6744
7828
  */
6745
7829
  const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToActive = true, ref, ...rest }) => {
6746
7830
  const listRef = react.useRef(null);
@@ -6787,7 +7871,18 @@ const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToA
6787
7871
  };
6788
7872
 
6789
7873
  /**
6790
- * Tabs are used to group different but related content, allowing users to navigate views without leaving the page. They always contain at least two items and one tab is active at a time. Tabs can be used on full page layouts or in components such as modals or tables.
7874
+ * Tabs group different but related content, allowing users to navigate views without leaving the page.
7875
+ * They always contain at least two items and one tab is active at a time.
7876
+ * Tabs can be used on full page layouts or in components such as modals or tables.
7877
+ *
7878
+ * Compose Tabs with TabList, Tab, and TabContent.
7879
+ *
7880
+ * ### When to use
7881
+ * Use tabs to switch between related content sections within the same context (e.g., different views of an asset, or settings categories).
7882
+ *
7883
+ * ### When not to use
7884
+ * Do not use tabs for primary navigation between unrelated pages. Use `Sidebar` or route-based navigation instead.
7885
+ * Avoid tabs when there is only one content panel — just show the content directly.
6791
7886
  *
6792
7887
  * @example Basic tabs with content panels
6793
7888
  * ```tsx
@@ -6821,6 +7916,8 @@ const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToA
6821
7916
  * </Tabs>
6822
7917
  * );
6823
7918
  * ```
7919
+ * @param {TabsProps} props - The props for the Tabs component
7920
+ * @returns {ReactElement} Tabs component
6824
7921
  */
6825
7922
  const Tabs = ({ children, forceRender, className, "data-testid": dataTestId, fullWidth, ref, ...rest }) => {
6826
7923
  return (jsxRuntime.jsx(reactTabs.Root, { className: cvaTabsRoot({ className }), "data-testid": dataTestId, ref: ref, ...rest, children: children }));
@@ -6941,8 +8038,37 @@ const cvaToggleItemContent = cssClassVarianceUtilities.cvaMerge([], {
6941
8038
  });
6942
8039
 
6943
8040
  /**
6944
- * Toggle Group allows users to toggle between two or more closely related options, and immediately apply that selection.
8041
+ * ToggleGroup allows users to toggle between two or more closely related options and immediately apply the selection.
8042
+ * It renders a segmented control with a sliding background indicator. Supports text-only, icon-only, and text+icon modes.
6945
8043
  *
8044
+ * ### When to use
8045
+ * Use ToggleGroup when the user needs to switch between 2-5 mutually exclusive options that take effect immediately (e.g., view modes, map/list toggle, time ranges).
8046
+ *
8047
+ * ### When not to use
8048
+ * Do not use ToggleGroup for navigation — use `Tabs`.
8049
+ * Do not use ToggleGroup for form selections with many options — use a Select or RadioGroup.
8050
+ *
8051
+ * @example ToggleGroup for view mode switching
8052
+ * ```tsx
8053
+ * import { ToggleGroup } from "@trackunit/react-components";
8054
+ * import { useState } from "react";
8055
+ *
8056
+ * const ViewToggle = () => {
8057
+ * const [selected, setSelected] = useState("list");
8058
+ *
8059
+ * return (
8060
+ * <ToggleGroup
8061
+ * selected={selected}
8062
+ * setSelected={setSelected}
8063
+ * onChange={(id) => console.log("Selected:", id)}
8064
+ * list={[
8065
+ * { id: "list", title: "List", iconName: "Bars3" },
8066
+ * { id: "map", title: "Map", iconName: "MapPin" },
8067
+ * ]}
8068
+ * />
8069
+ * );
8070
+ * };
8071
+ * ```
6946
8072
  * @param {ToggleGroupProps} props - The props for the ToggleGroup component
6947
8073
  * @returns {ReactElement} ToggleGroup component
6948
8074
  */
@@ -7059,7 +8185,7 @@ const SegmentedValueBar = ({ segments, total, size = "small", showValue = false,
7059
8185
  const valueText = formatValue(sum, unit);
7060
8186
  const canShowValue = showValue && size !== "extraSmall";
7061
8187
  const valueTextClassName = cvaValueBarText({ size: getValueTextVariant(size, sum, segments, total) });
7062
- return (jsxRuntime.jsxs("span", { className: "relative flex items-center gap-2", "data-testid": dataTestId, children: [jsxRuntime.jsx("div", { "aria-label": valueText, className: cvaSegmentedValueBar({ className, size }), "data-testid": dataTestId ? `${dataTestId}-track` : undefined, children: computedSegments.map((segment, index) => {
8188
+ return (jsxRuntime.jsxs("span", { className: valueBarContainerClassName, "data-testid": dataTestId, children: [jsxRuntime.jsx("div", { "aria-label": valueText, className: cvaSegmentedValueBar({ className, size }), "data-testid": dataTestId ? `${dataTestId}-track` : undefined, children: computedSegments.map((segment, index) => {
7063
8189
  const tooltipLabel = segment.label
7064
8190
  ? `${segment.label}: ${formatValue(segment.value, unit)}`
7065
8191
  : formatValue(segment.value, unit);