@trackunit/react-components 1.17.22 → 1.17.23

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 (56) hide show
  1. package/index.cjs.js +1309 -185
  2. package/index.esm.js +1309 -185
  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/ZStack/ZStack.d.ts +23 -4
  55. package/src/components/buttons/Button/Button.d.ts +1 -1
  56. 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";
@@ -4593,16 +5111,52 @@ const getValueBarColorByValue = (value, min, max, levelColors) => {
4593
5111
  };
4594
5112
 
4595
5113
  /**
4596
- * ValueBar component is used to display value on a colorful bar within provided range.
4597
-
4598
- * @param {ValueBarProps} props - The props for the ValueBar component
4599
- * @returns {ReactElement} ValueBar component
4600
- */
4601
- const ValueBar = ({ value, min = 0, max = 100, unit, size = "small", levelColors, valueColor, showValue = false, className, "data-testid": dataTestId, zeroScoreAllowed = false, ref, }) => {
4602
- const score = getScore(value, min, max, zeroScoreAllowed);
4603
- const barFillColor = levelColors ? getFillColor(score, levelColors) : getDefaultFillColor(score);
4604
- 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] }));
5114
+ * ValueBar displays a numeric value as a colored progress bar within a defined range.
5115
+ * The bar color changes based on the score (value relative to min/max) using either default or custom level colors.
5116
+ * It can optionally display the numeric value and unit alongside the bar.
5117
+ *
5118
+ * ### When to use
5119
+ * Use ValueBar to visualize a metric relative to a range (e.g., battery level, fuel percentage, utilization rate, temperature).
5120
+ *
5121
+ * ### When not to use
5122
+ * Do not use ValueBar for progress through a multi-step process. Use a stepper or progress indicator instead.
5123
+ *
5124
+ * @example Basic value bar with percentage
5125
+ * ```tsx
5126
+ * import { ValueBar } from "@trackunit/react-components";
5127
+ *
5128
+ * const BatteryLevel = () => (
5129
+ * <ValueBar value={72} min={0} max={100} unit="%" showValue />
5130
+ * );
5131
+ * ```
5132
+ * @example Value bar with custom level colors
5133
+ * ```tsx
5134
+ * import { ValueBar } from "@trackunit/react-components";
5135
+ *
5136
+ * const TemperatureBar = () => (
5137
+ * <ValueBar
5138
+ * value={85}
5139
+ * min={0}
5140
+ * max={120}
5141
+ * unit="°C"
5142
+ * showValue
5143
+ * size="large"
5144
+ * levelColors={[
5145
+ * { min: 0, max: 0.5, color: "#22c55e" },
5146
+ * { min: 0.5, max: 0.75, color: "#f59e0b" },
5147
+ * { min: 0.75, max: 1, color: "#ef4444" },
5148
+ * ]}
5149
+ * />
5150
+ * );
5151
+ * ```
5152
+ * @param {ValueBarProps} props - The props for the ValueBar component
5153
+ * @returns {ReactElement} ValueBar component
5154
+ */
5155
+ const ValueBar = ({ value, min = 0, max = 100, unit, size = "small", levelColors, valueColor, showValue = false, className, "data-testid": dataTestId, zeroScoreAllowed = false, ref, }) => {
5156
+ const score = getScore(value, min, max, zeroScoreAllowed);
5157
+ const barFillColor = levelColors ? getFillColor(score, levelColors) : getDefaultFillColor(score);
5158
+ const valueText = `${Number(value.toFixed(1))}${nonNullable(unit) ? unit : ""}`;
5159
+ 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] }));
4606
5160
  };
4607
5161
 
