@growth-angels/ds-core 1.2.1 → 1.3.0

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.
@@ -0,0 +1,2 @@
1
+ import { TabsProps } from "./Tabs.types";
2
+ export declare const Tabs: ({ tabs, children, extraClassNames, edit }: TabsProps) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useReactAdapter } from "../../hooks/useReactAdaptater";
3
+ export const Tabs = ({ tabs, children, extraClassNames, edit }) => {
4
+ const { useEffect, useState, useRef, Children, Fragment } = useReactAdapter();
5
+ console.log(edit);
6
+ const [activeTab, setActiveTab] = useState(tabs[0]?.id || "");
7
+ const tabsRef = useRef([]);
8
+ useEffect(() => {
9
+ const activeIndex = tabs.findIndex((tab) => tab.id === activeTab);
10
+ tabsRef.current[activeIndex]?.focus();
11
+ }, [activeTab, tabs]);
12
+ const classes = ["ga-ds-tabs"];
13
+ if (extraClassNames) {
14
+ classes.push(...extraClassNames);
15
+ }
16
+ return (_jsxs("div", { className: classes.join(" "), children: [_jsx("div", { className: "ga-ds-tabs__list", role: "tablist", children: tabs.map((tab, index) => (_jsx("button", { ref: (el) => (tabsRef.current[index] = el), role: "tab", "aria-selected": activeTab === tab.id, "aria-controls": `ga-ds-tabpanel-${tab.id}`, id: `ga-ds-tab-${tab.id}`, tabIndex: activeTab === tab.id ? 0 : -1, className: `ga-ds-tabs__tab ${activeTab === tab.id ? "ga-ds-tabs__tab--active" : ""}`, onClick: () => setActiveTab(tab.id), children: tab.label }, tab.id))) }), _jsx("div", { className: "ga-ds-tabs__panels", children: !edit
17
+ ? Children.toArray(children).map((child) => (_jsx("div", { className: ["ga-ds-tabs__panel", activeTab === child.props.id ? "ga-ds-tabs__panel--active" : ""].join(" "), children: _jsx("div", { role: "tabpanel", id: `ga-ds-tabpanel-${child.props.id}`, "aria-labelledby": `ga-ds-tab-${child.props.id}`, children: child }) }, child.props.id)))
18
+ : children })] }));
19
+ };
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { Tabs } from "./Tabs";
3
+ declare const meta: Meta<typeof Tabs>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof Tabs>;
6
+ export declare const Primary: Story;
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tabs } from "./Tabs";
3
+ const meta = {
4
+ title: "Organisms/Tabs",
5
+ component: Tabs,
6
+ tags: ["autodocs"],
7
+ };
8
+ export default meta;
9
+ const ids = Array.from({ length: 3 }, () => crypto.randomUUID());
10
+ export const Primary = {
11
+ args: {
12
+ tabs: [
13
+ { id: ids[0], label: "Tab 1" },
14
+ { id: ids[1], label: "Tab 2" },
15
+ { id: ids[2], label: "Tab 3" },
16
+ ],
17
+ children: [
18
+ _jsx("div", { id: ids[0], children: "Content for Tab 1" }),
19
+ _jsx("div", { id: ids[1], children: "Content for Tab 2" }),
20
+ _jsx("div", { id: ids[2], children: "Content for Tab 3" }),
21
+ ],
22
+ },
23
+ };
@@ -0,0 +1,9 @@
1
+ import { WordpressDefault } from "src/global.types";
2
+ export interface TabsProps extends WordpressDefault {
3
+ tabs: Array<{
4
+ id: string;
5
+ label: string;
6
+ }>;
7
+ edit?: boolean;
8
+ children: React.ReactNode;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -2,3 +2,5 @@ export * from './Card/Card';
2
2
  export * from './Card/Card.types';
3
3
  export * from './Carousel/Carousel';
4
4
  export * from './SpoilerList/SpoilerList';
5
+ export * from './Tabs/Tabs';
6
+ export * from './Tabs/Tabs.types';
@@ -2,3 +2,5 @@ export * from './Card/Card';
2
2
  export * from './Card/Card.types';
3
3
  export * from './Carousel/Carousel';
4
4
  export * from './SpoilerList/SpoilerList';
5
+ export * from './Tabs/Tabs';
6
+ export * from './Tabs/Tabs.types';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-angels/ds-core",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "Design system by Growth Angels",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -0,0 +1,28 @@
1
+ .ga-ds-tabs {
2
+ outline: 1px solid red;
3
+ $this: &;
4
+ &__list {
5
+ display: flex;
6
+
7
+ #{$this}__tab {
8
+ background: none;
9
+ border: none;
10
+ font-size: inherit;
11
+ padding: inherit;
12
+ }
13
+ }
14
+
15
+ &__panel {
16
+ height: 0;
17
+ visibility: hidden;
18
+ overflow: hidden;
19
+ clip-path: inset(100% 0 0 0);
20
+
21
+ &--active {
22
+ height: auto;
23
+ visibility: visible;
24
+ overflow: visible;
25
+ clip-path: none;
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,26 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite"
2
+ import { Tabs } from "./Tabs"
3
+
4
+ const meta: Meta<typeof Tabs> = {
5
+ title: "Organisms/Tabs",
6
+ component: Tabs,
7
+ tags: ["autodocs"],
8
+ }
9
+ export default meta
10
+ type Story = StoryObj<typeof Tabs>
11
+
12
+ const ids = Array.from({ length: 3 }, () => crypto.randomUUID())
13
+ export const Primary: Story = {
14
+ args: {
15
+ tabs: [
16
+ { id: ids[0], label: "Tab 1" },
17
+ { id: ids[1], label: "Tab 2" },
18
+ { id: ids[2], label: "Tab 3" },
19
+ ],
20
+ children: [
21
+ <div id={ids[0]}>Content for Tab 1</div>,
22
+ <div id={ids[1]}>Content for Tab 2</div>,
23
+ <div id={ids[2]}>Content for Tab 3</div>,
24
+ ],
25
+ },
26
+ }
@@ -0,0 +1,53 @@
1
+ import { useReactAdapter } from "../../hooks/useReactAdaptater"
2
+ import { TabsProps } from "./Tabs.types"
3
+ export const Tabs = ({ tabs, children, extraClassNames, edit }: TabsProps) => {
4
+ const { useEffect, useState, useRef, Children, Fragment } = useReactAdapter()
5
+ console.log(edit)
6
+ const [activeTab, setActiveTab] = useState(tabs[0]?.id || "")
7
+ const tabsRef = useRef<Array<HTMLButtonElement | null>>([])
8
+
9
+ useEffect(() => {
10
+ const activeIndex = tabs.findIndex((tab) => tab.id === activeTab)
11
+ tabsRef.current[activeIndex]?.focus()
12
+ }, [activeTab, tabs])
13
+
14
+ const classes = ["ga-ds-tabs"]
15
+ if (extraClassNames) {
16
+ classes.push(...extraClassNames)
17
+ }
18
+ return (
19
+ <div className={classes.join(" ")}>
20
+ <div className="ga-ds-tabs__list" role="tablist">
21
+ {tabs.map((tab, index) => (
22
+ <button
23
+ key={tab.id}
24
+ ref={(el) => (tabsRef.current[index] = el)}
25
+ role="tab"
26
+ aria-selected={activeTab === tab.id}
27
+ aria-controls={`ga-ds-tabpanel-${tab.id}`}
28
+ id={`ga-ds-tab-${tab.id}`}
29
+ tabIndex={activeTab === tab.id ? 0 : -1}
30
+ className={`ga-ds-tabs__tab ${activeTab === tab.id ? "ga-ds-tabs__tab--active" : ""}`}
31
+ onClick={() => setActiveTab(tab.id)}
32
+ >
33
+ {tab.label}
34
+ </button>
35
+ ))}
36
+ </div>
37
+ <div className="ga-ds-tabs__panels">
38
+ {!edit
39
+ ? Children.toArray(children).map((child: any) => (
40
+ <div
41
+ key={child.props.id}
42
+ className={["ga-ds-tabs__panel", activeTab === child.props.id ? "ga-ds-tabs__panel--active" : ""].join(" ")}
43
+ >
44
+ <div role="tabpanel" id={`ga-ds-tabpanel-${child.props.id}`} aria-labelledby={`ga-ds-tab-${child.props.id}`}>
45
+ {child}
46
+ </div>
47
+ </div>
48
+ ))
49
+ : children}
50
+ </div>
51
+ </div>
52
+ )
53
+ }
@@ -0,0 +1,10 @@
1
+ import { WordpressDefault } from "src/global.types"
2
+
3
+ export interface TabsProps extends WordpressDefault {
4
+ tabs: Array<{
5
+ id: string
6
+ label: string
7
+ }>
8
+ edit?: boolean
9
+ children: React.ReactNode
10
+ }
@@ -1,3 +1,4 @@
1
1
  @use "./Card/Card.scss";
2
2
  @use "./Carousel/Carousel.scss";
3
3
  @use "./SpoilerList/SpoilerList.scss";
4
+ @use "./Tabs/Tabs.scss";
@@ -1,4 +1,6 @@
1
1
  export * from './Card/Card'
2
2
  export * from './Card/Card.types'
3
3
  export * from './Carousel/Carousel'
4
- export * from './SpoilerList/SpoilerList'
4
+ export * from './SpoilerList/SpoilerList'
5
+ export * from './Tabs/Tabs'
6
+ export * from './Tabs/Tabs.types'