@sanvika/ui 0.1.1 → 0.1.3
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/package.json +1 -1
- package/src/components/buttons/FavoriteHeartButton.jsx +2 -2
- package/src/components/buttons/ScrollButton.jsx +1 -1
- package/src/components/buttons/ThreeDotButton.jsx +1 -1
- package/src/components/common/Section.jsx +1 -1
- package/src/components/layout/Footer.jsx +36 -125
- package/src/components/layout/Navbar.jsx +34 -49
- package/src/components/layout/SubNavbar.jsx +36 -0
- package/src/index.js +1 -0
- package/src/styles/components/layouts/Footer.module.css +41 -69
- package/src/styles/components/layouts/Navbar.module.css +39 -92
- package/src/styles/components/layouts/SubNavbar.module.css +34 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// src/components/buttons/FavoriteHeartButton.jsx
|
|
2
2
|
import React from "react";
|
|
3
|
-
import HeartIcon from "../icons/HeartIcon";
|
|
4
|
-
import Button from "./Button";
|
|
3
|
+
import HeartIcon from "../icons/HeartIcon.jsx";
|
|
4
|
+
import Button from "./Button.jsx";
|
|
5
5
|
import styles from "../../styles/components/buttons/FavoriteHeartButton.module.css";
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/components/common/Section.jsx
|
|
2
2
|
import styles from "../../styles/components/common/Section.module.css";
|
|
3
|
-
import Container from "./Container";
|
|
3
|
+
import Container from "./Container.jsx";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Section — a full-width page section with optional title/subtitle.
|
|
@@ -1,142 +1,53 @@
|
|
|
1
1
|
// src/components/layout/Footer.jsx
|
|
2
|
+
"use client";
|
|
2
3
|
import styles from "../../styles/components/layouts/Footer.module.css";
|
|
3
4
|
|
|
4
|
-
const DEFAULT_LEGAL_LINKS = [
|
|
5
|
-
{ href: "/about", label: "About" },
|
|
6
|
-
{ href: "/contact", label: "Contact" },
|
|
7
|
-
{ href: "/legal/privacy-policy", label: "Privacy" },
|
|
8
|
-
{ href: "/legal/terms-of-use", label: "Terms" },
|
|
9
|
-
{ href: "/sitemap", label: "Sitemap" },
|
|
10
|
-
];
|
|
11
|
-
|
|
12
|
-
const DEFAULT_SOCIAL_LINKS = [
|
|
13
|
-
{
|
|
14
|
-
href: "https://www.facebook.com/sanvikaproduction",
|
|
15
|
-
label: "Visit our Facebook page",
|
|
16
|
-
type: "facebook",
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
href: "https://www.instagram.com/sanvikaproduction",
|
|
20
|
-
label: "Visit our Instagram page",
|
|
21
|
-
type: "instagram",
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
href: "https://www.youtube.com/@SanvikaProduction",
|
|
25
|
-
label: "Visit our YouTube channel",
|
|
26
|
-
type: "youtube",
|
|
27
|
-
},
|
|
28
|
-
];
|
|
29
|
-
|
|
30
5
|
/**
|
|
31
|
-
* Footer —
|
|
6
|
+
* Footer — props-driven layout shell for all 50+ Sanvika projects.
|
|
7
|
+
* 3-row layout: socialSlot | legalSlot | trustSlot.
|
|
8
|
+
* Each project passes its own social icons, legal links, trust badge via slots.
|
|
32
9
|
*
|
|
33
|
-
* @param {
|
|
34
|
-
* @param {
|
|
35
|
-
* @param {
|
|
36
|
-
* @param {string} [
|
|
10
|
+
* @param {React.ReactNode} socialSlot - Social icons row (+ optional extra actions like RefreshButton)
|
|
11
|
+
* @param {React.ReactNode} legalSlot - Legal links row (About, Contact, Privacy, Terms, etc.)
|
|
12
|
+
* @param {React.ReactNode} trustSlot - Trust badge row (DUNS badge, copyright, etc.)
|
|
13
|
+
* @param {string} [className] - Additional CSS class
|
|
37
14
|
*/
|
|
38
15
|
const Footer = ({
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
16
|
+
socialSlot,
|
|
17
|
+
legalSlot,
|
|
18
|
+
trustSlot,
|
|
19
|
+
className = "",
|
|
43
20
|
}) => {
|
|
44
21
|
return (
|
|
45
|
-
<footer className={styles.footer}>
|
|
46
|
-
<div className={styles.
|
|
47
|
-
{/* Social icons */}
|
|
48
|
-
|
|
49
|
-
{
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
>
|
|
58
|
-
<SocialIcon name={type} />
|
|
59
|
-
</a>
|
|
60
|
-
))}
|
|
61
|
-
</div>
|
|
22
|
+
<footer className={`${styles.footer} ${className}`.trim()}>
|
|
23
|
+
<div className={styles.footerContent}>
|
|
24
|
+
{/* Row 1: Social icons + extra actions */}
|
|
25
|
+
{socialSlot && (
|
|
26
|
+
<div className={styles.topLine}>
|
|
27
|
+
<div className={styles.socialIconsContainer}>
|
|
28
|
+
<div className={styles.socialIcons}>
|
|
29
|
+
{socialSlot}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
)}
|
|
62
34
|
|
|
63
|
-
{/* Legal links */}
|
|
64
|
-
|
|
65
|
-
<
|
|
66
|
-
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
{label}
|
|
70
|
-
</a>
|
|
71
|
-
</li>
|
|
72
|
-
))}
|
|
73
|
-
</ul>
|
|
74
|
-
</nav>
|
|
35
|
+
{/* Row 2: Legal links */}
|
|
36
|
+
{legalSlot && (
|
|
37
|
+
<div className={styles.legalLinks}>
|
|
38
|
+
{legalSlot}
|
|
39
|
+
</div>
|
|
40
|
+
)}
|
|
75
41
|
|
|
76
|
-
{/* Trust badge */}
|
|
77
|
-
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
</p>
|
|
42
|
+
{/* Row 3: Trust badge */}
|
|
43
|
+
{trustSlot && (
|
|
44
|
+
<div className={styles.dunsContainer}>
|
|
45
|
+
{trustSlot}
|
|
46
|
+
</div>
|
|
47
|
+
)}
|
|
83
48
|
</div>
|
|
84
49
|
</footer>
|
|
85
50
|
);
|
|
86
51
|
};
|
|
87
52
|
|
|
88
|
-
/* Inline SVG social icons — no external dependency */
|
|
89
|
-
const SocialIcon = ({ name }) => {
|
|
90
|
-
if (name === "facebook") {
|
|
91
|
-
return (
|
|
92
|
-
<svg
|
|
93
|
-
viewBox="0 0 24 24"
|
|
94
|
-
width="1em"
|
|
95
|
-
height="1em"
|
|
96
|
-
fill="currentColor"
|
|
97
|
-
aria-hidden="true"
|
|
98
|
-
>
|
|
99
|
-
<path d="M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" />
|
|
100
|
-
</svg>
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
if (name === "instagram") {
|
|
104
|
-
return (
|
|
105
|
-
<svg
|
|
106
|
-
viewBox="0 0 24 24"
|
|
107
|
-
width="1em"
|
|
108
|
-
height="1em"
|
|
109
|
-
fill="none"
|
|
110
|
-
stroke="currentColor"
|
|
111
|
-
strokeWidth="2"
|
|
112
|
-
strokeLinecap="round"
|
|
113
|
-
strokeLinejoin="round"
|
|
114
|
-
aria-hidden="true"
|
|
115
|
-
>
|
|
116
|
-
<rect x="2" y="2" width="20" height="20" rx="5" ry="5" />
|
|
117
|
-
<circle cx="12" cy="12" r="4" />
|
|
118
|
-
<circle cx="17.5" cy="6.5" r="0.5" fill="currentColor" stroke="none" />
|
|
119
|
-
</svg>
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
if (name === "youtube") {
|
|
123
|
-
return (
|
|
124
|
-
<svg
|
|
125
|
-
viewBox="0 0 24 24"
|
|
126
|
-
width="1em"
|
|
127
|
-
height="1em"
|
|
128
|
-
fill="currentColor"
|
|
129
|
-
aria-hidden="true"
|
|
130
|
-
>
|
|
131
|
-
<path d="M22.54 6.42a2.78 2.78 0 0 0-1.95-1.97C18.88 4 12 4 12 4s-6.88 0-8.59.45A2.78 2.78 0 0 0 1.46 6.42 29 29 0 0 0 1 12a29 29 0 0 0 .46 5.58A2.78 2.78 0 0 0 3.41 19.6C5.12 20 12 20 12 20s6.88 0 8.59-.4a2.78 2.78 0 0 0 1.95-1.97A29 29 0 0 0 23 12a29 29 0 0 0-.46-5.58z" />
|
|
132
|
-
<polygon
|
|
133
|
-
points="9.75 15.02 15.5 12 9.75 8.98 9.75 15.02"
|
|
134
|
-
fill="var(--nav-bg, #fff)"
|
|
135
|
-
/>
|
|
136
|
-
</svg>
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
return null;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
53
|
export default Footer;
|
|
@@ -1,64 +1,49 @@
|
|
|
1
|
-
"use client";
|
|
2
1
|
// src/components/layout/Navbar.jsx
|
|
3
|
-
|
|
2
|
+
"use client";
|
|
4
3
|
import styles from "../../styles/components/layouts/Navbar.module.css";
|
|
5
4
|
|
|
6
|
-
const DEFAULT_NAV_LINKS = [{ href: "/", label: "Home" }];
|
|
7
|
-
|
|
8
|
-
const SunIcon = () => <span aria-hidden="true">☀️</span>;
|
|
9
|
-
const MoonIcon = () => <span aria-hidden="true">🌙</span>;
|
|
10
|
-
|
|
11
5
|
/**
|
|
12
|
-
* Navbar —
|
|
6
|
+
* Navbar — props-driven layout shell for all 50+ Sanvika projects.
|
|
7
|
+
* 3-column grid: leftSlot | centerSlot | rightSlot.
|
|
8
|
+
* Each project passes its own logo, buttons, menus via slot props.
|
|
13
9
|
*
|
|
14
|
-
* @param {
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {string} [
|
|
10
|
+
* @param {React.ReactNode} leftSlot - Logo area (left column)
|
|
11
|
+
* @param {React.ReactNode} centerSlot - Center menu items wrapped in <ul>
|
|
12
|
+
* @param {React.ReactNode} rightSlot - Right actions (profile, settings)
|
|
13
|
+
* @param {string} [className] - Additional CSS class
|
|
14
|
+
* @param {string} [ariaLabel] - Accessible label for <nav>
|
|
18
15
|
*/
|
|
19
16
|
const Navbar = ({
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
leftSlot,
|
|
18
|
+
centerSlot,
|
|
19
|
+
rightSlot,
|
|
20
|
+
className = "",
|
|
21
|
+
ariaLabel = "Main navigation",
|
|
24
22
|
}) => {
|
|
25
|
-
const { theme, toggleTheme } = useTheme();
|
|
26
|
-
|
|
27
23
|
return (
|
|
28
|
-
<
|
|
29
|
-
{
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
<nav
|
|
25
|
+
className={`${styles.navbar} ${className}`.trim()}
|
|
26
|
+
aria-label={ariaLabel}
|
|
27
|
+
>
|
|
28
|
+
{/* Left: Logo area */}
|
|
29
|
+
<div className={styles.navSectionLeft}>
|
|
30
|
+
{leftSlot}
|
|
31
|
+
</div>
|
|
33
32
|
|
|
34
|
-
{/* Center:
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
{
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
>
|
|
43
|
-
{label}
|
|
44
|
-
</a>
|
|
45
|
-
</li>
|
|
46
|
-
))}
|
|
47
|
-
</ul>
|
|
48
|
-
</nav>
|
|
33
|
+
{/* Center: Menu items */}
|
|
34
|
+
<div className={styles.navSectionCenter}>
|
|
35
|
+
{centerSlot && (
|
|
36
|
+
<ul className={styles.menu}>
|
|
37
|
+
{centerSlot}
|
|
38
|
+
</ul>
|
|
39
|
+
)}
|
|
40
|
+
</div>
|
|
49
41
|
|
|
50
|
-
{/* Right:
|
|
51
|
-
<div className={styles.
|
|
52
|
-
|
|
53
|
-
className={styles.themeToggle}
|
|
54
|
-
onClick={toggleTheme}
|
|
55
|
-
aria-label={`Switch to ${theme === "dark" ? "light" : "dark"} mode`}
|
|
56
|
-
title={`Switch to ${theme === "dark" ? "light" : "dark"} mode`}
|
|
57
|
-
>
|
|
58
|
-
{theme === "dark" ? <SunIcon /> : <MoonIcon />}
|
|
59
|
-
</button>
|
|
42
|
+
{/* Right: Action buttons */}
|
|
43
|
+
<div className={styles.navSectionRight}>
|
|
44
|
+
{rightSlot}
|
|
60
45
|
</div>
|
|
61
|
-
</
|
|
46
|
+
</nav>
|
|
62
47
|
);
|
|
63
48
|
};
|
|
64
49
|
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/components/layout/SubNavbar.jsx
|
|
2
|
+
"use client";
|
|
3
|
+
import styles from "../../styles/components/layouts/SubNavbar.module.css";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* SubNavbar — fixed below Navbar, props-driven layout shell.
|
|
7
|
+
* Accepts items as children (React nodes) and optional afterContent
|
|
8
|
+
* for global modals/overlays that should render outside the nav.
|
|
9
|
+
*
|
|
10
|
+
* @param {React.ReactNode} children - Menu items (each wrapped in <li>)
|
|
11
|
+
* @param {React.ReactNode} [afterContent] - Content rendered after nav (modals, overlays)
|
|
12
|
+
* @param {string} [className] - Additional CSS class
|
|
13
|
+
* @param {string} [ariaLabel] - Accessible label for <nav>
|
|
14
|
+
*/
|
|
15
|
+
const SubNavbar = ({
|
|
16
|
+
children,
|
|
17
|
+
afterContent,
|
|
18
|
+
className = "",
|
|
19
|
+
ariaLabel = "Secondary navigation",
|
|
20
|
+
}) => {
|
|
21
|
+
return (
|
|
22
|
+
<>
|
|
23
|
+
<nav
|
|
24
|
+
className={`${styles.subNavbar} ${className}`.trim()}
|
|
25
|
+
aria-label={ariaLabel}
|
|
26
|
+
>
|
|
27
|
+
<ul className={styles.menu}>
|
|
28
|
+
{children}
|
|
29
|
+
</ul>
|
|
30
|
+
</nav>
|
|
31
|
+
{afterContent}
|
|
32
|
+
</>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export default SubNavbar;
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// ─── Layout ──────────────────────────────────────────────────────────────────
|
|
6
6
|
export { default as Navbar } from "./components/layout/Navbar.jsx";
|
|
7
|
+
export { default as SubNavbar } from "./components/layout/SubNavbar.jsx";
|
|
7
8
|
export { default as Footer } from "./components/layout/Footer.jsx";
|
|
8
9
|
|
|
9
10
|
// ─── Buttons ─────────────────────────────────────────────────────────────────
|
|
@@ -1,100 +1,72 @@
|
|
|
1
1
|
/* src/styles/components/layouts/Footer.module.css */
|
|
2
2
|
|
|
3
|
+
/* Footer Container — Non-sticky, scrolls with content */
|
|
3
4
|
.footer {
|
|
4
|
-
width: 100%;
|
|
5
5
|
background-color: var(--card-bg);
|
|
6
|
-
|
|
7
|
-
border-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
padding: clamp(2px, 0.5vw, 4px) clamp(5px, 1.5vw, 10px);
|
|
7
|
+
border-top: clamp(0.5px, 0.2vw, 1px) solid var(--border-color);
|
|
8
|
+
border-bottom: clamp(0.5px, 0.2vw, 1px) solid var(--border-color);
|
|
9
|
+
width: 100%;
|
|
11
10
|
display: flex;
|
|
12
|
-
|
|
13
|
-
align-items: center;
|
|
11
|
+
z-index: 900;
|
|
14
12
|
justify-content: center;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
text-align: center;
|
|
14
|
+
transition: background-color 0.3s ease, color 0.3s ease;
|
|
15
|
+
position: relative;
|
|
16
|
+
min-height: clamp(24px, 6vw, 36px);
|
|
17
|
+
box-shadow: 0 -1px 0 0 var(--border-color) inset;
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
|
|
20
|
+
/* Footer Content — column layout */
|
|
21
|
+
.footerContent {
|
|
23
22
|
display: flex;
|
|
24
23
|
flex-direction: column;
|
|
25
24
|
align-items: center;
|
|
26
25
|
width: 100%;
|
|
27
|
-
max-width: clamp(300px, 90vw,
|
|
28
|
-
gap: clamp(
|
|
26
|
+
max-width: clamp(300px, 90vw, 400px);
|
|
27
|
+
gap: clamp(1px, 0.2vw, 2px);
|
|
29
28
|
}
|
|
30
29
|
|
|
31
|
-
/* Social
|
|
32
|
-
.
|
|
30
|
+
/* Top Line — Social Icons row */
|
|
31
|
+
.topLine {
|
|
33
32
|
display: flex;
|
|
34
33
|
align-items: center;
|
|
35
|
-
|
|
34
|
+
justify-content: center;
|
|
35
|
+
width: 100%;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
/* Social Icons Container */
|
|
39
|
+
.socialIconsContainer {
|
|
40
|
+
display: flex;
|
|
40
41
|
align-items: center;
|
|
41
42
|
justify-content: center;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
transition: color 0.3s ease;
|
|
45
|
-
text-decoration: none;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.socialLink:hover {
|
|
49
|
-
opacity: 0.8;
|
|
50
|
-
text-decoration: none;
|
|
43
|
+
flex: 0 0 auto;
|
|
44
|
+
padding: clamp(2px, 1vw, 4px) clamp(4px, 1.5vw, 6px);
|
|
51
45
|
}
|
|
52
46
|
|
|
53
|
-
/*
|
|
54
|
-
.
|
|
47
|
+
/* Social Icons row — includes extra actions like refresh button */
|
|
48
|
+
.socialIcons {
|
|
55
49
|
display: flex;
|
|
50
|
+
gap: clamp(8px, 2vw, 16px);
|
|
56
51
|
align-items: center;
|
|
57
|
-
flex-wrap: wrap;
|
|
58
52
|
justify-content: center;
|
|
59
|
-
gap: clamp(8px, 2vw, 16px);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.link {
|
|
63
|
-
font-size: clamp(0.65rem, 2vw, 0.75rem);
|
|
64
|
-
color: var(--text-color);
|
|
65
|
-
text-decoration: none;
|
|
66
|
-
white-space: nowrap;
|
|
67
|
-
transition: color 0.3s ease;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.link:hover {
|
|
71
|
-
color: var(--link-hover-color);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/* Copyright / trust line */
|
|
75
|
-
.trust {
|
|
76
|
-
font-size: clamp(0.6rem, 1.8vw, 0.68rem);
|
|
77
|
-
color: var(--text-color);
|
|
78
|
-
text-align: center;
|
|
79
53
|
}
|
|
80
54
|
|
|
81
|
-
|
|
82
|
-
|
|
55
|
+
/* Legal Links row */
|
|
56
|
+
.legalLinks {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-wrap: nowrap;
|
|
59
|
+
justify-content: center;
|
|
83
60
|
align-items: center;
|
|
84
|
-
gap: clamp(
|
|
85
|
-
|
|
86
|
-
font-size: inherit;
|
|
87
|
-
text-decoration: none;
|
|
88
|
-
transition: color 0.3s ease;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
.trustBadge:hover {
|
|
92
|
-
color: var(--success-color);
|
|
93
|
-
text-decoration: none;
|
|
61
|
+
gap: clamp(4px, 1.5vw, 8px);
|
|
62
|
+
width: 100%;
|
|
94
63
|
}
|
|
95
64
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
65
|
+
/* DUNS / Trust Badge Container */
|
|
66
|
+
.dunsContainer {
|
|
67
|
+
display: flex;
|
|
68
|
+
justify-content: center;
|
|
69
|
+
align-items: center;
|
|
70
|
+
width: 100%;
|
|
71
|
+
margin-top: clamp(2px, 0.5vw, 4px);
|
|
100
72
|
}
|
|
@@ -1,121 +1,68 @@
|
|
|
1
1
|
/* src/styles/components/layouts/Navbar.module.css */
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
position: fixed;
|
|
6
|
-
top: 0;
|
|
7
|
-
left: 0;
|
|
8
|
-
right: 0;
|
|
9
|
-
z-index: 1000;
|
|
3
|
+
/* Main navbar container — 3-column grid, fixed at top */
|
|
4
|
+
.navbar {
|
|
10
5
|
background-color: var(--card-bg);
|
|
6
|
+
padding: clamp(4px, 1vw, 10px) clamp(6px, 2vw, 18px);
|
|
11
7
|
border-top: 1px solid var(--border-color);
|
|
12
8
|
border-bottom: 1px solid var(--border-color);
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
width: 100%;
|
|
10
|
+
z-index: 1000;
|
|
11
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
12
|
+
overflow: visible;
|
|
13
|
+
min-height: clamp(40px, 10vw, 60px);
|
|
16
14
|
display: grid;
|
|
17
15
|
grid-template-columns: auto 1fr auto;
|
|
18
16
|
align-items: center;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
position: fixed;
|
|
18
|
+
top: 0;
|
|
19
|
+
left: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
column-gap: clamp(4px, 1vw, 12px);
|
|
22
22
|
transition: background-color 0.3s ease;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
/* Left
|
|
26
|
-
.
|
|
25
|
+
/* Left section — logo area */
|
|
26
|
+
.navSectionLeft {
|
|
27
27
|
display: flex;
|
|
28
28
|
align-items: center;
|
|
29
|
-
|
|
29
|
+
justify-content: flex-start;
|
|
30
|
+
height: 100%;
|
|
31
|
+
cursor: pointer;
|
|
32
|
+
user-select: none;
|
|
33
|
+
min-width: clamp(48px, 16vw, 88px);
|
|
30
34
|
text-decoration: none;
|
|
31
35
|
color: inherit;
|
|
32
|
-
flex-shrink: 0;
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
align-items: center;
|
|
38
|
-
gap: var(--space-2);
|
|
39
|
-
text-decoration: none;
|
|
40
|
-
color: var(--text-color);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.logoMark {
|
|
44
|
-
width: clamp(28px, 8vw, 40px);
|
|
45
|
-
height: clamp(28px, 8vw, 40px);
|
|
46
|
-
object-fit: contain;
|
|
47
|
-
border-radius: var(--radius-md);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
.logoText {
|
|
51
|
-
font-size: clamp(var(--text-base), 3vw, var(--text-lg));
|
|
52
|
-
font-weight: 700;
|
|
53
|
-
color: var(--text-color);
|
|
54
|
-
letter-spacing: -0.02em;
|
|
55
|
-
white-space: nowrap;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/* Center: nav links */
|
|
59
|
-
.nav {
|
|
38
|
+
/* Center section — menu items */
|
|
39
|
+
.navSectionCenter {
|
|
60
40
|
display: flex;
|
|
61
41
|
align-items: center;
|
|
62
42
|
justify-content: center;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.navLink {
|
|
69
|
-
font-size: clamp(var(--text-xs), 2.5vw, var(--text-sm));
|
|
70
|
-
font-weight: 500;
|
|
71
|
-
color: var(--text-color);
|
|
72
|
-
text-decoration: none;
|
|
73
|
-
padding: var(--space-1) var(--space-2);
|
|
74
|
-
border-radius: var(--radius-sm);
|
|
75
|
-
white-space: nowrap;
|
|
76
|
-
transition:
|
|
77
|
-
color 0.3s ease,
|
|
78
|
-
background-color 0.3s ease;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
.navLink:hover {
|
|
82
|
-
color: var(--nav-link-hover);
|
|
83
|
-
background-color: var(--hover-color);
|
|
84
|
-
text-decoration: none;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.navLinkActive {
|
|
88
|
-
color: var(--primary-color);
|
|
89
|
-
font-weight: 600;
|
|
43
|
+
height: 100%;
|
|
44
|
+
width: 100%;
|
|
45
|
+
min-width: 0;
|
|
90
46
|
}
|
|
91
47
|
|
|
92
|
-
|
|
93
|
-
|
|
48
|
+
.menu {
|
|
49
|
+
list-style: none;
|
|
94
50
|
display: flex;
|
|
95
51
|
align-items: center;
|
|
96
|
-
|
|
97
|
-
|
|
52
|
+
justify-content: center;
|
|
53
|
+
margin: 0;
|
|
54
|
+
padding: 0;
|
|
55
|
+
flex-wrap: nowrap;
|
|
56
|
+
gap: clamp(4px, 1.2vw, 12px);
|
|
57
|
+
width: 100%;
|
|
98
58
|
}
|
|
99
59
|
|
|
100
|
-
/*
|
|
101
|
-
.
|
|
60
|
+
/* Right section — action buttons */
|
|
61
|
+
.navSectionRight {
|
|
102
62
|
display: flex;
|
|
103
63
|
align-items: center;
|
|
104
|
-
justify-content:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
border: 1px solid var(--border-color-light);
|
|
109
|
-
background: transparent;
|
|
110
|
-
color: var(--text-color);
|
|
111
|
-
cursor: pointer;
|
|
112
|
-
font-size: var(--text-base);
|
|
113
|
-
transition:
|
|
114
|
-
background-color 0.3s ease,
|
|
115
|
-
border-color 0.3s ease;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
.themeToggle:hover {
|
|
119
|
-
background-color: var(--hover-color);
|
|
120
|
-
border-color: var(--border-color);
|
|
64
|
+
justify-content: flex-end;
|
|
65
|
+
height: 100%;
|
|
66
|
+
min-width: clamp(48px, 16vw, 88px);
|
|
67
|
+
overflow: visible;
|
|
121
68
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/* src/styles/components/layouts/SubNavbar.module.css */
|
|
2
|
+
|
|
3
|
+
/* Fixed below main Navbar */
|
|
4
|
+
.subNavbar {
|
|
5
|
+
background-color: var(--card-bg);
|
|
6
|
+
padding: clamp(6px, 1.5vw, 10px) clamp(6px, 2vw, 18px);
|
|
7
|
+
border-bottom: 0.5px solid var(--border-color);
|
|
8
|
+
width: 100%;
|
|
9
|
+
display: flex;
|
|
10
|
+
z-index: 999;
|
|
11
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
12
|
+
overflow: visible;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
position: fixed;
|
|
16
|
+
min-height: clamp(48px, 10vw, 60px);
|
|
17
|
+
top: clamp(48px, 10vw, 60px);
|
|
18
|
+
left: 0;
|
|
19
|
+
right: 0;
|
|
20
|
+
transition: background-color 0.3s ease;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.menu {
|
|
24
|
+
list-style: none;
|
|
25
|
+
display: flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
justify-content: space-evenly;
|
|
28
|
+
margin: 0;
|
|
29
|
+
padding: 0 clamp(4px, 1vw, 12px);
|
|
30
|
+
flex-wrap: nowrap;
|
|
31
|
+
gap: clamp(4px, 1.5vw, 16px);
|
|
32
|
+
width: 100%;
|
|
33
|
+
max-width: 500px;
|
|
34
|
+
}
|