4608
5162
  const cvaKPICard = cvaMerge([
@@ -4703,13 +5257,29 @@ const KPICard = ({ isActive = false, onClick, className, "data-testid": dataTest
4703
5257
  };
4704
5258
 
4705
5259
  /**
4706
- * Display a single placeholder block for shape-based elements before data gets loaded to reduce load-time frustration.
5260
+ * SkeletonBlock renders a single animated placeholder block for shape-based elements (images, icons, buttons, avatars)
5261
+ * before data is loaded. It uses exact height and width values to match the element it replaces.
4707
5262
  *
4708
- * Fills the full height for images, badges, buttons, avatars, and other shape-based elements.
4709
- * Uses numbers or CSS length values for height.
5263
+ * ### When to use
5264
+ * Use SkeletonBlock for loading placeholders of shape-based UI elements: images, icons, badges, buttons, avatars, thumbnails.
4710
5265
  *
4711
- * For text content, use SkeletonLabel component instead.
4712
- * For multiple text lines, use SkeletonLines component instead.
5266
+ * ### When not to use
5267
+ * For text content, use `SkeletonLabel` which accounts for text line-height margins.
5268
+ * For multiple text lines, use `SkeletonLines`.
5269
+ *
5270
+ * @example Skeleton block for an avatar and button
5271
+ * ```tsx
5272
+ * import { SkeletonBlock } from "@trackunit/react-components";
5273
+ *
5274
+ * const AvatarSkeleton = () => (
5275
+ * <div className="flex items-center gap-3">
5276
+ * <SkeletonBlock height={40} width={40} className="rounded-full" />
5277
+ * <SkeletonBlock height={32} width={120} className="rounded-md" />
5278
+ * </div>
5279
+ * );
5280
+ * ```
5281
+ * @param {SkeletonBlockProps} props - The props for the SkeletonBlock component
5282
+ * @returns {ReactElement} SkeletonBlock component
4713
5283
  */
4714
5284
  const SkeletonBlock = memo((props) => {
4715
5285
  const { width = "100%", height = 16, flexibleWidth = false, className, "data-testid": dataTestId, children, ref, } = props;
@@ -4724,8 +5294,29 @@ const SkeletonBlock = memo((props) => {
4724
5294
  SkeletonBlock.displayName = "SkeletonBlock";
4725
5295
 
4726
5296
  /**
4727
- * Skeleton loading indicator that mimics the KPICard component structure.
4728
- * Uses the same layout, spacing, and visual hierarchy as KPICard.
5297
+ * KPICardSkeleton is a loading placeholder that mimics the layout of a KPICard.
5298
+ * It renders skeleton lines for the KPI title/value, and optional icon, trends, value bar, and notice slots.
5299
+ *
5300
+ * ### When to use
5301
+ * Use KPICardSkeleton while `KPICard` data is loading to maintain layout stability in dashboards and metric displays.
5302
+ *
5303
+ * ### When not to use
5304
+ * Do not use KPICardSkeleton for generic card loading — use a `Card` with `SkeletonLabel` inside.
5305
+ *
5306
+ * @example KPICard skeletons in a dashboard row
5307
+ * ```tsx
5308
+ * import { KPICardSkeleton } from "@trackunit/react-components";
5309
+ *
5310
+ * const LoadingMetrics = () => (
5311
+ * <div className="grid grid-cols-3 gap-4">
5312
+ * <KPICardSkeleton hasIcon hasTrends />
5313
+ * <KPICardSkeleton hasIcon hasValueBar />
5314
+ * <KPICardSkeleton hasNotice />
5315
+ * </div>
5316
+ * );
5317
+ * ```
5318
+ * @param {KPICardSkeletonProps} props - The props for the KPICardSkeleton component
5319
+ * @returns {ReactElement} KPICardSkeleton component
4729
5320
  */
4730
5321
  const KPICardSkeleton = ({ hasIcon = false, hasTrends = false, hasValueBar = false, hasNotice = false, children, className, "data-testid": dataTestId, style, ref, ...rest }) => {
4731
5322
  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 +5396,30 @@ const DEFAULT_SKELETON_LIST_ITEM_PROPS = {
4805
5396
  hasDetails: false,
4806
5397
  };
4807
5398
  /**
4808
- * Skeleton loading indicator that mimics the ListItem component structure.
4809
- * Uses the same layout, spacing, and visual hierarchy as ListItem.
5399
+ * ListItemSkeleton is a loading placeholder that mimics the layout of a ListItem.
5400
+ * It renders skeleton lines for the title, description, meta, thumbnail, and details slots.
5401
+ * Use it inside a List to indicate that list data is loading.
5402
+ *
5403
+ * ### When to use
5404
+ * Use ListItemSkeleton as the loading state inside a `List` when data is being fetched. Configure it to match the shape of your actual ListItems.
5405
+ *
5406
+ * ### When not to use
5407
+ * Do not use ListItemSkeleton for non-list loading states. Use `SkeletonBlock` or `SkeletonLabel` for generic loading placeholders.
5408
+ *
5409
+ * @example ListItemSkeleton matching a typical asset list item
5410
+ * ```tsx
5411
+ * import { ListItemSkeleton } from "@trackunit/react-components";
5412
+ *
5413
+ * const LoadingList = () => (
5414
+ * <div>
5415
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5416
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5417
+ * <ListItemSkeleton hasThumbnail hasDescription hasMeta={false} />
5418
+ * </div>
5419
+ * );
5420
+ * ```
5421
+ * @param {ListItemSkeletonProps} props - The props for the ListItemSkeleton component
5422
+ * @returns {ReactElement} ListItemSkeleton component
4810
5423
  */
4811
5424
  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
5425
  // Generate stable random widths once and never change them
@@ -5292,10 +5905,32 @@ const getResolvedLoadingIndicator = (loadingIndicator) => {
5292
5905
  };
5293
5906
 
5294
5907
  /**
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.
5908
+ * ListItem presents a concise row of information for quick scanning and navigation. It supports a title, description, meta text, thumbnail,
5909
+ * and a details slot. When `onClick` is provided, the item becomes interactive with a chevron indicator.
5296
5910
  *
5297
- * @param { ListItemProps} props - The props for the ListItem component
5298
- * @returns {Element} ListItem component
5911
+ * ### When to use
5912
+ * Use ListItem inside a `List` to display items such as assets, events, users, or notifications with consistent layout.
5913
+ *
5914
+ * ### When not to use
5915
+ * Do not use ListItem outside of a `List` component for standalone clickable elements — use `Card` or `Button`.
5916
+ *
5917
+ * @example ListItem with thumbnail and details
5918
+ * ```tsx
5919
+ * import { ListItem, Icon, Tag } from "@trackunit/react-components";
5920
+ *
5921
+ * const AssetListItem = () => (
5922
+ * <ListItem
5923
+ * title="Excavator CAT 320"
5924
+ * description="Serial: SN-2024-00142"
5925
+ * meta="Last seen: 2 hours ago"
5926
+ * thumbnail={<Icon name="Truck" size="small" />}
5927
+ * details={<Tag color="success" size="small">Active</Tag>}
5928
+ * onClick={() => console.log("Navigate to asset")}
5929
+ * />
5930
+ * );
5931
+ * ```
5932
+ * @param {ListItemProps} props - The props for the ListItem component
5933
+ * @returns {ReactElement} ListItem component
5299
5934
  */
5300
5935
  const ListItem = ({ className, "data-testid": dataTestId, onClick, details, title, description, meta, thumbnail, thumbnailColor = "info-600", thumbnailBackground = "info-100", ...rest }) => {
5301
5936
  const baseClass = cvaListItem({ className });
@@ -5399,7 +6034,28 @@ const cvaMenuListMultiSelect = cvaMerge([
5399
6034
  const cvaMenuListItem = cvaMerge("max-w-full");
5400
6035
 
5401
6036
  /**
5402
- * The MenuDivider component is used to separate items in a menu list.
6037
+ * MenuDivider renders a horizontal line to visually separate groups of items within a MenuList.
6038
+ *
6039
+ * ### When to use
6040
+ * Use MenuDivider between groups of related `MenuItem` elements to create logical sections within a menu.
6041
+ *
6042
+ * ### When not to use
6043
+ * Do not use MenuDivider outside of a `MenuList`. For general-purpose dividers, use `Spacer` with `border`.
6044
+ *
6045
+ * @example Menu with grouped sections
6046
+ * ```tsx
6047
+ * import { MenuList, MenuItem, MenuDivider, Icon } from "@trackunit/react-components";
6048
+ *
6049
+ * const GroupedMenu = () => (
6050
+ * <MenuList>
6051
+ * <MenuItem id="edit" label="Edit" prefix={<Icon name="PencilSquare" size="small" />} />
6052
+ * <MenuItem id="duplicate" label="Duplicate" prefix={<Icon name="DocumentDuplicate" size="small" />} />
6053
+ * <MenuDivider />
6054
+ * <MenuItem id="delete" label="Delete" variant="danger" prefix={<Icon name="Trash" size="small" />} />
6055
+ * </MenuList>
6056
+ * );
6057
+ * ```
6058
+ * @returns {ReactElement} MenuDivider component
5403
6059
  */
5404
6060
  const MenuDivider = () => {
5405
6061
  return jsx("div", { className: cvaMenuListDivider(), "data-testid": "menu-divider" });
@@ -5525,8 +6181,37 @@ const cvaMenuItemSuffix = cvaMerge(["text-neutral-400", "text-sm", "flex", "item
5525
6181
  });
5526
6182
 
5527
6183
  /**
5528
- * The MenuItem component is used to display a menu, primarily meant to be used in a list form.
6184
+ * MenuItem represents a single actionable item within a MenuList.
6185
+ * It supports labels, icons (prefix/suffix), selected and focused states, and danger variants.
5529
6186
  *
6187
+ * ### When to use
6188
+ * Use MenuItem inside a `MenuList` for individual actions (edit, delete, duplicate) or selectable options.
6189
+ *
6190
+ * ### When not to use
6191
+ * Do not use MenuItem outside of a `MenuList` context. For standalone clickable items, use `Button` or `ListItem`.
6192
+ *
6193
+ * @example MenuItem with icon prefix
6194
+ * ```tsx
6195
+ * import { MenuList, MenuItem, Icon } from "@trackunit/react-components";
6196
+ *
6197
+ * const ActionMenu = () => (
6198
+ * <MenuList>
6199
+ * <MenuItem
6200
+ * id="edit"
6201
+ * label="Edit asset"
6202
+ * prefix={<Icon name="PencilSquare" size="small" />}
6203
+ * onClick={() => console.log("Edit clicked")}
6204
+ * />
6205
+ * <MenuItem
6206
+ * id="delete"
6207
+ * label="Delete asset"
6208
+ * prefix={<Icon name="Trash" size="small" />}
6209
+ * variant="danger"
6210
+ * onClick={() => console.log("Delete clicked")}
6211
+ * />
6212
+ * </MenuList>
6213
+ * );
6214
+ * ```
5530
6215
  * @param {MenuItemProps} props - The props for the MenuItem component
5531
6216
  * @returns {ReactElement} MenuItem component
5532
6217
  */
@@ -5656,9 +6341,45 @@ const MenuList = ({ "data-testid": dataTestId, className, children, isMulti = fa
5656
6341
  const cvaMoreMenu = cvaMerge(["p-0"]);
5657
6342
 
5658
6343
  /**
5659
- * A kebab menu component.
5660
- * Advice: fill it with MenuList
6344
+ * MoreMenu (kebab menu) renders a three-dot button that opens a popover with a list of actions.
6345
+ * It is typically filled with a MenuList containing MenuItem elements.
6346
+ *
6347
+ * ### When to use
6348
+ * 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.
6349
+ *
6350
+ * ### When not to use
6351
+ * Do not use MoreMenu for primary actions that should always be visible. Use `Button` instead.
6352
+ *
6353
+ * @example Action items with render prop — Pass a function as `children` to receive the `close` callback and dismiss the menu after an action.
6354
+ * ```tsx
6355
+ * import { MoreMenu, MenuList, MenuItem, Icon } from "@trackunit/react-components";
6356
+ *
6357
+ * const AssetActions = () => (
6358
+ * <MoreMenu>
6359
+ * {(close) => (
6360
+ * <MenuList onClick={close}>
6361
+ * <MenuItem id="edit" label="Edit" prefix={<Icon name="PencilSquare" size="small" />} />
6362
+ * <MenuItem id="delete" label="Delete" variant="danger" prefix={<Icon name="Trash" size="small" />} />
6363
+ * </MenuList>
6364
+ * )}
6365
+ * </MoreMenu>
6366
+ * );
6367
+ * ```
6368
+ * @example Custom trigger button — Use `customButton` to replace the default kebab icon with any element, like a labeled Button.
6369
+ * ```tsx
6370
+ * import { MoreMenu, MenuList, MenuItem, Button } from "@trackunit/react-components";
5661
6371
  *
6372
+ * const CustomTriggerMenu = () => (
6373
+ * <MoreMenu customButton={<Button variant="secondary" size="small">Actions</Button>}>
6374
+ * {(close) => (
6375
+ * <MenuList onClick={close}>
6376
+ * <MenuItem id="export" label="Export" />
6377
+ * <MenuItem id="archive" label="Archive" />
6378
+ * </MenuList>
6379
+ * )}
6380
+ * </MoreMenu>
6381
+ * );
6382
+ * ```
5662
6383
  * @param {MoreMenuProps} props - The props for the MoreMenu component
5663
6384
  * @returns {ReactElement} MoreMenu component
5664
6385
  */
@@ -5711,12 +6432,42 @@ const cvaNoticeIcon = cvaMerge(["rounded-full", "items-center", "justify-center"
5711
6432
  });
5712
6433
 
5713
6434
  /**
5714
- * Notices are non-interactive elements that communicate information that the user needs to see, without directly prompting an action button.
6435
+ * Notice is a non-interactive element that communicates informational messages the user should see, without prompting an action.
6436
+ * It displays an optional icon and text label, with optional tooltip support.
6437
+ *
6438
+ * ### When to use
6439
+ * Use Notice to communicate non-essential, contextual information that does not require action (e.g., status notes, informational hints).
5715
6440
  *
5716
- * _**Do use** notices to communicate non-essential information that does not necessarily require action to be taken._
6441
+ * ### When not to use
6442
+ * Do not use Notice for essential information that requires user action — use `Alert` instead.
6443
+ * Do not use Notice for asset state indicators — use `Indicator` instead.
5717
6444
  *
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)._
6445
+ * @example Notice with icon and label
6446
+ * ```tsx
6447
+ * import { Notice } from "@trackunit/react-components";
5719
6448
  *
6449
+ * const InfoNotice = () => (
6450
+ * <Notice
6451
+ * iconName="InformationCircle"
6452
+ * label="Last synced 5 minutes ago"
6453
+ * color="info"
6454
+ * />
6455
+ * );
6456
+ * ```
6457
+ * @example Warning notice with tooltip
6458
+ * ```tsx
6459
+ * import { Notice } from "@trackunit/react-components";
6460
+ *
6461
+ * const WarningNotice = () => (
6462
+ * <Notice
6463
+ * iconName="ExclamationTriangle"
6464
+ * label="Low battery"
6465
+ * color="warning"
6466
+ * withTooltip
6467
+ * tooltipLabel="Battery level is below 20%"
6468
+ * />
6469
+ * );
6470
+ * ```
5720
6471
  * @param {NoticeProps} props - The props for the Notice component
5721
6472
  * @returns {ReactElement} Notice component
5722
6473
  */
@@ -5751,18 +6502,68 @@ const cvaPageContent = cvaMerge(["overflow-auto", "page-content", "grid", "gap-r
5751
6502
  });
5752
6503
 
5753
6504
  /**
5754
- * Renders the page component. Adds padding and layout to the page.
6505
+ * Page is the top-level layout container that applies consistent padding and layout to page content.
6506
+ * Use it in combination with PageContent and PageHeader.
6507
+ *
6508
+ * ### When to use
6509
+ * Use Page as the outermost wrapper for a page view. It provides the base layout structure (padding, spacing) for the page.
6510
+ *
6511
+ * ### When not to use
6512
+ * Do not use Page for card-level or section-level layout. Use `Card` or standard flex/grid containers instead.
6513
+ *
6514
+ * @example Page with header and content
6515
+ * ```tsx
6516
+ * import { Page, PageContent, PageHeader } from "@trackunit/react-components";
6517
+ *
6518
+ * const AssetListPage = () => (
6519
+ * <Page layout="default">
6520
+ * <PageHeader
6521
+ * title="Assets"
6522
+ * accessoryType="actions"
6523
+ * primaryAction={{ actionText: "Add Asset", actionCallback: () => {} }}
6524
+ * />
6525
+ * <PageContent layout="default">
6526
+ * <p>Asset list content goes here</p>
6527
+ * </PageContent>
6528
+ * </Page>
6529
+ * );
6530
+ * ```
6531
+ * @param {PageProps} props - The props for the Page component
6532
+ * @returns {ReactElement} Page component
5755
6533
  */
5756
6534
  const Page = ({ layout, className, children, "data-testid": dataTestId, ref }) => {
5757
6535
  return (jsx("div", { className: cvaPage({ className, layout }), "data-testid": dataTestId ? dataTestId : "page", ref: ref, children: children }));
5758
6536
  };
5759
6537
 
5760
6538
  /**
5761
- * Renders the content of a page.
5762
- * Applies padding to content. To be used within a <Page/>
6539
+ * PageContent is the main content area inside a Page.
6540
+ * It applies consistent padding to the content section. Must be used within a Page component.
5763
6541
  *
5764
- * @param {PageContentProps} props - The component props.
5765
- * @returns {ReactNode} - The rendered component.
6542
+ * ### When to use
6543
+ * Use PageContent to wrap the main content of a page, below a `PageHeader`. It provides consistent padding and layout.
6544
+ *
6545
+ * ### When not to use
6546
+ * Do not use PageContent outside of a `Page`. For standalone content wrappers, use `Card` or `CardBody`.
6547
+ *
6548
+ * @example PageContent inside a Page
6549
+ * ```tsx
6550
+ * import { Page, PageContent, PageHeader, Card, CardBody, Text } from "@trackunit/react-components";
6551
+ *
6552
+ * const DetailPage = () => (
6553
+ * <Page layout="default">
6554
+ * <PageHeader title="Asset Details" />
6555
+ * <PageContent layout="default">
6556
+ * <Card>
6557
+ * <CardBody>
6558
+ * <Text>Asset information goes here</Text>
6559
+ * </CardBody>
6560
+ * </Card>
6561
+ * </PageContent>
6562
+ * </Page>
6563
+ * );
6564
+ * ```
6565
+ * @param {PageContentProps} props - The props for the PageContent component
6566
+ * @returns {ReactElement} PageContent component
5766
6567
  */
5767
6568
  const PageContent = ({ className, children, "data-testid": dataTestId, layout, ref, }) => {
5768
6569
  return (jsx("div", { className: cvaPageContent({ className, layout }), "data-testid": dataTestId ? dataTestId : "page-content", ref: ref, children: children }));
@@ -5846,14 +6647,16 @@ cvaMerge([
5846
6647
  ]);
5847
6648
 
5848
6649
  /**
5849
- * Display multiple placeholder lines before data gets loaded to reduce load-time frustration.
6650
+ * SkeletonLines renders multiple animated placeholder text lines before data loads.
6651
+ * It supports three modes: uniform (identical lines), custom (per-line config), and preset (common patterns like paragraphs or articles).
6652
+ * Built on top of SkeletonLabel for text-specific margins and sizing.
5850
6653
  *
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
6654
+ * ### When to use
6655
+ * Use SkeletonLines for loading placeholders of multi-line text content: paragraphs, descriptions, articles, or any text block.
5855
6656
  *
5856
- * Built on top of the [SkeletonLabel](?path=/docs/components-loading-states-skeletonlabel--docs) component for text-specific margins and sizing.
6657
+ * ### When not to use
6658
+ * For single text lines, use `SkeletonLabel`.
6659
+ * For shape-based elements, use `SkeletonBlock`.
5857
6660
  *
5858
6661
  * @example
5859
6662
  * // Uniform lines (simple mode)
@@ -6062,11 +6865,15 @@ const PageHeaderTitle = ({ title, "data-testid": dataTestId, className, ref: for
6062
6865
  };
6063
6866
 
6064
6867
  /**
6065
- * The PageHeader component is used to display the header of a page.
6868
+ * PageHeader displays the header of a page, providing context about the current location within the application.
6869
+ * It supports a title, optional description tooltip, tag, action buttons, KPI metrics, and tabs for in-page navigation.
6066
6870
  *
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.
6871
+ * ### When to use
6872
+ * Use PageHeader at the top of a `Page` to display the page title, description, and primary/secondary actions.
6873
+ *
6874
+ * ### When not to use
6875
+ * Do not use PageHeader for section-level headings within a page. Use `SectionHeader` instead.
6876
+ * Do not use for card-level headers — use `CardHeader`.
6070
6877
  *
6071
6878
  * @example Page header with actions
6072
6879
  * ```tsx
@@ -6135,8 +6942,37 @@ const cvaPagination = cvaMerge(["flex", "items-center", "gap-1"]);
6135
6942
  const cvaPaginationText = cvaMerge("whitespace-nowrap");
6136
6943
 
6137
6944
  /**
6138
- * Pagination Description. It could be used when you need navigation for your paging feature.
6139
-
6945
+ * Pagination provides previous/next page navigation with an optional page counter and jump-to-page input.
6946
+ * It supports both offset-based pagination (with `pageIndex` and `pageCount`) and cursor-based pagination (with `cursorBase`).
6947
+ *
6948
+ * ### When to use
6949
+ * Use Pagination below a table or list when data is split across multiple pages and the user needs to navigate between them.
6950
+ *
6951
+ * ### When not to use
6952
+ * Do not use Pagination for infinite scroll patterns. Use the `useInfiniteScroll` hook instead.
6953
+ *
6954
+ * @example Basic offset-based pagination
6955
+ * ```tsx
6956
+ * import { Pagination } from "@trackunit/react-components";
6957
+ * import { useState } from "react";
6958
+ *
6959
+ * const PaginatedList = () => {
6960
+ * const [page, setPage] = useState(0);
6961
+ * const totalPages = 10;
6962
+ *
6963
+ * return (
6964
+ * <Pagination
6965
+ * pageIndex={page}
6966
+ * pageCount={totalPages}
6967
+ * canPreviousPage={page > 0}
6968
+ * canNextPage={page < totalPages - 1}
6969
+ * previousPage={() => setPage(p => p - 1)}
6970
+ * nextPage={() => setPage(p => p + 1)}
6971
+ * getTranslatedCount={(count) => `of ${count}`}
6972
+ * />
6973
+ * );
6974
+ * };
6975
+ * ```
6140
6976
  * @param {PaginationProps} props - The props for the Pagination component
6141
6977
  * @returns {ReactElement} Pagination component
6142
6978
  */
@@ -6192,10 +7028,29 @@ const Pagination = ({ previousPage, nextPage, canPreviousPage = false, canNextPa
6192
7028
 
6193
7029
  const STROKE_WIDTH_THRESHOLD = 32;
6194
7030
  /**
6195
- * Draws an svg Polygon from a set of points.
7031
+ * Polygon renders an SVG polygon from a set of coordinate points. Points are automatically normalized to fit within the specified size.
7032
+ * It supports fill/stroke color options and optional opacity for overlay effects.
6196
7033
  *
6197
- * @param { PolygonProps} props - The props for the Polygon component
6198
- * @returns {ReactElement} Polygon component
7034
+ * ### When to use
7035
+ * Use Polygon for rendering geofence boundaries, map overlays, or any custom shape defined by coordinate points.
7036
+ *
7037
+ * ### When not to use
7038
+ * Do not use Polygon for standard UI elements — use the design system components instead.
7039
+ *
7040
+ * @example Rendering a triangle
7041
+ * ```tsx
7042
+ * import { Polygon } from "@trackunit/react-components";
7043
+ *
7044
+ * const Triangle = () => (
7045
+ * <Polygon
7046
+ * points={[[0, 100], [50, 0], [100, 100]]}
7047
+ * size={64}
7048
+ * color="black"
7049
+ * />
7050
+ * );
7051
+ * ```
7052
+ * @param {PolygonProps} props - The props for the Polygon component
7053
+ * @returns {ReactElement} Polygon component
6199
7054
  */
6200
7055
  const Polygon = ({ points, size, color = "black", opaque = true, className, "data-testid": dataTestId, ref, }) => {
6201
7056
  // Calculate the bounds of the points
@@ -6225,8 +7080,39 @@ const Polygon = ({ points, size, color = "black", opaque = true, className, "dat
6225
7080
  const normalize = ({ value, min, max, size }) => ((value - min) / (max - min)) * size;
6226
7081
 
6227
7082
  /**
6228
- * The PopoverTitle component.
7083
+ * PopoverTitle renders a styled title bar at the top of a PopoverContent panel.
7084
+ * It displays uppercase bold text with an optional action element and divider.
6229
7085
  *
7086
+ * ### When to use
7087
+ * Use PopoverTitle inside `PopoverContent` when the popover needs a labeled header, optionally with an action (e.g., a close button).
7088
+ *
7089
+ * ### When not to use
7090
+ * Do not use PopoverTitle outside of a `Popover` context. For standalone headings, use `Heading`.
7091
+ *
7092
+ * @example Popover with titled content
7093
+ * ```tsx
7094
+ * import { Popover, PopoverTrigger, PopoverContent, PopoverTitle, Button, Text } from "@trackunit/react-components";
7095
+ *
7096
+ * const TitledPopover = () => (
7097
+ * <Popover placement="bottom-start">
7098
+ * <PopoverTrigger>
7099
+ * <Button variant="secondary">Details</Button>
7100
+ * </PopoverTrigger>
7101
+ * <PopoverContent>
7102
+ * {(close) => (
7103
+ * <div className="w-64">
7104
+ * <PopoverTitle divider action={<Button variant="ghost" size="small" onClick={close}>Close</Button>}>
7105
+ * Asset Info
7106
+ * </PopoverTitle>
7107
+ * <div className="p-3">
7108
+ * <Text size="small">Additional information about this asset.</Text>
7109
+ * </div>
7110
+ * </div>
7111
+ * )}
7112
+ * </PopoverContent>
7113
+ * </Popover>
7114
+ * );
7115
+ * ```
6230
7116
  * @param {PopoverTitleProps} props - The props for the PopoverTitle component
6231
7117
  * @returns {ReactElement} PopoverTitle component
6232
7118
  */
@@ -6369,9 +7255,31 @@ const preferenceCardGrid = createGrid()
6369
7255
  })
6370
7256
  .build();
6371
7257
  /**
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.
7258
+ * PreferenceCard is a flexible component for displaying add-on options or settings with an optional input control (checkbox, radio, toggle).
7259
+ * It supports icons/images, titles with tags, descriptions, and custom child content for advanced layouts.
7260
+ *
7261
+ * ### When to use
7262
+ * Use PreferenceCard for settings pages, feature toggles, or plan selection where each option needs a title, description, and an input control.
7263
+ *
7264
+ * ### When not to use
7265
+ * Do not use PreferenceCard for data display — use `Card`.
7266
+ * Do not use for simple toggle settings — use a standalone toggle switch.
7267
+ *
7268
+ * @example PreferenceCard with checkbox input
7269
+ * ```tsx
7270
+ * import { PreferenceCard } from "@trackunit/react-components";
7271
+ *
7272
+ * const FeatureToggle = () => (
7273
+ * <PreferenceCard
7274
+ * title="Email Notifications"
7275
+ * description="Receive email alerts for asset status changes"
7276
+ * icon={{ type: "icon", name: "EnvelopeOpen", containerClassName: "bg-primary-100" }}
7277
+ * input={<input type="checkbox" />}
7278
+ * />
7279
+ * );
7280
+ * ```
7281
+ * @param {PreferenceCardProps} props - The props for the PreferenceCard component
7282
+ * @returns {ReactNode} PreferenceCard component
6375
7283
  */
6376
7284
  const PreferenceCard = ({ title, description, icon, input, titleTag, cardTag, disabled = false, className, "data-testid": dataTestId, children, ref: forwardedRef, }) => {
6377
7285
  const { ref: measureRef, geometry } = useMeasure();
@@ -6421,8 +7329,29 @@ const getRandomWidth = (min, max) => {
6421
7329
  return Math.floor(Math.random() * (max - min + 1)) + min;
6422
7330
  };
6423
7331
  /**
6424
- * Skeleton loading indicator that mimics the PreferenceCard component structure.
6425
- * Uses the same grid layout, spacing, and visual hierarchy as PreferenceCard.
7332
+ * PreferenceCardSkeleton is a loading placeholder that mimics the layout of a PreferenceCard.
7333
+ * It renders skeleton lines for the title, description, and optional slots (icon, tags, input).
7334
+ * Configure the boolean flags to match the shape of your actual PreferenceCards.
7335
+ *
7336
+ * ### When to use
7337
+ * Use PreferenceCardSkeleton while preference/settings data is loading to maintain layout stability and reduce perceived load time.
7338
+ *
7339
+ * ### When not to use
7340
+ * Do not use PreferenceCardSkeleton for generic loading — use `SkeletonBlock` or `SkeletonLabel`.
7341
+ *
7342
+ * @example PreferenceCard skeleton with icon and input
7343
+ * ```tsx
7344
+ * import { PreferenceCardSkeleton } from "@trackunit/react-components";
7345
+ *
7346
+ * const LoadingSettings = () => (
7347
+ * <div className="flex flex-col gap-3">
7348
+ * <PreferenceCardSkeleton hasIcon hasInput />
7349
+ * <PreferenceCardSkeleton hasIcon hasInput />
7350
+ * </div>
7351
+ * );
7352
+ * ```
7353
+ * @param {PreferenceCardSkeletonProps} props - The props for the PreferenceCardSkeleton component
7354
+ * @returns {ReactElement} PreferenceCardSkeleton component
6426
7355
  */
6427
7356
  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
7357
  const gridAreas = useGridAreas(preferenceCardGrid);
@@ -6449,11 +7378,27 @@ function useConfirmExit(confirmExit, when = true) {
6449
7378
  useBlocker(confirmExit, when);
6450
7379
  }
6451
7380
  /**
6452
- * The usePrompt hook.
6453
-
6454
- * @param {string} message -
6455
- * @param {boolean} when -
6456
- * @returns {void} void
7381
+ * usePrompt displays a browser confirmation dialog when the user tries to navigate away from the current page.
7382
+ * It blocks both in-app navigation (via TanStack Router's `useBlocker`) and browser-level navigation (via `beforeunload`).
7383
+ *
7384
+ * ### When to use
7385
+ * Use usePrompt when the user has unsaved changes (e.g., in a form) and should be warned before navigating away.
7386
+ *
7387
+ * ### When not to use
7388
+ * Do not use usePrompt for non-destructive navigation. Only use when there is genuinely unsaved state that would be lost.
7389
+ *
7390
+ * @example Warn user about unsaved form changes
7391
+ * ```tsx
7392
+ * import { usePrompt } from "@trackunit/react-components";
7393
+ *
7394
+ * const EditForm = ({ isDirty }: { isDirty: boolean }) => {
7395
+ * usePrompt("You have unsaved changes. Are you sure you want to leave?", isDirty);
7396
+ * return <form>...</form>;
7397
+ * };
7398
+ * ```
7399
+ * @param {string} message - The confirmation message shown to the user
7400
+ * @param {boolean} when - Whether the prompt should be active. Defaults to true.
7401
+ * @returns {void}
6457
7402
  */
6458
7403
  const usePrompt = (message, when = true) => {
6459
7404
  useEffect(() => {
@@ -6476,10 +7421,28 @@ const usePrompt = (message, when = true) => {
6476
7421
  useConfirmExit(confirmExit, when);
6477
7422
  };
6478
7423
  /**
6479
- * The Prompt function.
7424
+ * Prompt is a declarative component wrapper around the `usePrompt` hook. It displays a browser confirmation dialog
7425
+ * when the user tries to navigate away while `when` is true.
6480
7426
  *
6481
- * @param {PromptProps} Props -
6482
- * @returns {void} void
7427
+ * ### When to use
7428
+ * Use Prompt when you prefer a declarative approach to navigation blocking (instead of the `usePrompt` hook).
7429
+ *
7430
+ * ### When not to use
7431
+ * Do not use Prompt when `when` is always false — simply omit it.
7432
+ *
7433
+ * @example Declarative prompt for unsaved changes
7434
+ * ```tsx
7435
+ * import { Prompt } from "@trackunit/react-components";
7436
+ *
7437
+ * const EditPage = ({ hasUnsavedChanges }: { hasUnsavedChanges: boolean }) => (
7438
+ * <>
7439
+ * <Prompt when={hasUnsavedChanges} message="Discard unsaved changes?" />
7440
+ * <form>...</form>
7441
+ * </>
7442
+ * );
7443
+ * ```
7444
+ * @param {PromptProps} props - The props for the Prompt component
7445
+ * @returns {null} Renders nothing; only activates the navigation prompt
6483
7446
  */
6484
7447
  const Prompt = ({ when, message }) => {
6485
7448
  usePrompt(message, when);
@@ -6505,18 +7468,25 @@ const cvaSpacer = cvaMerge([], {
6505
7468
  });
6506
7469
 
6507
7470
  /**
6508
- * The Spacer component is used for adding a bit of space in the ui.
7471
+ * Spacer adds vertical whitespace between elements. It can optionally render a visible border line as a divider.
7472
+ *
7473
+ * ### When to use
7474
+ * Use Spacer to add consistent vertical gaps between sections or to render a horizontal divider line.
7475
+ *
7476
+ * ### When not to use
7477
+ * Do not use Spacer for horizontal gaps — use Tailwind flex/grid gap utilities. Do not use for structural layout — use CSS grid or flex.
6509
7478
  *
6510
- * @example basic usage
7479
+ * @example Spacer as a divider
6511
7480
  * ```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
- * };
7481
+ * import { Spacer, Text } from "@trackunit/react-components";
7482
+ *
7483
+ * const DividedSections = () => (
7484
+ * <div>
7485
+ * <Text>Section 1 content</Text>
7486
+ * <Spacer size="medium" border />
7487
+ * <Text>Section 2 content</Text>
7488
+ * </div>
7489
+ * );
6520
7490
  * ```
6521
7491
  * @param {SpacerProps} props - The props for the Spacer component
6522
7492
  * @returns {ReactElement} Spacer component
@@ -6526,9 +7496,29 @@ const Spacer = ({ size = "medium", border = false, "data-testid": dataTestId, cl
6526
7496
  };
6527
7497
 
6528
7498
  /**
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
7499
+ * SectionHeader renders a section title with an optional subtitle and addon elements (e.g., action buttons, status indicators).
7500
+ * It also sets the document title via React Helmet for SEO and browser tab labeling.
7501
+ *
7502
+ * ### When to use
7503
+ * Use SectionHeader to label a distinct section within a page, below a `PageHeader`. It provides consistent heading styles and an optional subtitle.
7504
+ *
7505
+ * ### When not to use
7506
+ * Do not use SectionHeader for the main page title — use `PageHeader`.
7507
+ * Do not use for card-level headers — use `CardHeader`.
7508
+ *
7509
+ * @example Section header with subtitle and addon
7510
+ * ```tsx
7511
+ * import { SectionHeader, Button } from "@trackunit/react-components";
7512
+ *
7513
+ * const AssetSection = () => (
7514
+ * <SectionHeader
7515
+ * title="Maintenance Schedule"
7516
+ * subtitle="Upcoming and past maintenance events"
7517
+ * addons={<Button variant="secondary" size="small">Add Event</Button>}
7518
+ * />
7519
+ * );
7520
+ * ```
7521
+ * @param {SectionHeaderProps} props - The props for the SectionHeader component
6532
7522
  * @returns {ReactElement} SectionHeader component
6533
7523
  */
6534
7524
  const SectionHeader = ({ title, subtitle, "data-testid": dataTestId, addons, ref, }) => {
@@ -6604,12 +7594,19 @@ const useOverflowItems = ({ threshold = 1, childUniqueIdentifierAttribute = "id"
6604
7594
  };
6605
7595
 
6606
7596
  /**
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._**
7597
+ * Sidebar renders a responsive horizontal/vertical navigation bar that automatically collapses overflowing items into a MoreMenu.
7598
+ * It is rendered horizontally until a given breakpoint, then stacks vertically.
6611
7599
  *
6612
- * When using this component make sure to add `setupIntersectionObserver();` to your jest.setup.ts file.
7600
+ * **Important:** The Sidebar is just a layout wrapper. You are responsible for styling the children.
7601
+ * For the overflow functionality, use `min-w-[*]` or `flex-shrink-0` on child elements.
7602
+ *
7603
+ * When testing, add `setupIntersectionObserver();` to your `jest.setup.ts` file.
7604
+ *
7605
+ * ### When to use
7606
+ * Use Sidebar for secondary in-page navigation (e.g., switching between views within a page). Works well with `Tabs` for page-level navigation.
7607
+ *
7608
+ * ### When not to use
7609
+ * Do not use Sidebar for primary app navigation (the main menu). For top-level navigation, use the app shell navigation.
6613
7610
  *
6614
7611
  * @example Responsive sidebar with navigation items
6615
7612
  * ```tsx
@@ -6715,8 +7712,35 @@ const cvaTab = cvaMerge([
6715
7712
  });
6716
7713
 
6717
7714
  /**
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.
7715
+ * Tab is an individual tab trigger within a TabList.
7716
+ * Each Tab requires a unique `value` prop that corresponds to a TabContent with the same value.
7717
+ * Supports optional icons, suffixes (e.g., badges), and rendering as a custom child element via `asChild`.
7718
+ *
7719
+ * ### When to use
7720
+ * Use Tab inside a `TabList` to create clickable tab triggers. Each Tab maps to a `TabContent` panel.
7721
+ *
7722
+ * ### When not to use
7723
+ * Do not use Tab outside of a `TabList`/`Tabs` context. For standalone buttons, use `Button`.
7724
+ *
7725
+ * @example Tab with icon and badge suffix
7726
+ * ```tsx
7727
+ * import { Tabs, TabList, Tab, TabContent, Badge } from "@trackunit/react-components";
7728
+ *
7729
+ * const TabsWithBadge = () => (
7730
+ * <Tabs defaultValue="alerts">
7731
+ * <TabList>
7732
+ * <Tab value="alerts" iconName="Bell" suffix={<Badge count={3} color="danger" />}>
7733
+ * Alerts
7734
+ * </Tab>
7735
+ * <Tab value="history" iconName="Clock">History</Tab>
7736
+ * </TabList>
7737
+ * <TabContent value="alerts">Active alerts</TabContent>
7738
+ * <TabContent value="history">Event history</TabContent>
7739
+ * </Tabs>
7740
+ * );
7741
+ * ```
7742
+ * @param {TabProps} props - The props for the Tab component
7743
+ * @returns {ReactElement} Tab component
6720
7744
  */
6721
7745
  const Tab = ({ value, isFullWidth = false, iconName = undefined, "data-testid": dataTestId, className, children, suffix, asChild = false, appendTabStylesToChildIfAsChild = true, ref, ...rest }) => {
6722
7746
  const renderContent = () => (jsxs(Fragment$1, { children: [iconName !== undefined ? jsx(Icon, { name: iconName, size: "small" }) : null, isValidElement(children) ? children.props.children : children, suffix] }));
@@ -6731,14 +7755,72 @@ const Tab = ({ value, isFullWidth = false, iconName = undefined, "data-testid":
6731
7755
  };
6732
7756
 
6733
7757
  /**
6734
- * Wrapper for radix tab content component.
7758
+ * TabContent is the content panel displayed when its corresponding Tab is active.
7759
+ * Each TabContent must have a `value` prop that matches the `value` of its corresponding Tab trigger.
7760
+ * TabContent is only rendered when its tab is selected (unless `forceMount` is set).
7761
+ *
7762
+ * ### When to use
7763
+ * Use TabContent inside a `Tabs` component, one for each `Tab` trigger.
7764
+ *
7765
+ * ### When not to use
7766
+ * Do not use TabContent outside of a `Tabs` context. For conditionally shown content, use standard conditional rendering.
7767
+ *
7768
+ * @example Tabs with styled content panels
7769
+ * ```tsx
7770
+ * import { Tabs, TabList, Tab, TabContent, Text } from "@trackunit/react-components";
7771
+ *
7772
+ * const AssetTabs = () => (
7773
+ * <Tabs defaultValue="overview">
7774
+ * <TabList>
7775
+ * <Tab value="overview">Overview</Tab>
7776
+ * <Tab value="maintenance">Maintenance</Tab>
7777
+ * </TabList>
7778
+ * <TabContent value="overview">
7779
+ * <Text>Asset overview information</Text>
7780
+ * </TabContent>
7781
+ * <TabContent value="maintenance">
7782
+ * <Text>Maintenance schedule and history</Text>
7783
+ * </TabContent>
7784
+ * </Tabs>
7785
+ * );
7786
+ * ```
7787
+ * @param {TabContentProps} props - The props for the TabContent component
7788
+ * @returns {ReactElement} TabContent component
6735
7789
  */
6736
7790
  const TabContent = ({ className, "data-testid": dataTestId, children, ref, ...rest }) => {
6737
7791
  return (jsx(Content, { className: cvaTabContent({ className }), "data-testid": dataTestId ? `${dataTestId}-content` : undefined, ref: ref, ...rest, children: children }));
6738
7792
  };
6739
7793
 
6740
7794
  /**
6741
- * Wrapper for radix tab list component.
7795
+ * TabList is the container for Tab triggers inside a Tabs component.
7796
+ * It renders a horizontal row of tab triggers and handles horizontal scroll behavior when tabs overflow.
7797
+ * By default, it auto-scrolls the active tab into view.
7798
+ *
7799
+ * ### When to use
7800
+ * Use TabList as a direct child of `Tabs` to wrap the `Tab` triggers. It handles layout and scrolling.
7801
+ *
7802
+ * ### When not to use
7803
+ * Do not use TabList outside of a `Tabs` context. For horizontal navigation lists, use a standard nav element.
7804
+ *
7805
+ * @example TabList with auto-scroll disabled
7806
+ * ```tsx
7807
+ * import { Tabs, TabList, Tab, TabContent } from "@trackunit/react-components";
7808
+ *
7809
+ * const StaticTabs = () => (
7810
+ * <Tabs defaultValue="first">
7811
+ * <TabList autoScrollToActive={false}>
7812
+ * <Tab value="first">First</Tab>
7813
+ * <Tab value="second">Second</Tab>
7814
+ * <Tab value="third">Third</Tab>
7815
+ * </TabList>
7816
+ * <TabContent value="first">First panel</TabContent>
7817
+ * <TabContent value="second">Second panel</TabContent>
7818
+ * <TabContent value="third">Third panel</TabContent>
7819
+ * </Tabs>
7820
+ * );
7821
+ * ```
7822
+ * @param {TabListProps} props - The props for the TabList component
7823
+ * @returns {ReactElement} TabList component
6742
7824
  */
6743
7825
  const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToActive = true, ref, ...rest }) => {
6744
7826
  const listRef = useRef(null);
@@ -6785,7 +7867,18 @@ const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToA
6785
7867
  };
6786
7868
 
6787
7869
  /**
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.
7870
+ * Tabs group different but related content, allowing users to navigate views without leaving the page.
7871
+ * They always contain at least two items and one tab is active at a time.
7872
+ * Tabs can be used on full page layouts or in components such as modals or tables.
7873
+ *
7874
+ * Compose Tabs with TabList, Tab, and TabContent.
7875
+ *
7876
+ * ### When to use
7877
+ * Use tabs to switch between related content sections within the same context (e.g., different views of an asset, or settings categories).
7878
+ *
7879
+ * ### When not to use
7880
+ * Do not use tabs for primary navigation between unrelated pages. Use `Sidebar` or route-based navigation instead.
7881
+ * Avoid tabs when there is only one content panel — just show the content directly.
6789
7882
  *
6790
7883
  * @example Basic tabs with content panels
6791
7884
  * ```tsx
@@ -6819,6 +7912,8 @@ const TabList = ({ className, "data-testid": dataTestId, children, autoScrollToA
6819
7912
  * </Tabs>
6820
7913
  * );
6821
7914
  * ```
7915
+ * @param {TabsProps} props - The props for the Tabs component
7916
+ * @returns {ReactElement} Tabs component
6822
7917
  */
6823
7918
  const Tabs = ({ children, forceRender, className, "data-testid": dataTestId, fullWidth, ref, ...rest }) => {
6824
7919
  return (jsx(Root, { className: cvaTabsRoot({ className }), "data-testid": dataTestId, ref: ref, ...rest, children: children }));
@@ -6939,8 +8034,37 @@ const cvaToggleItemContent = cvaMerge([], {
6939
8034
  });
6940
8035
 
6941
8036
  /**
6942
- * Toggle Group allows users to toggle between two or more closely related options, and immediately apply that selection.
8037
+ * ToggleGroup allows users to toggle between two or more closely related options and immediately apply the selection.
8038
+ * It renders a segmented control with a sliding background indicator. Supports text-only, icon-only, and text+icon modes.
8039
+ *
8040
+ * ### When to use
8041
+ * 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).
8042
+ *
8043
+ * ### When not to use
8044
+ * Do not use ToggleGroup for navigation — use `Tabs`.
8045
+ * Do not use ToggleGroup for form selections with many options — use a Select or RadioGroup.
8046
+ *
8047
+ * @example ToggleGroup for view mode switching
8048
+ * ```tsx
8049
+ * import { ToggleGroup } from "@trackunit/react-components";
8050
+ * import { useState } from "react";
8051
+ *
8052
+ * const ViewToggle = () => {
8053
+ * const [selected, setSelected] = useState("list");
6943
8054
  *
8055
+ * return (
8056
+ * <ToggleGroup
8057
+ * selected={selected}
8058
+ * setSelected={setSelected}
8059
+ * onChange={(id) => console.log("Selected:", id)}
8060
+ * list={[
8061
+ * { id: "list", title: "List", iconName: "Bars3" },
8062
+ * { id: "map", title: "Map", iconName: "MapPin" },
8063
+ * ]}
8064
+ * />
8065
+ * );
8066
+ * };
8067
+ * ```
6944
8068
  * @param {ToggleGroupProps} props - The props for the ToggleGroup component
6945
8069
  * @returns {ReactElement} ToggleGroup component
6946
8070
  */