@cerberus-design/react 0.2.0-next-ae70f9a → 0.2.0-next-87c3df1

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 (52) hide show
  1. package/build/legacy/_tsup-dts-rollup.d.ts +125 -0
  2. package/build/legacy/chunk-24B4KIPX.js +46 -0
  3. package/build/legacy/chunk-24B4KIPX.js.map +1 -0
  4. package/build/legacy/chunk-6DXQW4WK.js +109 -0
  5. package/build/legacy/chunk-6DXQW4WK.js.map +1 -0
  6. package/build/legacy/chunk-BVILNJ6M.js +28 -0
  7. package/build/legacy/chunk-BVILNJ6M.js.map +1 -0
  8. package/build/legacy/chunk-UI7OR6PG.js +31 -0
  9. package/build/legacy/chunk-UI7OR6PG.js.map +1 -0
  10. package/build/legacy/components/Tab.d.ts +2 -0
  11. package/build/legacy/components/Tab.js +9 -0
  12. package/build/legacy/components/Tab.js.map +1 -0
  13. package/build/legacy/components/TabList.d.ts +2 -0
  14. package/build/legacy/components/TabList.js +7 -0
  15. package/build/legacy/components/TabList.js.map +1 -0
  16. package/build/legacy/components/TabPanel.d.ts +2 -0
  17. package/build/legacy/components/TabPanel.js +10 -0
  18. package/build/legacy/components/TabPanel.js.map +1 -0
  19. package/build/legacy/context/tabs.d.ts +4 -0
  20. package/build/legacy/context/tabs.js +10 -0
  21. package/build/legacy/context/tabs.js.map +1 -0
  22. package/build/legacy/index.d.ts +10 -0
  23. package/build/legacy/index.js +18 -0
  24. package/build/modern/_tsup-dts-rollup.d.ts +125 -0
  25. package/build/modern/chunk-24B4KIPX.js +46 -0
  26. package/build/modern/chunk-24B4KIPX.js.map +1 -0
  27. package/build/modern/chunk-AMFL3PZV.js +108 -0
  28. package/build/modern/chunk-AMFL3PZV.js.map +1 -0
  29. package/build/modern/chunk-BVILNJ6M.js +28 -0
  30. package/build/modern/chunk-BVILNJ6M.js.map +1 -0
  31. package/build/modern/chunk-UI7OR6PG.js +31 -0
  32. package/build/modern/chunk-UI7OR6PG.js.map +1 -0
  33. package/build/modern/components/Tab.d.ts +2 -0
  34. package/build/modern/components/Tab.js +9 -0
  35. package/build/modern/components/Tab.js.map +1 -0
  36. package/build/modern/components/TabList.d.ts +2 -0
  37. package/build/modern/components/TabList.js +7 -0
  38. package/build/modern/components/TabList.js.map +1 -0
  39. package/build/modern/components/TabPanel.d.ts +2 -0
  40. package/build/modern/components/TabPanel.js +10 -0
  41. package/build/modern/components/TabPanel.js.map +1 -0
  42. package/build/modern/context/tabs.d.ts +4 -0
  43. package/build/modern/context/tabs.js +10 -0
  44. package/build/modern/context/tabs.js.map +1 -0
  45. package/build/modern/index.d.ts +10 -0
  46. package/build/modern/index.js +18 -0
  47. package/package.json +1 -1
  48. package/src/components/Tab.tsx +128 -0
  49. package/src/components/TabList.tsx +42 -0
  50. package/src/components/TabPanel.tsx +45 -0
  51. package/src/context/tabs.tsx +83 -0
  52. package/src/index.ts +4 -0
