atomsystem 0.1.25 → 0.1.27

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.
package/cli/add.js CHANGED
@@ -19,7 +19,7 @@ const components = [
19
19
  "Card",
20
20
  "Collapse",
21
21
  "CodeBlock",
22
- "GlobalNav",
22
+ "Navigation",
23
23
  "Input",
24
24
  "Theme",
25
25
  "Tab",
@@ -34,21 +34,53 @@ const components = [
34
34
  const args = process.argv.slice(2); // 'npx atomsystem-add Button -> [Button]'
35
35
  const component = args[0] || "all"; // '사용자가 입력하지 않으면 기본적으로 'all''
36
36
 
37
+ // 일부 컴포넌트의 의존성 구조 (Theme 설치시 내부적으로 Button, Form, Modal 등이 필요함)
38
+ const dependenciesMap = {
39
+ Theme: ["Button", "Form", "Modal"], // Form 안에는 Radio가 들어있음
40
+ };
41
+
42
+ // 재귀 방지를 위한 Set
43
+ const addedComponents = new Set();
44
+
37
45
  function addComponent(comp) {
46
+ if (addedComponents.has(comp)) return;
47
+ addedComponents.add(comp);
38
48
  const componentPath = path.join(templateDir, comp, `${comp}.tsx`);
39
49
  const targetDir = path.join(process.cwd(), "app", "components", comp);
40
50
  const targetPath = path.join(targetDir, `${comp}.tsx`);
41
51
 
52
+ // 컴포넌트의 CSS 파일 복제 지원
53
+ const cssFileName = `${comp}.css`.toLowerCase();
54
+ const sourceCssPath = path.join(__dirname, "..", "css", cssFileName);
55
+ const targetCssPath = path.join(targetDir, cssFileName);
56
+
42
57
  if (fs.existsSync(componentPath)) {
43
58
  // 대상 디렉토리가 없으면 생성
44
59
  if (!fs.existsSync(targetDir)) {
45
60
  fs.mkdirSync(targetDir, { recursive: true });
46
61
  console.log(`Created directory: ${targetDir}`);
47
62
  }
63
+
64
+ // 1) TSX 복사
48
65
  copyFileSync(componentPath, targetPath);
49
- console.log(`${comp} component has been added to ${targetPath}`);
66
+ console.log(`✅ ${comp} component typescript has been added to ${targetPath}`);
67
+
68
+ // 2) CSS 복사
69
+ if (fs.existsSync(sourceCssPath)) {
70
+ copyFileSync(sourceCssPath, targetCssPath);
71
+ console.log(`✅ ${comp} component stylesheet has been added to ${targetCssPath}`);
72
+ }
73
+ // 3) 의존성 컴포넌트 자동 복사 (Recursive Copy)
74
+ if (dependenciesMap[comp]) {
75
+ console.log(`\n⏳ Checking dependencies for ${comp}...`);
76
+ dependenciesMap[comp].forEach((dep) => {
77
+ addComponent(dep);
78
+ });
79
+ console.log(`✅ Finished adding dependencies for ${comp}.\n`);
80
+ }
81
+
50
82
  } else {
51
- console.log(`Component ${comp} does not exist in the atomsystem.`);
83
+ console.log(`❌ Component ${comp} does not exist in the atomsystem.`);
52
84
  }
53
85
  }
54
86
 
package/cli/init.js CHANGED
@@ -14,14 +14,23 @@ const __dirname = path.dirname(__filename);
14
14
 
15
15
  // 패키지 내부 경로 설정
16
16
  const packageRoot = path.join(__dirname, "..");
17
- const tokenFile = path.join(packageRoot, "token.json");
18
- const buildFile = path.join(packageRoot, "/build/build-tokens.js");
17
+ const tokenFile = path.join(packageRoot, "tokens", "tokens.json");
18
+ const buildFile = path.join(packageRoot, "build", "build-tokens.js");
19
19
 
20
20
  // 프로젝트 루트 경로 (사용자가 실행한 곳)
21
21
  const projectRoot = process.cwd();
22
- const targetTokenFile = path.join(projectRoot, "token.json");
22
+ const targetTokenDir = path.join(projectRoot, "tokens");
23
+ const targetTokenFile = path.join(targetTokenDir, "tokens.json");
23
24
  const targetBuildDir = path.join(projectRoot, "build");
24
- const targetBuildFile = path.join(projectRoot, "/build/build-tokens.js");
25
+ const targetBuildFile = path.join(targetBuildDir, "build-tokens.js");
26
+
27
+ // 사용자 프로젝트에 package.json이 존재하는지 먼저 확인 (안전장치)
28
+ const packageJsonPath = path.join(projectRoot, "package.json");
29
+ if (!fs.existsSync(packageJsonPath)) {
30
+ console.error("❌ Error: package.json not found in the current directory.");
31
+ console.error("Please run 'npm init' or 'npm init -y' before running atomsystem-init.");
32
+ process.exit(1);
33
+ }
25
34
 
26
35
  // 사용자에게 Next.js 설치 여부 질문
27
36
  inquirer
@@ -41,9 +50,18 @@ inquirer
41
50
  await execPromise(
42
51
  "npm install next@latest react@latest react-dom@latest tailwindcss"
43
52
  );
44
- console.log("✅ Installation complete!");
53
+ console.log("✅ Next.js and React Installation complete!");
45
54
  } catch (err) {
46
- console.error("❌ Error during installation:", err);
55
+ console.error("❌ Error during Next.js/React installation:", err);
56
+ return;
57
+ }
58
+
59
+ console.log("Installing style-dictionary for atom design tokens...");
60
+ try {
61
+ await execPromise("npm install style-dictionary -D");
62
+ console.log("✅ style-dictionary Installation complete!");
63
+ } catch (err) {
64
+ console.error("❌ Error during style-dictionary installation:", err);
47
65
  return;
48
66
  }
49
67
 
@@ -54,6 +72,7 @@ inquirer
54
72
  fs.readFileSync(packageJsonPath, "utf8")
55
73
  );
