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