@@ -0,0 +1,46 @@
1
+ // src/context/tabs.tsx
2
+ import {
3
+ createContext,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useState
8
+ } from "react";
9
+ import { jsx } from "react/jsx-runtime";
10
+ var TabsContext = createContext(null);
11
+ function Tabs(props) {
12
+ const { cache } = props;
13
+ const [active, setActive] = useState(() => props.active ?? "");
14
+ const value = useMemo(
15
+ () => ({
16
+ active,
17
+ onTabUpdate: setActive
18
+ }),
19
+ [active, setActive]
20
+ );
21
+ useEffect(() => {
22
+ if (cache) {
23
+ const cachedTab = window.localStorage.getItem("cerberus-tabs");
24
+ setActive(cachedTab ?? active);
25
+ }
26
+ }, [cache]);
27
+ useEffect(() => {
28
+ if (cache) {
29
+ window.localStorage.setItem("cerberus-tabs", active);
30
+ }
31
+ }, [active, cache]);
32
+ return /* @__PURE__ */ jsx(TabsContext.Provider, { value, children: props.children });
33
+ }
34
+ function useTabsContext() {
35
+ const context = useContext(TabsContext);
36
+ if (!context) {
37
+ throw new Error("useTabsContext must be used within a Tabs Provider.");
38
+ }
39
+ return context;
40
+ }
41
+
42
+ export {
43
+ Tabs,
44
+ useTabsContext
45
+ };
46
+ //# sourceMappingURL=chunk-24B4KIPX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/context/tabs.tsx"],"sourcesContent":["'use client'\n\nimport {\n createContext,\n useContext,\n useEffect,\n useMemo,\n useState,\n type PropsWithChildren,\n} from 'react'\n\n/**\n * This module provides a Tabs component and a hook to access its context.\n * @module\n */\n\nexport interface TabsContextValue {\n active: string\n onTabUpdate: (active: string) => void\n}\n\nconst TabsContext = createContext<TabsContextValue | null>(null)\n\nexport interface TabsProps {\n active?: string\n cache?: boolean\n}\n\n/**\n * The Tabs component provides a context to manage tab state.\n * @param active - the default active tab id,\n * @param cache - whether to cache the active tab state\n * @example\n * ```tsx\n * <Tabs cache>\n * <TabList description=\"Button details\">\n * <Tab id=\"overview\">Overview</Tab>\n * <Tab id=\"guidelines\">Guidelines</Tab>\n * </TabList>\n * <TabPanels>\n * <TabPanel id=\"overview\">Overview content</TabPanel>\n * <TabPanel id=\"guidelines\">Guidelines content</TabPanel>\n * </TabPanels>\n * </Tabs>\n * ```\n */\nexport function Tabs(props: PropsWithChildren<TabsProps>): JSX.Element {\n const { cache } = props\n const [active, setActive] = useState(() => props.active ?? '')\n\n const value = useMemo(\n () => ({\n active,\n onTabUpdate: setActive,\n }),\n [active, setActive],\n )\n\n useEffect(() => {\n if (cache) {\n const cachedTab = window.localStorage.getItem('cerberus-tabs')\n setActive(cachedTab ?? active)\n }\n }, [cache])\n\n useEffect(() => {\n if (cache) {\n window.localStorage.setItem('cerberus-tabs', active)\n }\n }, [active, cache])\n\n return (\n <TabsContext.Provider value={value}>{props.children}</TabsContext.Provider>\n )\n}\n\nexport function useTabsContext(): TabsContextValue {\n const context = useContext(TabsContext)\n if (!context) {\n throw new Error('useTabsContext must be used within a Tabs Provider.')\n }\n return context\n}\n"],"mappings":";AAEA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA+DH;AAnDJ,IAAM,cAAc,cAAuC,IAAI;AAyBxD,SAAS,KAAK,OAAkD;AACrE,QAAM,EAAE,MAAM,IAAI;AAClB,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,MAAM,MAAM,UAAU,EAAE;AAE7D,QAAM,QAAQ;AAAA,IACZ,OAAO;AAAA,MACL;AAAA,MACA,aAAa;AAAA,IACf;AAAA,IACA,CAAC,QAAQ,SAAS;AAAA,EACpB;AAEA,YAAU,MAAM;AACd,QAAI,OAAO;AACT,YAAM,YAAY,OAAO,aAAa,QAAQ,eAAe;AAC7D,gBAAU,aAAa,MAAM;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,YAAU,MAAM;AACd,QAAI,OAAO;AACT,aAAO,aAAa,QAAQ,iBAAiB,MAAM;AAAA,IACrD;AAAA,EACF,GAAG,CAAC,QAAQ,KAAK,CAAC;AAElB,SACE,oBAAC,YAAY,UAAZ,EAAqB,OAAe,gBAAM,UAAS;AAExD;AAEO,SAAS,iBAAmC;AACjD,QAAM,UAAU,WAAW,WAAW;AACtC,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AACA,SAAO;AACT;","names":[]}
@@ -0,0 +1,108 @@
1
+ import {
2
+ useTabsContext
3
+ } from "./chunk-24B4KIPX.js";
4
+
5
+ // src/components/Tab.tsx
6
+ import { useMemo } from "react";
7
+ import { css, cx } from "@cerberus/styled-system/css";
8
+ import { jsx } from "react/jsx-runtime";
9
+ function Tab(props) {
10
+ const { controls, value, ...nativeProps } = props;
11
+ const { active, onTabUpdate } = useTabsContext();
12
+ const isActive = useMemo(() => active === value, [active, value]);
13
+ function handleClick(e) {
14
+ props.onClick?.(e);
15
+ onTabUpdate(e.currentTarget.value);
16
+ }
17
+ return /* @__PURE__ */ jsx(
18
+ "button",
19
+ {
20
+ ...nativeProps,
21
+ ...!isActive && { tabIndex: -1 },
22
+ "aria-controls": controls,
23
+ "aria-selected": isActive,
24
+ className: cx(nativeProps.className, btnStyles),
25
+ onClick: handleClick,
26
+ role: "tab",
27
+ value
28
+ }
29
+ );
30
+ }
31
+ var btnStyles = css({
32
+ fontSize: "sm",
33
+ fontWeight: "600",
34
+ h: "2.75rem",
35
+ position: "relative",
36
+ pxi: "4",
37
+ zIndex: "base",
38
+ _motionSafe: {
39
+ transition: "all 200ms ease-in-out",
40
+ _before: {
41
+ transitionProperty: "height",
42
+ transitionDuration: "200ms",
43
+ transitionTimingFunction: "ease-in-out"
44
+ },
45
+ _after: {
46
+ transitionProperty: "height",
47
+ transitionDuration: "200ms",
48
+ transitionTimingFunction: "ease-in-out"
49
+ }
50
+ },
51
+ _before: {
52
+ bgColor: "action.border.initial",
53
+ bottom: "0",
54
+ content: '""',
55
+ h: "0",
56
+ position: "absolute",
57
+ left: "0",
58
+ right: "0",
59
+ w: "full",
60
+ willChange: "height",
61
+ zIndex: "decorator"
62
+ },
63
+ _after: {
64
+ borderTopLeftRadius: "md",
65
+ borderTopRightRadius: "md",
66
+ bottom: "0",
67
+ bgColor: "neutral.surface.100",
68
+ content: '""',
69
+ left: "0",
70
+ position: "absolute",
71
+ right: "0",
72
+ h: "0",
73
+ w: "full",
74
+ willChange: "height",
75
+ zIndex: "-1"
76
+ },
77
+ _hover: {
78
+ _after: {
79
+ h: "full"
80
+ }
81
+ },
82
+ _focusVisible: {
83
+ boxShadow: "none",
84
+ outline: "3px solid",
85
+ outlineColor: "action.border.focus",
86
+ outlineOffset: "2px"
87
+ },
88
+ _disabled: {
89
+ cursor: "not-allowed",
90
+ opacity: "0.5"
91
+ },
92
+ _selected: {
93
+ color: "action.text.200",
94
+ _before: {
95
+ h: "3px"
96
+ },
97
+ _hover: {
98
+ _after: {
99
+ h: "0"
100
+ }
101
+ }
102
+ }
103
+ });
104
+
105
+ export {
106
+ Tab
107
+ };
108
+ //# sourceMappingURL=chunk-AMFL3PZV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/Tab.tsx"],"sourcesContent":["'use client'\n\nimport { useMemo, type ButtonHTMLAttributes, type MouseEvent } from 'react'\nimport { useTabsContext } from '../context/tabs'\nimport { css, cx } from '@cerberus/styled-system/css'\n\n/**\n * This module provides a Tab component.\n * @module\n */\n\nexport interface TabProps extends ButtonHTMLAttributes<HTMLButtonElement> {\n id: string\n controls: string\n value: string\n}\n\n/**\n * The Tab component provides a tab element to be used in a TabList.\n * @definition [ARIA Target Size](https://www.w3.org/WAI/WCAG21/Understanding/target-size.html#:~:text=Understanding%20SC%202.5.,%3ATarget%20Size%20(Level%20AAA)&text=The%20size%20of%20the%20target,Equivalent)\n * @definition [Tab docs](https://cerberus.digitalu.design/react/tabs)\n * @param id - the id of the tab (used for aria-labelledby in the panel)\n * @param controls - the id of the tab panel that the tab controls\n * @param value - the id of the tab that will be tracked as the active tab\n * @example\n * ```tsx\n * <Tab controls=\"panel:overview\" value=\"overview\">\n * Overview\n * </Tab>\n * ```\n */\nexport function Tab(props: TabProps) {\n const { controls, value, ...nativeProps } = props\n const { active, onTabUpdate } = useTabsContext()\n const isActive = useMemo(() => active === value, [active, value])\n\n function handleClick(e: MouseEvent<HTMLButtonElement>) {\n props.onClick?.(e)\n onTabUpdate(e.currentTarget.value)\n }\n\n return (\n <button\n {...nativeProps}\n {...(!isActive && { tabIndex: -1 })}\n aria-controls={controls}\n aria-selected={isActive}\n className={cx(nativeProps.className, btnStyles)}\n onClick={handleClick}\n role=\"tab\"\n value={value}\n />\n )\n}\n\nconst btnStyles = css({\n fontSize: 'sm',\n fontWeight: '600',\n h: '2.75rem',\n position: 'relative',\n pxi: '4',\n zIndex: 'base',\n _motionSafe: {\n transition: 'all 200ms ease-in-out',\n _before: {\n transitionProperty: 'height',\n transitionDuration: '200ms',\n transitionTimingFunction: 'ease-in-out',\n },\n _after: {\n transitionProperty: 'height',\n transitionDuration: '200ms',\n transitionTimingFunction: 'ease-in-out',\n },\n },\n _before: {\n bgColor: 'action.border.initial',\n bottom: '0',\n content: '\"\"',\n h: '0',\n position: 'absolute',\n left: '0',\n right: '0',\n w: 'full',\n willChange: 'height',\n zIndex: 'decorator',\n },\n _after: {\n borderTopLeftRadius: 'md',\n borderTopRightRadius: 'md',\n bottom: '0',\n bgColor: 'neutral.surface.100',\n content: '\"\"',\n left: '0',\n position: 'absolute',\n right: '0',\n h: '0',\n w: 'full',\n willChange: 'height',\n zIndex: '-1',\n },\n _hover: {\n _after: {\n h: 'full',\n },\n },\n _focusVisible: {\n boxShadow: 'none',\n outline: '3px solid',\n outlineColor: 'action.border.focus',\n outlineOffset: '2px',\n },\n _disabled: {\n cursor: 'not-allowed',\n opacity: '0.5',\n },\n _selected: {\n color: 'action.text.200',\n _before: {\n h: '3px',\n },\n _hover: {\n _after: {\n h: '0',\n },\n },\n },\n})\n"],"mappings":";;;;;AAEA,SAAS,eAA2D;AAEpE,SAAS,KAAK,UAAU;AAsCpB;AAXG,SAAS,IAAI,OAAiB;AACnC,QAAM,EAAE,UAAU,OAAO,GAAG,YAAY,IAAI;AAC5C,QAAM,EAAE,QAAQ,YAAY,IAAI,eAAe;AAC/C,QAAM,WAAW,QAAQ,MAAM,WAAW,OAAO,CAAC,QAAQ,KAAK,CAAC;AAEhE,WAAS,YAAY,GAAkC;AACrD,UAAM,UAAU,CAAC;AACjB,gBAAY,EAAE,cAAc,KAAK;AAAA,EACnC;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACH,GAAI,CAAC,YAAY,EAAE,UAAU,GAAG;AAAA,MACjC,iBAAe;AAAA,MACf,iBAAe;AAAA,MACf,WAAW,GAAG,YAAY,WAAW,SAAS;AAAA,MAC9C,SAAS;AAAA,MACT,MAAK;AAAA,MACL;AAAA;AAAA,EACF;AAEJ;AAEA,IAAM,YAAY,IAAI;AAAA,EACpB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,GAAG;AAAA,EACH,UAAU;AAAA,EACV,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,aAAa;AAAA,IACX,YAAY;AAAA,IACZ,SAAS;AAAA,MACP,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,0BAA0B;AAAA,IAC5B;AAAA,IACA,QAAQ;AAAA,MACN,oBAAoB;AAAA,MACpB,oBAAoB;AAAA,MACpB,0BAA0B;AAAA,IAC5B;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,GAAG;AAAA,IACH,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,IACV,OAAO;AAAA,IACP,GAAG;AAAA,IACH,GAAG;AAAA,IACH,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,IACN,QAAQ;AAAA,MACN,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EACA,eAAe;AAAA,IACb,WAAW;AAAA,IACX,SAAS;AAAA,IACT,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AAAA,EACA,WAAW;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAAA,EACA,WAAW;AAAA,IACT,OAAO;AAAA,IACP,SAAS;AAAA,MACP,GAAG;AAAA,IACL;AAAA,IACA,QAAQ;AAAA,MACN,QAAQ;AAAA,QACN,GAAG;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF,CAAC;","names":[]}
@@ -0,0 +1,28 @@
1
+ // src/components/TabList.tsx
2
+ import { cx } from "@cerberus/styled-system/css";
3
+ import { hstack } from "@cerberus/styled-system/patterns";
4
+ import { jsx } from "react/jsx-runtime";
5
+ function TabList(props) {
6
+ const { description, ...nativeProps } = props;
7
+ return /* @__PURE__ */ jsx(
8
+ "div",
9
+ {
10
+ ...nativeProps,
11
+ "aria-describedby": description,
12
+ className: cx(
13
+ nativeProps.className,
14
+ hstack({
15
+ borderBottom: "1px solid",
16
+ borderBottomColor: "action.border.100",
17
+ gap: "0",
18
+ w: "full"
19
+ })
20
+ )
21
+ }
22
+ );
23
+ }
24
+
25
+ export {
26
+ TabList
27
+ };
28
+ //# sourceMappingURL=chunk-BVILNJ6M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/TabList.tsx"],"sourcesContent":["import { cx } from '@cerberus/styled-system/css'\nimport { hstack } from '@cerberus/styled-system/patterns'\nimport type { HTMLAttributes, PropsWithChildren } from 'react'\n\n/**\n * This module provides a TabList component.\n * @module\n */\n\nexport interface TabListProps extends HTMLAttributes<HTMLDivElement> {\n description?: string\n}\n\n/**\n * The TabList component provides a container for tab elements.\n * @param description - a description of what the tab list contains\n * @example\n * ```tsx\n * <TabList description=\"Button details\">\n * <Tab id=\"overview\">Overview</Tab>\n * <Tab id=\"guidelines\">Guidelines</Tab>\n * </TabList>\n * ```\n */\nexport function TabList(props: PropsWithChildren<TabListProps>) {\n const { description, ...nativeProps } = props\n return (\n <div\n {...nativeProps}\n aria-describedby={description}\n className={cx(\n nativeProps.className,\n hstack({\n borderBottom: '1px solid',\n borderBottomColor: 'action.border.100',\n gap: '0',\n w: 'full',\n }),\n )}\n />\n )\n}\n"],"mappings":";AAAA,SAAS,UAAU;AACnB,SAAS,cAAc;AA0BnB;AAHG,SAAS,QAAQ,OAAwC;AAC9D,QAAM,EAAE,aAAa,GAAG,YAAY,IAAI;AACxC,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ,oBAAkB;AAAA,MAClB,WAAW;AAAA,QACT,YAAY;AAAA,QACZ,OAAO;AAAA,UACL,cAAc;AAAA,UACd,mBAAmB;AAAA,UACnB,KAAK;AAAA,UACL,GAAG;AAAA,QACL,CAAC;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -0,0 +1,31 @@
1
+ import {
2
+ useTabsContext
3
+ } from "./chunk-24B4KIPX.js";
4
+ import {
5
+ Show
6
+ } from "./chunk-R4H3352X.js";
7
+
8
+ // src/components/TabPanel.tsx
9
+ import { css, cx } from "@cerberus/styled-system/css";
10
+ import { useMemo } from "react";
11
+ import { jsx } from "react/jsx-runtime";
12
+ function TabPanel(props) {
13
+ const { tab, ...nativeProps } = props;
14
+ const { active } = useTabsContext();
15
+ const isActive = useMemo(() => active === tab, [active, tab]);
16
+ return /* @__PURE__ */ jsx(Show, { when: isActive, children: /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ ...nativeProps,
20
+ ...isActive && { tabIndex: 0 },
21
+ "aria-labelledby": tab,
22
+ className: cx(nativeProps.className, css()),
23
+ role: "tabpanel"
24
+ }
25
+ ) });
26
+ }
27
+
28
+ export {
29
+ TabPanel
30
+ };
31
+ //# sourceMappingURL=chunk-UI7OR6PG.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/components/TabPanel.tsx"],"sourcesContent":["'use client'\n\nimport { css, cx } from '@cerberus/styled-system/css'\nimport { useMemo, type HTMLAttributes } from 'react'\nimport { useTabsContext } from '../context/tabs'\nimport { Show } from './Show'\n\n/**\n * This module provides a TabPanel component.\n * @module\n */\n\nexport interface TabPanelProps extends HTMLAttributes<HTMLDivElement> {\n id: string\n tab: string\n}\n\n/**\n * The TabPanel component provides a panel element to be used in a Tabs provider.\n * @param id - the id of the tab panel which is used for the Tab's control prop\n * @param tab - the id of the tab that will be tracked as the active tab\n * @example\n * ```tsx\n * <TabPanel id=\"panel:overview\" tab=\"overview\">\n * Overview content\n * </TabPanel>\n * ```\n */\nexport function TabPanel(props: TabPanelProps) {\n const { tab, ...nativeProps } = props\n const { active } = useTabsContext()\n const isActive = useMemo(() => active === tab, [active, tab])\n\n return (\n <Show when={isActive}>\n <div\n {...nativeProps}\n {...(isActive && { tabIndex: 0 })}\n aria-labelledby={tab}\n className={cx(nativeProps.className, css())}\n role=\"tabpanel\"\n />\n </Show>\n )\n}\n"],"mappings":";;;;;;;;AAEA,SAAS,KAAK,UAAU;AACxB,SAAS,eAAoC;AAgCvC;AAPC,SAAS,SAAS,OAAsB;AAC7C,QAAM,EAAE,KAAK,GAAG,YAAY,IAAI;AAChC,QAAM,EAAE,OAAO,IAAI,eAAe;AAClC,QAAM,WAAW,QAAQ,MAAM,WAAW,KAAK,CAAC,QAAQ,GAAG,CAAC;AAE5D,SACE,oBAAC,QAAK,MAAM,UACV;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACH,GAAI,YAAY,EAAE,UAAU,EAAE;AAAA,MAC/B,mBAAiB;AAAA,MACjB,WAAW,GAAG,YAAY,WAAW,IAAI,CAAC;AAAA,MAC1C,MAAK;AAAA;AAAA,EACP,GACF;AAEJ;","names":[]}
@@ -0,0 +1,2 @@
1
+ export { Tab_alias_1 as Tab } from '../_tsup-dts-rollup';
2
+ export { TabProps_alias_1 as TabProps } from '../_tsup-dts-rollup';
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import {
3
+ Tab
4
+ } from "../chunk-AMFL3PZV.js";
5
+ import "../chunk-24B4KIPX.js";
6
+ export {
7
+ Tab
8
+ };
9
+ //# sourceMappingURL=Tab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export { TabList_alias_1 as TabList } from '../_tsup-dts-rollup';
2
+ export { TabListProps_alias_1 as TabListProps } from '../_tsup-dts-rollup';
@@ -0,0 +1,7 @@
1
+ import {
2
+ TabList
3
+ } from "../chunk-BVILNJ6M.js";
4
+ export {
5
+ TabList
6
+ };
7
+ //# sourceMappingURL=TabList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,2 @@
1
+ export { TabPanel_alias_1 as TabPanel } from '../_tsup-dts-rollup';
2
+ export { TabPanelProps_alias_1 as TabPanelProps } from '../_tsup-dts-rollup';
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import {
3
+ TabPanel
4
+ } from "../chunk-UI7OR6PG.js";
5
+ import "../chunk-24B4KIPX.js";
6
+ import "../chunk-R4H3352X.js";
7
+ export {
8
+ TabPanel
9
+ };
10
+ //# sourceMappingURL=TabPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,4 @@
1
+ export { Tabs_alias_1 as Tabs } from '../_tsup-dts-rollup';
2
+ export { useTabsContext_alias_1 as useTabsContext } from '../_tsup-dts-rollup';
3
+ export { TabsContextValue_alias_1 as TabsContextValue } from '../_tsup-dts-rollup';
4
+ export { TabsProps_alias_1 as TabsProps } from '../_tsup-dts-rollup';
@@ -0,0 +1,10 @@
1
+ "use client";
2
+ import {
3
+ Tabs,
4
+ useTabsContext
5
+ } from "../chunk-24B4KIPX.js";
6
+ export {
7
+ Tabs,
8
+ useTabsContext
9
+ };
10
+ //# sourceMappingURL=tabs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -16,6 +16,12 @@ export { NavMenuList } from './_tsup-dts-rollup';
16
16
  export { NavMenuListProps } from './_tsup-dts-rollup';