56
74
 
75
+ packageJson.type = "module";
57
76
  packageJson.scripts = {
58
77
  ...packageJson.scripts,
59
78
  "token-build": "node build/build-tokens.js",
@@ -71,20 +90,68 @@ inquirer
71
90
  if (!fs.existsSync(appDir)) mkdirSync(appDir);
72
91
 
73
92
  const files = [
93
+ {
94
+ path: path.join(appDir, "ThemeProvider.tsx"),
95
+ content: `"use client";
96
+ import { useEffect, useState } from "react";
97
+ import { themes } from "@/build/typescript/theme";
98
+
99
+ export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
100
+ const [theme, setTheme] = useState<Record<string, string>>({});
101
+ const [isThemeLoading, setThemeLoading] = useState(false);
102
+
103
+ useEffect(() => {
104
+ const listenStorageChange = () => {
105
+ const newThemes: Record<string, string> = {};
106
+ Object.entries(themes).forEach(([group, groupThemes]) => {
107
+ const storedKey = group === "global" ? "theme" : \`theme-\${group}\`;
108
+ const currentTheme = localStorage.getItem(storedKey) || groupThemes[0];
109
+ newThemes[group] = currentTheme;
110
+
111
+ document.documentElement.classList.remove(...groupThemes);
112
+ document.documentElement.classList.add(currentTheme);
113
+ });
114
+ setTheme(newThemes);
115
+ };
116
+
117
+ listenStorageChange();
118
+ window.addEventListener("storage", listenStorageChange);
119
+ setThemeLoading(true);
120
+ return () => window.removeEventListener("storage", listenStorageChange);
121
+ }, []);
122
+
123
+ if (isThemeLoading === false) return null;
124
+ return <>{children}</>;
125
+ };`,
126
+ },
74
127
  {
75
128
  path: path.join(appDir, "layout.tsx"),
76
- content: `export default function RootLayout({ children }: { children: React.ReactNode }) {
129
+ content: `import { ThemeProvider } from "./ThemeProvider";
130
+ import "../css/global.css"; // Ensure to load the CSS configuration if possible
131
+
132
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
77
133
  return (
78
134
  <html lang="en">
79
- <body>{children}</body>
135
+ <body>
136
+ <ThemeProvider>
137
+ {children}
138
+ </ThemeProvider>
139
+ </body>
80
140
  </html>
81
141
  )
82
142
  }`,
83
143
  },
84
144
  {
85
145
  path: path.join(appDir, "page.tsx"),
86
- content: `export default function Page() {
87
- return <h1>Hello, Next.js!</h1>
146
+ content: `import { ThemeSelector } from "./components/Theme/Theme";
147
+
148
+ export default function Page() {
149
+ return (
150
+ <main style={{ padding: "20px" }}>
151
+ <h1>Hello, atomsystem!</h1>
152
+ <ThemeSelector />
153
+ </main>
154
+ )
88
155
  }`,
89
156
  },
90
157
  ];
@@ -97,13 +164,14 @@ inquirer
97
164
  console.log("🚀 Installation skipped.");
98
165
  }
