atomsystem 0.1.48 → 0.1.50

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 (69) hide show
  1. package/README.md +147 -55
  2. package/atom.design.md +155 -0
  3. package/atom.uxPattern.md +431 -0
  4. package/components/ui/Badge.tsx +20 -0
  5. package/components/ui/Button.tsx +33 -0
  6. package/components/ui/Card.tsx +20 -0
  7. package/components/ui/Input.tsx +35 -0
  8. package/components/ui/Modal.tsx +54 -0
  9. package/components/ui/index.ts +5 -0
  10. package/css/atom-ui.css +216 -0
  11. package/dist/cli.cjs +105 -0
  12. package/dist/cli.cjs.map +1 -0
  13. package/dist/cli.d.cts +1 -0
  14. package/dist/cli.d.ts +1 -0
  15. package/dist/cli.js +97 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/index.cjs +7897 -0
  18. package/dist/index.cjs.map +1 -0
  19. package/dist/index.d.cts +218 -0
  20. package/dist/index.d.ts +218 -0
  21. package/dist/index.js +7845 -451
  22. package/dist/index.js.map +1 -0
  23. package/package.json +120 -81
  24. package/presets/default.design.md +155 -0
  25. package/presets/uxPattern.md +431 -0
  26. package/skills/atomsystem.skill.md +104 -0
  27. package/tokens/token.json +319 -0
  28. package/tokens/tokens.json +318 -976
  29. package/app/templates/Animations/Animation.tsx +0 -282
  30. package/app/templates/Badge/Badge.tsx +0 -28
  31. package/app/templates/Badge/badge.css +0 -28
  32. package/app/templates/Button/Button.tsx +0 -31
  33. package/app/templates/Button/button.css +0 -135
  34. package/app/templates/Card/Card.tsx +0 -50
  35. package/app/templates/Card/card.css +0 -17
  36. package/app/templates/Checkbox/Checkbox.tsx +0 -55
  37. package/app/templates/Checkbox/checkbox.css +0 -38
  38. package/app/templates/CodeBlock/CodeBlock.tsx +0 -68
  39. package/app/templates/Collapse/Collapse.tsx +0 -207
  40. package/app/templates/Collapse/collapse.css +0 -24
  41. package/app/templates/Dropdown/Dropdown.css +0 -112
  42. package/app/templates/Dropdown/Dropdown.tsx +0 -103
  43. package/app/templates/Input/Input.tsx +0 -29
  44. package/app/templates/Input/input.css +0 -24
  45. package/app/templates/Label/Label.tsx +0 -22
  46. package/app/templates/Modal/Modal.tsx +0 -71
  47. package/app/templates/Modal/modal.css +0 -98
  48. package/app/templates/Navigation/Navigation.tsx +0 -169
  49. package/app/templates/Navigation/navigation.css +0 -59
  50. package/app/templates/Pagination/Pagination.tsx +0 -104
  51. package/app/templates/Pagination/pagination.css +0 -66
  52. package/app/templates/Radio/Radio.tsx +0 -45
  53. package/app/templates/Radio/radio.css +0 -29
  54. package/app/templates/Select/Select.tsx +0 -143
  55. package/app/templates/Select/select.css +0 -47
  56. package/app/templates/Sidebar/Sidebar.tsx +0 -139
  57. package/app/templates/Sidebar/sidebar.css +0 -4
  58. package/app/templates/TOC/TOC.tsx +0 -165
  59. package/app/templates/Tab/Tab.tsx +0 -117
  60. package/app/templates/Tab/tab.css +0 -56
  61. package/app/templates/Table/Table.tsx +0 -54
  62. package/app/templates/Table/table.css +0 -58
  63. package/app/templates/Theme/Theme.tsx +0 -122
  64. package/app/templates/Toast/Toast.tsx +0 -106
  65. package/app/templates/Toast/toast.css +0 -69
  66. package/build/build-tokens.js +0 -223
  67. package/build/css/_variables.css +0 -251
  68. package/build/typescript/theme.ts +0 -6
  69. package/css/text.css +0 -18