17
17
  export { NavMenuLink } from './_tsup-dts-rollup';
18
18
  export { NavMenuLinkProps } from './_tsup-dts-rollup';
19
+ export { Tab } from './_tsup-dts-rollup';
20
+ export { TabProps } from './_tsup-dts-rollup';
21
+ export { TabList } from './_tsup-dts-rollup';
22
+ export { TabListProps } from './_tsup-dts-rollup';
23
+ export { TabPanel } from './_tsup-dts-rollup';
24
+ export { TabPanelProps } from './_tsup-dts-rollup';
19
25
  export { Show } from './_tsup-dts-rollup';
20
26
  export { ShowProps } from './_tsup-dts-rollup';
21
27
  export { Field } from './_tsup-dts-rollup';
@@ -26,6 +32,10 @@ export { useNavMenuContext } from './_tsup-dts-rollup';
26
32
  export { NavTriggerRef } from './_tsup-dts-rollup';
27
33
  export { NavMenuRef } from './_tsup-dts-rollup';
28
34
  export { NavMenuContextValue } from './_tsup-dts-rollup';
35
+ export { Tabs } from './_tsup-dts-rollup';
36
+ export { useTabsContext } from './_tsup-dts-rollup';
37
+ export { TabsContextValue } from './_tsup-dts-rollup';
38
+ export { TabsProps } from './_tsup-dts-rollup';
29
39
  export { ThemeProvider } from './_tsup-dts-rollup';