99
166
 
100
- // ✅ 토큰 파일 복사 (Next.js 설치 여부와 관계없이 실행)
167
+ // ✅ 토큰 파일과 빌드 파일 복사 (Next.js 설치 여부와 관계없이 실행)
168
+ if (!fs.existsSync(targetTokenDir)) mkdirSync(targetTokenDir, { recursive: true });
101
169
  copyFileSync(tokenFile, targetTokenFile);
102
- console.log(`✅ Copied: token.json -> ${targetTokenFile}`);
170
+ console.log(`✅ Copied: tokens/tokens.json -> ${targetTokenFile}`);
103
171
 
104
- if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir);
172
+ if (!fs.existsSync(targetBuildDir)) mkdirSync(targetBuildDir, { recursive: true });
105
173
  copyFileSync(buildFile, targetBuildFile);
106
- console.log(`✅ Copied: build-token.json -> ${targetTokenFile}`);
174
+ console.log(`✅ Copied: build-tokens.js -> ${targetBuildFile}`);
107
175
 
108
176
  console.log("🚀 Token setup complete!");
109
177
  })
package/css/badge.css ADDED
@@ -0,0 +1,28 @@
1
+ .badge,
2
+ .badge-tint {
3
+ font-size: var(--text-sm);
4
+ padding: 0 var(--spacing-common-y);
5
+ border-radius: var(--radius-common);
6
+ }
7
+
8
+
9
+
10
+ .badge.primary { --badge-bg: var(--color-primary); }
11
+ .badge.secondary { --badge-bg: var(--color-secondary); }
12
+ .badge.warning { --badge-bg: var(--color-warning); }
13
+ .badge.danger { --badge-bg: var(--color-danger); }
14
+
15
+ .badge {
16
+ background-color: var(--badge-bg);
17
+ color: var(--color-white);
18
+ }
19
+
20
+ .badge-tint.primary { --badge-bg: var(--color-blue-100); --text-color: var(--color-primary); }
21
+ .badge-tint.secondary { --badge-bg: var(--color-indigo-100); --text-color: var(--color-secondary); }
22
+ .badge-tint.warning { --badge-bg: var(--color-yellow-100); --text-color: var(--color-warning); }
23
+ .badge-tint.danger { --badge-bg: var(--color-red-100); --text-color: var(--color-danger); }
24
+
25
+ .badge-tint {
26
+ background-color: var(--badge-bg);
27
+ color: var(--text-color);
28
+ }
package/css/button.css ADDED
@@ -0,0 +1,75 @@
1
+ .btn {
2
+ padding: var(--spacing-common-y) var(--spacing-common-x);
3
+ color: var(--color-white);
4
+ transition: all 0.2s;
5
+ cursor: pointer;
6
+ border-radius: var(--radius-common);
7
+ border: none;
8
+ font-family: var(--font-spoqaNeo);
9
+ }
10
+
11
+ .btn.primary {
12
+ --btn-bg: var(--color-primary);
13
+ --btn-hover: var(--color-blue-600);
14
+ --btn-active: var(--color-blue-700);
15
+ --btn-bg-disabled: var(--button-primary-bg-disabled);
16
+ --btn-text-disabled: var(--button-primary-text-disabled);
17
+ --btn-border-disabled: var(--button-primary-border-disabled);
18
+ }
19
+ .btn.secondary {
20
+ --btn-bg: var(--color-secondary);
21
+ --btn-hover: var(--color-indigo-600);
22
+ --btn-active: var(--color-indigo-700);
23
+ --btn-bg-disabled: var(--button-secondary-bg-disabled);
24
+ --btn-text-disabled: var(--button-secondary-text-disabled);
25
+ --btn-border-disabled: var(--button-secondary-border-disabled);
26
+ }
27
+ .btn.success {
28
+ --btn-bg: var(--color-success);
29
+ --btn-hover: var(--color-green-600);
30
+ --btn-active: var(--color-green-700);
31
+ --btn-bg-disabled: var(--button-success-bg-disabled);
32
+ --btn-text-disabled: var(--button-success-text-disabled);
33
+ --btn-border-disabled: var(--button-success-border-disabled);
34
+ }
35
+ .btn.warning {
36
+ --btn-bg: var(--color-warning);
37
+ --btn-hover: var(--color-yellow-600);
38
+ --btn-active: var(--color-yellow-700);
39
+ --btn-bg-disabled: var(--button-warning-bg-disabled);
40
+ --btn-text-disabled: var(--button-warning-text-disabled);
41
+ --btn-border-disabled: var(--button-warning-border-disabled);
42
+ }
43
+ .btn.danger {
44
+ --btn-bg: var(--color-danger);
45
+ --btn-hover: var(--color-red-600);
46
+ --btn-active: var(--color-red-700);
47
+ --btn-bg-disabled: var(--button-danger-bg-disabled);
48
+ --btn-text-disabled: var(--button-danger-text-disabled);
49
+ --btn-border-disabled: var(--button-danger-border-disabled);
50
+ }
51
+ .btn.gray {
52
+ --btn-bg: var(--color-gray-500);
53
+ --btn-hover: var(--color-gray-600);
54
+ --btn-active: var(--color-gray-700);
55
+ --btn-bg-disabled: var(--button-gray-bg-disabled);
56
+ --btn-text-disabled: var(--button-gray-text-disabled);
57
+ --btn-border-disabled: var(--button-gray-border-disabled);
58
+ }
59
+
60
+ .btn {
61
+ background-color: var(--btn-bg);
62
+ }
63
+ .btn:hover:not(:disabled) {
64
+ background-color: var(--btn-hover);
65
+ }
66
+ .btn:active:not(:disabled) {
67
+ background-color: var(--btn-active);
68
+ }
69
+ .btn:disabled {
70
+ background-color: var(--btn-bg-disabled);
71
+ color: var(--btn-text-disabled);
72
+ cursor: not-allowed;
73
+ opacity: 0.7;
74
+ border: 1px solid var(--btn-border-disabled);
75
+ }
package/css/card.css ADDED
@@ -0,0 +1,17 @@
1
+ .card {
2
+ background-color: var(--color-bg-card);
3
+ border-radius: var(--radius-common);
4
+ border: 1px solid var(--border-standard);
5
+ }
6
+
7
+ .card-header,
8
+ .card-content,
9
+ .card-footer {
10
+ padding: var(--spacing-common-x);
11
+ }
12
+
13
+ .card-header.no-margin,
14
+ .card-content.no-margin,
15
+ .card-footer.no-margin {
16
+ padding: 0;
17
+ }
@@ -0,0 +1,33 @@
1
+ .collapse-item {
2
+ border-top: 1px solid var(--border-standard);
3
+ background-color: var(--color-bg-card);
4
+ }
5
+
6
+ .collapse-header {
7
+ display: flex;
8
+ justify-content: space-between;
9
+ align-items: center;
10
+ cursor: pointer;
11
+ padding: var(--spacing-common-x);
12
+ color: var(--text-standard);
13
+ font-size: var(--text-body);
14
+ }
15
+
16
+ .collapse-icon {
17
+ transition: transform 0.3s ease;
18
+ color: var(--text-standard);
19
+ }
20
+
21
+ .collapse-icon.open {
22
+ transform: rotate(90deg);
23
+ }
24
+
25
+ .collapse-icon.closed {
26
+ transform: rotate(0deg);
27
+ }
28
+
29
+ .collapse-content {
30
+ padding: var(--spacing-common-x);
31
+ color: var(--text-standard);
32
+ font-size: var(--text-body);
33
+ }
package/css/form.css ADDED
@@ -0,0 +1,115 @@
1
+
2
+ .input{
3
+ background: var(--bg-input-standard);
4
+ border: 1px solid var(--border-standard);
5
+ color: var(--text-standard);
6
+ padding: var(--spacing-common-y) var(--spacing-common-x);
7
+ border-radius: var(--radius-common);
8
+ }
9
+
10
+ .input::placeholder{
11
+ color: var(--text-placeholder);
12
+ }
13
+
14
+ .input:focus{
15
+ border: 1px solid var(--border-active);
16
+ }
17
+
18
+ .input:disabled{
19
+ background: var(--bg-input-disabled);
20
+ border: 1px solid var(--border-standard);
21
+ color: var(--text-disabled);
22
+ }
23
+
24
+ .select{
25
+ background: var(--bg-input-standard);
26
+ border: 1px solid var(--border-standard);
27
+ color: var(--text-standard);
28
+ padding: var(--spacing-common-y) var(--spacing-common-x);
29
+ border-radius: var(--radius-common);
30
+ }
31
+ .select:focus{
32
+ border: 1px solid var(--border-active);
33
+ }
34
+
35
+ .select:disabled{
36
+ background: var(--bg-input-disabled);
37
+ border: 1px solid var(--border-standard);
38
+ color: var(--text-disabled);
39
+ }
40
+
41
+ .select-menu {
42
+ border: 1px solid var(--border-active);
43
+ border-radius: var(--radius-common);
44
+ overflow:hidden;
45
+ }
46
+
47
+ .select-menu .select-menu-item {
48
+ background: var(--bg-input-standard);
49
+ border: 1px solid var(--border-standard);
50
+ color: var(--text-standard);
51
+ padding: var(--spacing-common-y) var(--spacing-common-x);
52
+ cursor:pointer
53
+ }
54
+
55
+ .select-menu .select-menu-item:hover {
56
+ background: var(--bg-input-hover);
57
+ }
58
+
59
+ .select-menu .select-menu-item:active,
60
+ .select-menu .select-menu-item:focus {
61
+ background: var(--color-primary);
62
+ border: 1px solid var(--color-primary);
63
+ color: var(--text-active);
64
+ }
65
+
66
+ .checkbox{
67
+ display: flex;
68
+ align-items: center;
69
+ position: relative;
70
+ width: var(--spacing-small);
71
+ height: var(--spacing-small);
72
+ border: 1px solid var(--border-standard);
73
+ border-radius: var(--radius-common);
74
+ background: var(--bg-input-standard);
75
+ color: var(--bg-input-standard);
76
+ }
77
+
78
+ .checkbox span svg{
79
+ color: var(--bg-input-standard);
80
+ fill: var(--bg-input-standard);
81
+ }
82
+
83
+ .checkbox:has(input:checked){
84
+ background: var(--color-primary);
85
+ border: 1px solid var(--color-primary);
86
+ }
87
+
88
+ .checkbox:has(input:checked) span svg{
89
+ color: var(--text-active);
90
+ fill: var(--text-active);
91
+ }
92
+
93
+ .radio{
94
+ position: relative;
95
+ width: var(--spacing-small);
96
+ height: var(--spacing-small);
97
+ border: 1px solid var(--border-standard);
98
+ background: var(--bg-input-standard);
99
+ color: var(--bg-input-standard);
100
+ }
101
+
102
+ .radio::after{
103
+ content:'';
104
+ position:absolute;
105
+ left: 50%;
106
+ top: 50%;
107
+ transform: translate(-50%, -50%);
108
+ width: var(--spacing-common-y);
109
+ height: var(--spacing-common-y);
110
+ border-radius: var(--radius-circle);
111
+ }
112
+
113
+ .radio:checked::after{
114
+ background: var(--color-primary);
115
+ }
package/css/modal.css ADDED
@@ -0,0 +1,98 @@
1
+ .modal-overlay {
2
+ position: fixed;
3
+ inset: 0;
4
+ background-color: rgba(0, 0, 0, 0.4);
5
+ display: flex;
6
+ justify-content: center;
7
+ align-items: center;
8
+ z-index: 50;
9
+ }
10
+
11
+ .modal {
12
+ background-color: var(--color-bg-card);
13
+ padding: 0;
14
+ border-radius: var(--radius-common);
15
+ box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
16
+ width: 100%;
17
+ display: flex;
18
+ flex-direction: column;
19
+ color: var(--color-text-standard);
20
+ border: 1px solid var(--color-border-standard);
21
+ max-height: 90vh;
22
+ }
23
+
24
+ .modal-content {
25
+ padding: var(--spacing-common-x);
26
+ width: 100%;
27
+ overflow-y: auto;
28
+ flex: 1;
29
+ }
30
+
31
+ .modal-header {
32
+ display: flex;
33
+ justify-content: space-between;
34
+ align-items: center;
35
+ padding: var(--spacing-common-y) var(--spacing-common-x);
36
+ border-bottom: 1px solid var(--color-border-standard);
37
+ }
38
+
39
+ .modal-title {
40
+ font-size: var(--text-h6);
41
+ font-weight: var(--font-weight-header);
42
+ margin: 0;
43
+ color: var(--color-text-standard);
44
+ }
45
+
46
+ .modal-close {
47
+ cursor: pointer;
48
+ background: transparent;
49
+ border: none;
50
+ color: var(--color-text-standard);
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ padding: 0;
55
+ transition: color 0.2s ease-in-out;
56
+ }
57
+
58
+ .modal-close:hover {
59
+ color: var(--color-danger);
60
+ }
61
+
62
+ .modal-footer {
63
+ display: flex;
64
+ justify-content: flex-end;
65
+ padding: var(--spacing-common-y) var(--spacing-common-x);
66
+ border-top: 1px solid var(--color-border-standard);
67
+ gap: var(--spacing-gap-small);
68
+ }
69
+
70
+ /* Modal Sizes */
71
+ .modal-normal {
72
+ max-width: 28rem; /* Tailwind max-w-md */
73
+ }
74
+
75
+ .modal-middle {
76
+ max-width: 36rem; /* Tailwind max-w-xl */
77
+ }
78
+
79
+ .modal-large {
80
+ max-width: 64rem; /* Tailwind max-w-5xl */
81
+ }
82
+
83
+ .modal-xl {
84
+ max-width: 72rem; /* Tailwind max-w-6xl */
85
+ }
86
+
87
+ .modal-full {
88
+ max-width: calc(100vw - (var(--spacing-common-x) * 2));
89
+ }
90
+
91
+ .modal-full-screen {
92
+ width: 100vw;
93
+ height: 100vh;
94
+ max-height: 100vh;
95
+ max-width: 100vw;
96
+ border-radius: 0;
97
+ border: none;
98
+ }
@@ -0,0 +1,69 @@
1
+
2
+
3
+ .nav-container.nav-topnav {
4
+ background-color: var(--bg-topnav);
5
+ color: var(--text-topnav-standard);
6
+ border-color: var(--border-topnav);
7
+ }
8
+
9
+ .nav-container.nav-sidenav {
10
+ background-color: var(--bg-sidenav);
11
+ color: var(--text-sidenav-standard);
12
+ border-color: var(--border-sidenav);
13
+ }
14
+
15
+ .nav-bg.nav-topnav {
16
+ background-color: var(--bg-topnav);
17
+ }
18
+
19
+ .nav-bg.nav-sidenav {
20
+ background-color: var(--bg-sidenav);
21
+ }
22
+
23
+ .nav-border.nav-topnav {
24
+ border-color: var(--border-topnav);
25
+ }
26
+
27
+ .nav-border.nav-sidenav {
28
+ border-color: var(--border-sidenav);
29
+ }
30
+
31
+ .nav-text-standard.nav-topnav {
32
+ color: var(--text-topnav-standard);
33
+ }
34
+
35
+ .nav-text-standard.nav-sidenav {
36
+ color: var(--text-sidenav-standard);
37
+ }
38
+
39
+ .nav-text-active.nav-topnav {
40
+ color: var(--text-topnav-active);
41
+ }
42
+
43
+ .nav-text-active.nav-sidenav {
44
+ color: var(--text-sidenav-active);
45
+ }
46
+
47
+ .nav-text-sub.nav-topnav {
48
+ color: var(--text-topnav-sub);
49
+ }
50
+
51
+ .nav-text-sub.nav-sidenav {
52
+ color: var(--text-sidenav-sub);
53
+ }
54
+
55
+ .nav-padding.nav-topnav {
56
+ padding: var(--spacing-topnav-y) var(--spacing-topnav-x);
57
+ }
58
+
59
+ .nav-padding.nav-sidenav {
60
+ padding: var(--spacing-sidenav-y) var(--spacing-sidenav-x);
61
+ }
62
+
63
+ .nav-gap.nav-topnav {
64
+ gap: var(--spacing-topnav-gap);
65
+ }
66
+
67
+ .nav-gap.nav-sidenav {
68
+ gap: var(--spacing-sidenav-gap);
69
+ }