@@ -1,143 +0,0 @@
1
- "use client";
2
- import { useEffect, useLayoutEffect, useRef, useState } from "react";
3
- import { createPortal } from "react-dom";
4
- import "./select.css";
5
-
6
- export const Select = ({
7
- options = [],
8
- disabled,
9
- }: {
10
- options: string[];
11
- disabled?: boolean;
12
- }) => {
13
- const [filterValue, setFilterValue] = useState("");
14
- const [isOpen, setIsOpen] = useState(false);
15
- const [menuPosition, setMenuPosition] = useState({
16
- top: 0,
17
- left: 0,
18
- width: 0,
19
- });
20
- const inputRef = useRef<HTMLInputElement>(null);
21
- const dropdownRef = useRef<HTMLUListElement>(null);
22
- const filteredOptions = options.filter((option) =>
23
- option.toLowerCase().includes(filterValue.toLowerCase())
24
- );
25
-
26
- useLayoutEffect(() => {
27
- if (isOpen && inputRef.current && dropdownRef.current) {
28
- const rect = inputRef.current.getBoundingClientRect();
29
- const dropdownRect = dropdownRef.current.getBoundingClientRect();
30
-
31
- if (Math.abs(menuPosition.width - rect.width) > 0.5) {
32
- setMenuPosition({
33
- top: rect.bottom + window.scrollY,
34
- left: rect.left,
35
- width: rect.width,
36
- });
37
- return;
38
- }
39
-
40
- let top = rect.bottom + window.scrollY;
41
-
42
- if (rect.bottom + dropdownRect.height > window.innerHeight) {
43
- top = rect.top + window.scrollY - dropdownRect.height;
44
- }
45
-
46
- setMenuPosition((prev) => {
47
- if (
48
- Math.abs(prev.top - top) < 0.5 &&
49
- Math.abs(prev.left - rect.left) < 0.5
50
- ) {
51
- return prev;
52
- }
53
- return {
54
- top,
55
- left: rect.left,
56
- width: rect.width,
57
- };
58
- });
59
- }
60
- }, [isOpen, filterValue, menuPosition.width]);
61
-
62
- useEffect(() => {
63
- const handleClickOutside = (event: MouseEvent) => {
64
- if (
65
- dropdownRef.current &&
66
- !dropdownRef.current.contains(event.target as Node) &&
67
- inputRef.current &&
68
- !inputRef.current.contains(event.target as Node)
69
- ) {
70
- setIsOpen(false);
71
- }
72
- };
73
- document.addEventListener("mousedown", handleClickOutside);
74
- return () => document.removeEventListener("mousedown", handleClickOutside);
75
- }, []);
76
-
77
- return (
78
- <div className="relative">
79
- <label className="relative w-fit hidden md:block">
80
- <input
81
- ref={inputRef}
82
- type="text"
83
- value={filterValue}
84
- placeholder="값을 선택해주세요..."
85
- onChange={(e) => {
86
- setFilterValue(e.target.value);
87
- }}
88
- onFocus={() => setIsOpen(true)}
89
- className="select hidden sm:block"
90
- disabled={disabled}
91
- />
92
- <div
93
- className="absolute flex items-center right-0 top-0 h-full px-2"
94
- >
95
- <span className="material-symbols-outlined">
96
- <span className="text-base">arrow_drop_down</span>
97
- </span>
98
- </div>
99
- </label>
100
- {isOpen &&
101
- createPortal(
102
- <ul
103
- ref={dropdownRef}
104
- className="absolute w-full select-menu"
105
- style={{
106
- top: menuPosition.top,
107
- left: menuPosition.left,
108
- width: menuPosition.width,
109
- }}
110
- >
111
- {filteredOptions.length > 0 ? (
112
- filteredOptions.map((option, index) => (
113
- <li
114
- key={index}
115
- className="select-menu-item"
116
- onClick={() => {
117
- setFilterValue(option);
118
- setIsOpen(false);
119
- }}
120
- >
121
- {option}
122
- </li>
123
- ))
124
- ) : (
125
- <li className="select-menu-item">No results</li>
126
- )}
127
- </ul>,
128
- document.body
129
- )}
130
- <select
131
- className="select block sm:hidden"
132
- >
133
- {options.map((option, index) => {
134
- return (
135
- <option key={index} value={option}>
136
- {option}
137
- </option>
138
- );
139
- })}
140
- </select>
141
- </div>
142
- );
143
- };
@@ -1,47 +0,0 @@
1
- .select{
2
- background: var(--color-bg-input-standard);
3
- border: 1px solid var(--color-border-standard);
4
- color: var(--color-text-standard);
5
- padding: var(--spacing-common-y) var(--spacing-common-x);
6
- border-radius: var(--radius-common);
7
- width: 100%;
8
- outline: none;
9
- cursor: pointer;
10
- }
11
- .select:focus{
12
- border: 1px solid var(--color-border-active);
13
- }
14
-
15
- .select:disabled{
16
- background: var(--color-bg-input-disabled);
17
- border: 1px solid var(--color-border-standard);
18
- color: var(--color-text-disabled);
19
- cursor: not-allowed;
20
- }
21
-
22
- .select-menu {
23
- border: 1px solid var(--color-border-active);
24
- border-radius: var(--radius-common);
25
- overflow:hidden;
26
- z-index: 9999;
27
- box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
28
- background: var(--color-bg-input-standard);
29
- }
30
-
31
- .select-menu .select-menu-item {
32
- background: var(--color-bg-input-standard);
33
- color: var(--color-text-standard);
34
- padding: var(--spacing-common-y) var(--spacing-common-x);
35
- cursor:pointer;
36
- list-style: none;
37
- }
38
-
39
- .select-menu .select-menu-item:hover {
40
- background: var(--color-bg-input-hover);
41
- }
42
-
43
- .select-menu .select-menu-item:active,
44
- .select-menu .select-menu-item:focus {
45
- background: var(--color-primary);
46
- color: var(--color-text-active);
47
- }
@@ -1,139 +0,0 @@
1
- "use client"
2
-
3
- import Link from "next/link";
4
- import { usePathname } from "next/navigation";
5
- import gsap from 'gsap';
6
- import { useGSAP } from '@gsap/react';
7
- import { createContext, useContext, useRef, useState } from "react";
8
-
9
- // Icons
10
- import MenuIcon from '@mui/icons-material/Menu';
11
-
12
- gsap.registerPlugin(useGSAP); // register the hook to avoid React version discrepancies
13
-
14
- // Navigation을 베이스 interface로 정의
15
- export interface Sidebar {
16
- children: React.ReactNode;
17
- minWidth?: number
18
- }
19
-
20
- export interface NavLink {
21
- children: React.ReactNode;
22
- href: string;
23
- }
24
-
25
- interface SideContext {
26
- isOpen: boolean;
27
- setToggle: (open: boolean) => void;
28
- }
29
-
30
- const SideContext = createContext<SideContext | undefined>(undefined);
31
-
32
- const useSideContext = () => {
33
- const context = useContext(SideContext);
34
- if (!context) {
35
- return { isOpen: false, setToggle: () => {} };
36
- }
37
- return context;
38
- }
39
-
40
- const SidebarProvider = ({ children }: { children: React.ReactNode }) => {
41
- const [isOpen, setIsOpen] = useState(true);
42
- const setToggle = (open: boolean) => setIsOpen(open);
43
-
44
- return (
45
- <SideContext.Provider value={{ isOpen, setToggle }}>
46
- {children}
47
- </SideContext.Provider>
48
- );
49
- };
50
-
51
- const SidebarToggle = () => {
52
- const { isOpen, setToggle } = useSideContext();
53
- return (
54
- <button className="cursor-pointer" onClick={() => setToggle(!isOpen)}><MenuIcon className="text-text-sub" sx={{fontSize: "20px"}}/></button>
55
- )
56
- }
57
-
58
- const Sidebar = ({ children, minWidth }: Sidebar) => {
59
- const { isOpen } = useSideContext();
60
- const sidebarRef = useRef<HTMLDivElement>(null);
61
-
62
- useGSAP(() => {
63
- if (sidebarRef.current) {
64
- if (isOpen) {
65
- // 열릴 때: 나타나면서 제자리로
66
- gsap.to(sidebarRef.current, {
67
- display: "flex",
68
- opacity: 1,
69
- x: 0,
70
- width: minWidth,
71
- minWidth: minWidth,
72
- duration: 0.3,
73
- ease: "power2.out"
74
- });
75
- } else {
76
- // 닫힐 때: 사라지면서 왼쪽으로, 너비도 0으로
77
- gsap.to(sidebarRef.current, {
78
- opacity: 0,
79
- x: -20,
80
- width: 0,
81
- minWidth: 0,
82
- duration: 0.3,
83
- ease: "power2.in",
84
- onComplete: () => {
85
- gsap.set(sidebarRef.current, { display: "none" });
86
- }
87
- });
88
- }
89
- }
90
- }, [isOpen]);
91
-
92
-
93
- return (
94
- <aside ref={sidebarRef} className={`nav-side flex flex-col overflow-auto h-full`} style={{ width: isOpen ? minWidth : 0, minWidth: isOpen ? minWidth : 0 }}>
95
- {children}
96
- </aside>
97
- )
98
- }
99
-
100
-
101
- const SideNavBrand = ({children, href}: NavLink) => {
102
- return (
103
- <Link href={href} className="flex items-center">{children}</Link>
104
- )
105
- }
106
-
107
- const SideNavList = ({children}: Sidebar) => {
108
- return (
109
- <ul className="nav-list flex flex-col">{children}</ul>
110
- )
111
- }
112
-
113
-
114
- const SideNavItem = ({children}: Sidebar) => {
115
- return (
116
- <li>{children}</li>
117
- )
118
- }
119
-
120
- const SideNavLink = ({children, href}: NavLink) => {
121
-
122
- const pathname = usePathname();
123
- const active = pathname === href;
124
-
125
- return (
126
- <Link href={href} className={`nav-link text-nowrap ${active ? "active" : ""}`}>{children}</Link>
127
- )
128
- }
129
-
130
-
131
- export {
132
- Sidebar,
133
- SidebarProvider,
134
- SidebarToggle,
135
- SideNavBrand,
136
- SideNavList,
137
- SideNavItem,
138
- SideNavLink
139
- }
@@ -1,4 +0,0 @@
1
- .nav-side{
2
- background-color: var(--bg-card);
3
- border-right: 1px solid var(--border-standard);
4
- }
@@ -1,165 +0,0 @@
1
- "use client";
2
- import { usePathname } from "next/navigation";
3
- import { useEffect, useState } from "react";
4
- import gsap from "gsap";
5
- import { ScrollToPlugin } from "gsap/ScrollToPlugin";
6
-
7
- if (typeof window !== "undefined") {
8
- gsap.registerPlugin(ScrollToPlugin);
9
- }
10
-
11
- type Heading = {
12
- id: string;
13
- text: string;
14
- level: number;
15
- };
16
-
17
- export default function TOC() {
18
- const [headings, setHeadings] = useState<Heading[]>([]);
19
- const [activeId, setActiveId] = useState<string>("");
20
- const [mounted, setMounted] = useState(false);
21
-
22
- const pathname = usePathname();
23
-
24
- useEffect(() => {
25
- setMounted(true);
26
- }, []);
27
-
28
- useEffect(() => {
29
- if (!mounted) return;
30
-
31
- const timer = setTimeout(() => {
32
- /**
33
- * Document에서 읽히는 h1, h2, h3 태그를 array 형태로 정의
34
- * */
35
- const headingElements = Array.from(
36
- document.querySelectorAll("h1, h2, h3")
37
- ) as HTMLHeadingElement[];
38
-
39
- const usedIds = new Set<string>();
40
- const generatedHeadings: Heading[] = headingElements.map((heading) => {
41
- let finalId = heading.id;
42
-
43
- // ID가 없거나 중복된 경우 새로 생성
44
- if (!finalId || usedIds.has(finalId)) {
45
- const baseId =
46
- heading.textContent
47
- ?.toLowerCase()
48
- .trim()
49
- .replace(/\s+/g, "-")
50
- .replace(/[^\w\-가-힣]+/g, "") || "heading";
51
-
52
- finalId = baseId;
53
- let counter = 1;
54
- while (usedIds.has(finalId)) {
55
- finalId = `${baseId}-${counter}`;
56
- counter++;
57
- }
58
- heading.id = finalId;
59
- }
60
-
61
- usedIds.add(finalId);
62
-
63
- return {
64
- id: finalId,
65
- text: heading.textContent || "",
66
- level: parseInt(heading.tagName.replace("H", "")),
67
- };
68
- });
69
-
70
- setHeadings(generatedHeadings);
71
- }, 100); // 딜레이를 약간 주어 DOM이 완전히 안정화된 후 실행
72
-
73
- return () => clearTimeout(timer);
74
- }, [pathname, mounted]); // 페이지 변경사항이 있거나 마운트된 경우 실행
75
-
76
- useEffect(() => {
77
- if (!mounted || headings.length === 0) return;
78
-
79
- const observer = new IntersectionObserver(
80
- (entries) => {
81
- const visibleEntries = entries.filter((entry) => entry.isIntersecting);
82
-
83
- if (visibleEntries.length > 0) {
84
- // 뷰포트 상단에 가장 가까운 요소를 찾아 활성화
85
- const topVisible = visibleEntries.reduce((prev, curr) =>
86
- curr.boundingClientRect.top < prev.boundingClientRect.top ? curr : prev
87
- );
88
- setActiveId(topVisible.target.id);
89
- }
90
- },
91
- {
92
- // 상단 10% ~ 20% 지점을 타겟으로 감지
93
- rootMargin: "-10% 0% -80% 0%",
94
- threshold: 0,
95
- }
96
- );
97
-
98
- headings.forEach((heading) => {
99
- const el = document.getElementById(heading.id);
100
- if (el) observer.observe(el);
101
- });
102
-
103
- return () => observer.disconnect();
104
- }, [headings, mounted]);
105
-
106
- if (!mounted) {
107
- return <nav className="space-y-2 flex flex-col min-h-[100px]" />;
108
- }
109
-
110
- return (
111
- <nav className="flex flex-col space-y-1 border-l border-border-standard ml-2 py-1">
112
- <div className="text-[10px] font-bold text-text-sub/60 uppercase tracking-widest mb-3 px-4">
113
- On this page
114
- </div>
115
- {headings.length > 0 ? (
116
- headings.map((heading, idx) => {
117
- const isActive = activeId === heading.id;
118
- return (
119
- <a
120
- key={`${heading.id}-${idx}`}
121
- href={`#${heading.id}`}
122
- style={{ paddingLeft: `${(heading.level - 1) * 12 + 16}px` }}
123
- className={`text-xs py-1.5 pr-4 border-l-2 transition-all duration-200 ease-in-out ${
124
- isActive
125
- ? "text-primary bg-primary/5 border-primary font-medium"
126
- : "text-text-sub border-transparent hover:text-primary hover:bg-primary/5 hover:border-primary/30"
127
- }`}
128
- onClick={(e) => {
129
- e.preventDefault();
130
- const element = document.getElementById(heading.id);
131
- if (element) {
132
- // GSAP scrollTo를 사용하여 부드럽게 이동
133
- // element.closest('.overflow-auto') 등을 통해 스크롤 컨테이너를 찾습니다.
134
- const container = element.closest('.overflow-auto') || window;
135
-
136
- gsap.to(container, {
137
- duration: 0.8,
138
- scrollTo: {
139
- y: element,
140
- offsetY: 80, // 상단 여백
141
- autoKill: true
142
- },
143
- ease: "power2.inOut"
144
- });
145
-
146
- // 클릭 시 즉시 활성화 상태 업데이트
147
- setActiveId(heading.id);
148
-
149
- // URL 해시 업데이트
150
- window.history.pushState(null, "", `#${heading.id}`);
151
- }
152
- }}
153
- >
154
- {heading.text}
155
- </a>
156
- );
157
- })
158
- ) : (
159
- <div className="px-4 text-[10px] text-text-sub/40 italic mt-2">
160
- 목차를 찾을 수 없습니다
161
- </div>
162
- )}
163
- </nav>
164
- );
165
- }
@@ -1,117 +0,0 @@
1
- "use client";
2
-
3
- import { useRef, useState } from "react";
4
- import gsap from "gsap";
5
- import { useGSAP } from "@gsap/react";
6
-
7
- const Tab = ({
8
- tabs,
9
- tabClass = "tab",
10
- tabNavItemClass = "tab-nav-item",
11
- tabNavItemActiveClass = "tab-nav-item-active",
12
- tabContents,
13
- tabContentClass = "tab-content",
14
- tabContentItem = "tab-content-item",
15
- expectionValue,
16
- expectionLayout,
17
- }: {
18
- /**탭 네비게이션을 정의내립니다.
19
- */
20
- tabs: Array<{
21
- /** id는 탭 메뉴의 고유 값입니다. 고유 값을 통해 Active 상태 값을 관리합니다.*/
22
- id: string;
23
- /** target은 배열로 제공되며, 타겟의 배열과 동일한 내용을 tabContent로 적용됩니다.*/
24
- target: string[];
25
- /** 탭 메뉴의 ReactNode 내용을 받습니다.*/
26
- tabItem: React.ReactNode;
27
- }>;
28
- /** 탭 메뉴의 tailwinds css 스타일 지정을 위한 class를 받습니다.*/
29
- tabClass?: string;
30
- /** 탭 메뉴의 각각의 tailwinds css 스타일 지정을 위한 class를 받습니다.*/
31
- tabNavItemClass?: string;
32
- /** 탭 메뉴의 활성화 상태의 tailwinds css 스타일 지정을 위한 class를 받습니다.*/
33
- tabNavItemActiveClass?: string;
34
- /** 탭 메뉴의 콘텐츠 값을 정의내립니다.*/
35
- tabContents: Array<{
36
- /** 고유 ID 값입니다.*/
37
- id: string;
38
- /** 태그 값으로 tabs target에서 선택된 내용만 화면에 제공됩니다.*/
39
- tag: string;
40
- /** 탭 메뉴의 콘텐츠 ReactNode 정보를 받습니다.*/
41
- content: React.ReactNode;
42
- }>;
43
- /** 탭 메뉴의 콘텐츠 레이아웃을 위한한 tailwinds css 스타일 지정을 위한 class를 받습니다. */
44
- tabContentClass?: string;
45
- /** 탭 메뉴의 콘텐츠의 각 개별 요소를 위한 tailwinds css 스타일 지정을 위한 class를 받습니다. */
46
- tabContentItem?: string;
47
- /** 예외 레이아웃을 사용할 콘텐츠의 tag값을 입력받습니다. */
48
- expectionValue?: string;
49
- /** 예외 레이아웃에 사용하기 위한 tailwinds css 스타일 지정을 위한 class를 받습니다. */
50
- expectionLayout?: string;
51
- }) => {
52
- const [activeContent, setActiveContent] = useState(tabs[0].target);
53
- const [activeTab, setActiveTab] = useState(tabs[0].id);
54
- const tabContentRef = useRef<HTMLDivElement>(null);
55
-
56
- const handleTabActive = (target: string[], id: string) => {
57
- setActiveContent(target);
58
- setActiveTab(id);
59
- };
60
-
61
- // 👇 activeContent가 변경된 이후에 실행
62
- useGSAP(() => {
63
- if (tabContentRef.current) {
64
- gsap.fromTo(
65
- tabContentRef.current.children,
66
- { y: 50, opacity: 0 },
67
- {
68
- y: 0,
69
- opacity: 1,
70
- stagger: 0.1,
71
- duration: 0.6,
72
- ease: "power4.out",
73
- }
74
- );
75
- }
76
- }, [activeContent]);
77
-
78
- return (
79
- <div className="flex flex-col w-full">
80
- <div className={tabClass}>
81
- {tabs.map((tab) => {
82
- return (
83
- <button
84
- key={tab.id}
85
- id={tab.id}
86
- onClick={() => handleTabActive(tab.target, tab.id)}
87
- className={`${tabNavItemClass} ${
88
- activeTab == tab.id
89
- ? tabNavItemActiveClass
90
- : ""
91
- }`}
92
- >
93
- {tab.tabItem}
94
- </button>
95
- );
96
- })}
97
- </div>
98
- <div ref={tabContentRef} className={tabContentClass}>
99
- {tabContents.map((tabContent) => {
100
- return activeContent.includes(tabContent.tag) ? (
101
- <div
102
- key={tabContent.id}
103
- id={tabContent.tag}
104
- className={`${tabContentItem} ${
105
- activeTab == expectionValue ? expectionLayout : ""
106
- }`}
107
- >
108
- {tabContent.content}
109
- </div>
110
- ) : null;
111
- })}
112
- </div>
113
- </div>
114
- );
115
- };
116
-
117
- export default Tab;
@@ -1,56 +0,0 @@
1
- .tab {
2
- display: flex;
3
- width: 100%;
4
- background-color: var(--color-bg-wrapper);
5
- border-bottom: 1px solid var(--color-border-standard);
6
- position: relative;
7
- z-index: 0;
8
- height: 57px;
9
- }
10
-
11
- .tab-nav-item {
12
- padding: var(--spacing-common-x);
13
- cursor: pointer;
14
- border: 1px solid transparent; /* reserve space for active state border */
15
- border-bottom: none;
16
- background-color: transparent;
17
- color: var(--color-text-standard);
18
- transition: all 0.2s ease-in-out;
19
- display: flex;
20
- align-items: center;
21
- justify-content: center;
22
- }
23
-
24
- .tab-nav-item:hover {
25
- background-color: var(--color-bg-card);
26
- }
27
-
28
- .tab-nav-item-active {
29
- background-color: var(--color-bg-card);
30
- border: 1px solid var(--color-border-standard);
31
- border-bottom: 1px solid var(--color-bg-card);
32
- position: relative;
33
- z-index: 10;
34
- color: var(--color-primary);
35
- }
36
-
37
- .tab-content {
38
- background-color: var(--color-bg-card);
39
- padding: var(--spacing-common-x);
40
- border: 1px solid var(--color-border-standard);
41
- border-top: 0;
42
- margin-top: -1px; /* Overlap the top line of content with the bottom line of tab to allow the active tab to connect */
43
- position: relative;
44
- z-index: 1;
45
- }
46
-
47
- .tab-content-item {
48
- color: var(--color-text-standard);
49
- width: 100%;
50
- }
51
-
52
- @media (min-width: 640px) {
53
- .tab-content-item {
54
- width: auto;
55
- }
56
- }