30
40
  export { useThemeContext } from './_tsup-dts-rollup';
31
41
  export { DefaultThemes } from './_tsup-dts-rollup';
@@ -15,6 +15,19 @@ import {
15
15
  NavMenu,
16
16
  useNavMenuContext
17
17
  } from "./chunk-KJUCHZHV.js";
18
+ import {
19
+ Tab
20
+ } from "./chunk-AMFL3PZV.js";
21
+ import {
22
+ TabList
23
+ } from "./chunk-BVILNJ6M.js";
24
+ import {
25
+ TabPanel
26
+ } from "./chunk-UI7OR6PG.js";
27
+ import {
28
+ Tabs,
29
+ useTabsContext
30
+ } from "./chunk-24B4KIPX.js";
18
31
  import "./chunk-55J6XMHW.js";
19
32
  import {
20
33
  createNavTriggerProps
@@ -59,11 +72,16 @@ export {
59
72
  NavMenuTrigger,
60
73
  Show,
61
74
  THEME_KEY,
75
+ Tab,
76
+ TabList,
77
+ TabPanel,
78
+ Tabs,
62
79
  ThemeProvider,
63
80
  createNavTriggerProps,
64
81
  getPosition,
65
82
  useFieldContext,
66
83
  useNavMenuContext,
84
+ useTabsContext,
67
85
  useTheme,
68
86
  useThemeContext
69
87
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cerberus-design/react",
3
- "version": "0.2.0-next-ae70f9a",
3
+ "version": "0.2.0-next-87c3df1",
4
4
  "description": "The Cerberus Design React component library.",
5
5
  "browserslist": "> 0.25%, not dead",
6
6
  "sideEffects": false,
@@ -0,0 +1,128 @@
1
+ 'use client'
2
+
3
+ import { useMemo, type ButtonHTMLAttributes, type MouseEvent } from 'react'
4
+ import { useTabsContext } from '../context/tabs'
5
+ import { css, cx } from '@cerberus/styled-system/css'
6
+
7
+ /**
8
+ * This module provides a Tab component.
9
+ * @module
10
+ */
11
+
12
+ export interface TabProps extends ButtonHTMLAttributes<HTMLButtonElement> {
13
+ id: string
14
+ controls: string
15
+ value: string
16
+ }
17
+
18
+ /**
19
+ * The Tab component provides a tab element to be used in a TabList.
20
+ * @definition [ARIA Target Size](https://www.w3.org/WAI/WCAG21/Understanding/target-size.html#:~:text=Understanding%20SC%202.5.,%3ATarget%20Size%20(Level%20AAA)&text=The%20size%20of%20the%20target,Equivalent)
21
+ * @definition [Tab docs](https://cerberus.digitalu.design/react/tabs)
22
+ * @param id - the id of the tab (used for aria-labelledby in the panel)
23
+ * @param controls - the id of the tab panel that the tab controls
24
+ * @param value - the id of the tab that will be tracked as the active tab
25
+ * @example
26
+ * ```tsx
27
+ * <Tab controls="panel:overview" value="overview">
28
+ * Overview
29
+ * </Tab>
30
+ * ```
31
+ */
32
+ export function Tab(props: TabProps) {
33
+ const { controls, value, ...nativeProps } = props
34
+ const { active, onTabUpdate } = useTabsContext()
35
+ const isActive = useMemo(() => active === value, [active, value])
36
+
37
+ function handleClick(e: MouseEvent<HTMLButtonElement>) {
38
+ props.onClick?.(e)
39
+ onTabUpdate(e.currentTarget.value)
40
+ }
41
+
42
+ return (
43
+ <button
44
+ {...nativeProps}
45
+ {...(!isActive && { tabIndex: -1 })}
46
+ aria-controls={controls}
47
+ aria-selected={isActive}
48
+ className={cx(nativeProps.className, btnStyles)}
49
+ onClick={handleClick}
50
+ role="tab"
51
+ value={value}
52
+ />
53
+ )
54
+ }
55
+
56
+ const btnStyles = css({
57
+ fontSize: 'sm',
58
+ fontWeight: '600',
59
+ h: '2.75rem',
60
+ position: 'relative',
61
+ pxi: '4',
62
+ zIndex: 'base',
63
+ _motionSafe: {
64
+ transition: 'all 200ms ease-in-out',
65
+ _before: {
66
+ transitionProperty: 'height',
67
+ transitionDuration: '200ms',
68
+ transitionTimingFunction: 'ease-in-out',
69
+ },
70
+ _after: {
71
+ transitionProperty: 'height',
72
+ transitionDuration: '200ms',
73
+ transitionTimingFunction: 'ease-in-out',
74
+ },
75
+ },
76
+ _before: {
77
+ bgColor: 'action.border.initial',
78
+ bottom: '0',
79
+ content: '""',
80
+ h: '0',
81
+ position: 'absolute',
82
+ left: '0',
83
+ right: '0',
84
+ w: 'full',
85
+ willChange: 'height',
86
+ zIndex: 'decorator',
87
+ },
88
+ _after: {
89
+ borderTopLeftRadius: 'md',
90
+ borderTopRightRadius: 'md',
91
+ bottom: '0',
92
+ bgColor: 'neutral.surface.100',
93
+ content: '""',
94
+ left: '0',
95
+ position: 'absolute',
96
+ right: '0',
97
+ h: '0',
98
+ w: 'full',
99
+ willChange: 'height',
100
+ zIndex: '-1',
101
+ },
102
+ _hover: {
103
+ _after: {
104
+ h: 'full',
105
+ },
106
+ },
107
+ _focusVisible: {
108
+ boxShadow: 'none',
109
+ outline: '3px solid',
110
+ outlineColor: 'action.border.focus',
111
+ outlineOffset: '2px',
112
+ },
113
+ _disabled: {
114
+ cursor: 'not-allowed',
115
+ opacity: '0.5',
116
+ },
117
+ _selected: {
118
+ color: 'action.text.200',
119
+ _before: {
120
+ h: '3px',
121
+ },
122
+ _hover: {
123
+ _after: {
124
+ h: '0',
125
+ },
126
+ },
127
+ },
128
+ })
@@ -0,0 +1,42 @@
1
+ import { cx } from '@cerberus/styled-system/css'
2
+ import { hstack } from '@cerberus/styled-system/patterns'
3
+ import type { HTMLAttributes, PropsWithChildren } from 'react'
4
+
5
+ /**
6
+ * This module provides a TabList component.
7
+ * @module
8
+ */
9
+
10
+ export interface TabListProps extends HTMLAttributes<HTMLDivElement> {
11
+ description?: string
12
+ }
13
+
14
+ /**
15
+ * The TabList component provides a container for tab elements.
16
+ * @param description - a description of what the tab list contains
17
+ * @example
18
+ * ```tsx
19
+ * <TabList description="Button details">
20
+ * <Tab id="overview">Overview</Tab>
21
+ * <Tab id="guidelines">Guidelines</Tab>
22
+ * </TabList>
23
+ * ```
24
+ */
25
+ export function TabList(props: PropsWithChildren<TabListProps>) {
26
+ const { description, ...nativeProps } = props
27
+ return (
28
+ <div
29
+ {...nativeProps}
30
+ aria-describedby={description}
31
+ className={cx(
32
+ nativeProps.className,
33
+ hstack({
34
+ borderBottom: '1px solid',
35
+ borderBottomColor: 'action.border.100',
36
+ gap: '0',
37
+ w: 'full',
38
+ }),
39
+ )}
40
+ />
41
+ )
42
+ }
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+
3
+ import { css, cx } from '@cerberus/styled-system/css'
4
+ import { useMemo, type HTMLAttributes } from 'react'
5
+ import { useTabsContext } from '../context/tabs'
6
+ import { Show } from './Show'
7
+
8
+ /**
9
+ * This module provides a TabPanel component.
10
+ * @module
11
+ */
12
+
13
+ export interface TabPanelProps extends HTMLAttributes<HTMLDivElement> {
14
+ id: string
15
+ tab: string
16
+ }
17
+
18
+ /**
19
+ * The TabPanel component provides a panel element to be used in a Tabs provider.
20
+ * @param id - the id of the tab panel which is used for the Tab's control prop
21
+ * @param tab - the id of the tab that will be tracked as the active tab
22
+ * @example
23
+ * ```tsx
24
+ * <TabPanel id="panel:overview" tab="overview">
25
+ * Overview content
26
+ * </TabPanel>
27
+ * ```
28
+ */
29
+ export function TabPanel(props: TabPanelProps) {
30
+ const { tab, ...nativeProps } = props
31
+ const { active } = useTabsContext()
32
+ const isActive = useMemo(() => active === tab, [active, tab])
33
+
34
+ return (
35
+ <Show when={isActive}>
36
+ <div
37
+ {...nativeProps}
38
+ {...(isActive && { tabIndex: 0 })}
39
+ aria-labelledby={tab}
40
+ className={cx(nativeProps.className, css())}
41
+ role="tabpanel"
42
+ />
43
+ </Show>
44
+ )
45
+ }