@salmansaeed/nexa 1.0.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,217 @@
1
+ /* === RESET === */
2
+ * {
3
+ margin: 0;
4
+ padding: 0;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ ul {
9
+ list-style: none;
10
+ }
11
+
12
+ /* === BASE NAVBAR === */
13
+ .nav-wrapper {
14
+ position: relative;
15
+ font-family: "Share Tech Mono", monospace;
16
+ z-index: 10000;
17
+ }
18
+
19
+ /* === DESKTOP SIDEBAR === */
20
+ .nav-sidebar {
21
+ position: fixed;
22
+ top: 0;
23
+ left: 0;
24
+ width: 220px;
25
+ height: 100vh;
26
+ background: linear-gradient(180deg, #07111f 0%, #0d1b2d 100%);
27
+ padding: 1rem;
28
+ border-right: 1px solid var(--nexa-border);
29
+ overflow-y: auto;
30
+ z-index: 9000;
31
+ }
32
+
33
+ .nav-sidebar li {
34
+ margin: 0.7rem 0;
35
+ }
36
+
37
+ .nav-sidebar li a {
38
+ display: block;
39
+ padding: 12px 20px;
40
+ background: var(--nexa-surface);
41
+ color: var(--nexa-text);
42
+ border-radius: 8px;
43
+ text-decoration: none;
44
+ font-size: 1.05rem;
45
+ transition: all 0.25s ease;
46
+ border: 1px solid transparent;
47
+ }
48
+
49
+ .nav-sidebar li a:hover {
50
+ transform: translateY(-2px);
51
+ border-color: var(--nexa-border);
52
+ box-shadow: 0 0 12px var(--nexa-glow);
53
+ }
54
+
55
+ .nav-sidebar li a.active {
56
+ color: var(--nexa-accent);
57
+ border-color: var(--nexa-border);
58
+ box-shadow: 0 0 10px rgba(255, 207, 90, 0.2);
59
+ animation: nexaGlowPulse 3.4s ease-in-out infinite;
60
+ }
61
+
62
+ /* === MOBILE HEADER === */
63
+ .nav-mobile-header {
64
+ position: fixed;
65
+ top: 0;
66
+ left: 0;
67
+ width: 100%;
68
+ height: 60px;
69
+ background: rgba(7, 17, 31, 0.9);
70
+ backdrop-filter: blur(12px);
71
+ padding: 0 1.2rem;
72
+ display: flex;
73
+ align-items: center;
74
+ border-bottom: 1px solid var(--nexa-border);
75
+ box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
76
+ z-index: 20000;
77
+ }
78
+
79
+ /* === HAMBURGER BUTTON === */
80
+ .nav-hamburger {
81
+ display: flex;
82
+ flex-direction: column;
83
+ justify-content: space-between;
84
+ width: 34px;
85
+ height: 22px;
86
+ background: none;
87
+ border: none;
88
+ cursor: pointer;
89
+ z-index: 20001;
90
+ }
91
+
92
+ .nav-bar {
93
+ width: 100%;
94
+ height: 3px;
95
+ background-color: var(--nexa-primary);
96
+ border-radius: 2px;
97
+ transition: all 0.35s ease;
98
+ }
99
+
100
+ .nav-bar1.open {
101
+ transform: rotate(45deg) translate(5px, 5px);
102
+ }
103
+
104
+ .nav-bar2.open {
105
+ opacity: 0;
106
+ }
107
+
108
+ .nav-bar3.open {
109
+ transform: rotate(-45deg) translate(5px, -5px);
110
+ }
111
+
112
+ /* === MOBILE MODAL === */
113
+ .nav-mobile-modal {
114
+ position: fixed;
115
+ top: 0;
116
+ left: 0;
117
+ width: 100vw;
118
+ height: 100vh;
119
+ background: rgba(7, 17, 31, 0.96);
120
+ backdrop-filter: blur(10px);
121
+ display: flex;
122
+ justify-content: center;
123
+ align-items: flex-start;
124
+ padding-top: 60px;
125
+ z-index: 15000;
126
+ overflow-y: auto;
127
+ }
128
+
129
+ .nav-mobile-modal .nav-modal-links {
130
+ width: 100%;
131
+ max-height: calc(100vh - 60px);
132
+ display: flex;
133
+ flex-direction: column;
134
+ padding: 1rem;
135
+ box-sizing: border-box;
136
+ margin-top: 0;
137
+ }
138
+
139
+ .nav-mobile-modal .nav-modal-links li {
140
+ border-bottom: 1px solid var(--nexa-border);
141
+ margin-bottom: 0.4rem;
142
+ animation: fadeInUp 0.35s ease;
143
+ }
144
+
145
+ .nav-mobile-modal .nav-modal-links li:last-child {
146
+ border-bottom: none;
147
+ }
148
+
149
+ .nav-mobile-modal .nav-modal-links li a {
150
+ display: flex;
151
+ align-items: center;
152
+ justify-content: center;
153
+ background: var(--nexa-surface);
154
+ color: var(--nexa-text);
155
+ text-decoration: none;
156
+ font-size: 1.3rem;
157
+ font-weight: 600;
158
+ border-radius: 6px;
159
+ padding: 0.75rem 0;
160
+ transition: all 0.25s ease;
161
+ border: 1px solid transparent;
162
+ }
163
+
164
+ .nav-mobile-modal .nav-modal-links li a:hover {
165
+ border-color: var(--nexa-border);
166
+ box-shadow: 0 0 12px var(--nexa-glow);
167
+ }
168
+
169
+ .nav-mobile-modal .nav-modal-links li a.active {
170
+ color: var(--nexa-accent);
171
+ border-color: var(--nexa-border);
172
+ animation: nexaGlowPulse 3.4s ease-in-out infinite;
173
+ }
174
+
175
+ /* === RESPONSIVE === */
176
+ @media (max-width: 768px) {
177
+ .nav-sidebar {
178
+ display: none !important;
179
+ }
180
+
181
+ .nav-mobile-header {
182
+ display: flex;
183
+ }
184
+ }
185
+
186
+ /* === ANIMATIONS === */
187
+ @keyframes fadeInUp {
188
+ from {
189
+ opacity: 0;
190
+ transform: translateY(14px);
191
+ }
192
+ to {
193
+ opacity: 1;
194
+ transform: translateY(0);
195
+ }
196
+ }
197
+
198
+ @keyframes nexaGlowPulse {
199
+ 0% {
200
+ box-shadow: 0 0 0 rgba(62, 231, 255, 0);
201
+ }
202
+ 50% {
203
+ box-shadow:
204
+ 0 0 12px rgba(62, 231, 255, 0.18),
205
+ 0 0 18px rgba(255, 207, 90, 0.1);
206
+ }
207
+ 100% {
208
+ box-shadow: 0 0 0 rgba(62, 231, 255, 0);
209
+ }
210
+ }
211
+
212
+ /* Mobile top padding already handled in .app-container */
213
+ @media (max-width: 768px) {
214
+ .app-container {
215
+ padding-top: 60px;
216
+ }
217
+ }
@@ -0,0 +1,85 @@
1
+ import React, { useState, useEffect, useMemo } from "react";
2
+ import { NavLink, useLocation } from "react-router-dom";
3
+ import { routeMeta } from "../../config/routeMeta";
4
+ import "./Navbar.css";
5
+
6
+ function Navbar({ isMobile }) {
7
+ const location = useLocation();
8
+ const [menuOpen, setMenuOpen] = useState(false);
9
+
10
+ // Build nav items from routeMeta
11
+ const navItems = useMemo(() => {
12
+ return Object.entries(routeMeta)
13
+ .filter(([, meta]) => meta.showInNav)
14
+ .map(([path, meta]) => ({
15
+ path,
16
+ label: meta.navLabel || path,
17
+ }));
18
+ }, []);
19
+
20
+ // Close menu on route change
21
+ useEffect(() => {
22
+ setMenuOpen(false);
23
+ }, [location.pathname]);
24
+
25
+ const toggleMenu = () => setMenuOpen((prev) => !prev);
26
+
27
+ return (
28
+ <nav className="nav-wrapper">
29
+ {/* Mobile Header */}
30
+ {isMobile && (
31
+ <div className="nav-mobile-header">
32
+ <button
33
+ className="nav-hamburger"
34
+ onClick={toggleMenu}
35
+ aria-label="Toggle menu"
36
+ >
37
+ <div
38
+ className={
39
+ menuOpen ? "nav-bar nav-bar1 open" : "nav-bar nav-bar1"
40
+ }
41
+ />
42
+ <div
43
+ className={
44
+ menuOpen ? "nav-bar nav-bar2 open" : "nav-bar nav-bar2"
45
+ }
46
+ />
47
+ <div
48
+ className={
49
+ menuOpen ? "nav-bar nav-bar3 open" : "nav-bar nav-bar3"
50
+ }
51
+ />
52
+ </button>
53
+ </div>
54
+ )}
55
+
56
+ {/* Desktop Sidebar */}
57
+ {!isMobile && (
58
+ <ul className="nav-links nav-sidebar">
59
+ {navItems.map((item) => (
60
+ <li key={item.path}>
61
+ <NavLink to={item.path}>{item.label}</NavLink>
62
+ </li>
63
+ ))}
64
+ </ul>
65
+ )}
66
+
67
+ {/* Mobile Menu */}
68
+ {isMobile && menuOpen && (
69
+ <div className="nav-mobile-modal">
70
+ <ul className="nav-links nav-modal-links">
71
+ {navItems.map((item) => (
72
+ <li key={item.path}>
73
+ <NavLink to={item.path} onClick={toggleMenu}>
74
+ {item.label}
75
+ </NavLink>
76
+ </li>
77
+ ))}
78
+ </ul>
79
+ </div>
80
+ )}
81
+ </nav>
82
+ );
83
+ }
84
+
85
+ export default Navbar;
@@ -0,0 +1,2 @@
1
+ import Navbar from './Navbar';
2
+ export default Navbar;
@@ -0,0 +1,116 @@
1
+ .nexa-page {
2
+ width: 100%;
3
+ max-width: 1100px;
4
+ margin: 0 auto;
5
+ padding: 24px;
6
+ }
7
+
8
+ .nexa-hero {
9
+ margin-bottom: 28px;
10
+ padding: 24px;
11
+ border: 1px solid rgba(255, 215, 0, 0.2);
12
+ border-radius: 18px;
13
+ background: linear-gradient(
14
+ 180deg,
15
+ rgba(255, 215, 0, 0.06),
16
+ rgba(0, 255, 255, 0.04)
17
+ );
18
+ box-shadow: 0 0 24px rgba(255, 215, 0, 0.06);
19
+ }
20
+
21
+ .nexa-eyebrow {
22
+ margin: 0 0 10px;
23
+ font-size: 12px;
24
+ letter-spacing: 0.16em;
25
+ text-transform: uppercase;
26
+ color: #ffd700;
27
+ }
28
+
29
+ .nexa-title {
30
+ margin: 0 0 14px;
31
+ font-size: clamp(2rem, 4vw, 3rem);
32
+ line-height: 1.15;
33
+ color: #00ffff;
34
+ }
35
+
36
+ .nexa-description {
37
+ margin: 0;
38
+ max-width: 760px;
39
+ font-size: 1rem;
40
+ color: #b8c4d6;
41
+ }
42
+
43
+ .nexa-grid {
44
+ display: grid;
45
+ grid-template-columns: repeat(3, minmax(0, 1fr));
46
+ gap: 18px;
47
+ margin-bottom: 28px;
48
+ }
49
+
50
+ .nexa-card {
51
+ padding: 20px;
52
+ border-radius: 16px;
53
+ background: rgba(255, 255, 255, 0.03);
54
+ border: 1px solid rgba(255, 215, 0, 0.14);
55
+ transition:
56
+ transform 0.2s ease,
57
+ box-shadow 0.2s ease,
58
+ border-color 0.2s ease;
59
+ }
60
+
61
+ .nexa-card:hover {
62
+ transform: translateY(-2px);
63
+ border-color: rgba(255, 215, 0, 0.3);
64
+ box-shadow: 0 8px 24px rgba(255, 215, 0, 0.08);
65
+ }
66
+
67
+ .nexa-card h3 {
68
+ margin: 0 0 10px;
69
+ font-size: 1rem;
70
+ color: #ffd700;
71
+ }
72
+
73
+ .nexa-card p {
74
+ margin: 0;
75
+ color: #b8c4d6;
76
+ }
77
+
78
+ .nexa-section {
79
+ padding: 22px;
80
+ border-radius: 16px;
81
+ background: rgba(255, 255, 255, 0.02);
82
+ border: 1px solid rgba(0, 255, 255, 0.14);
83
+ }
84
+
85
+ .nexa-section-title {
86
+ margin: 0 0 12px;
87
+ font-size: 1.1rem;
88
+ color: #00ffff;
89
+ }
90
+
91
+ .nexa-section-text {
92
+ margin: 0;
93
+ color: #b8c4d6;
94
+ }
95
+
96
+ @media (max-width: 900px) {
97
+ .nexa-grid {
98
+ grid-template-columns: 1fr;
99
+ }
100
+ }
101
+
102
+ @media (max-width: 768px) {
103
+ .nexa-page {
104
+ padding: 16px;
105
+ }
106
+
107
+ .nexa-hero,
108
+ .nexa-card,
109
+ .nexa-section {
110
+ padding: 18px;
111
+ }
112
+
113
+ .nexa-title {
114
+ font-size: 2rem;
115
+ }
116
+ }
@@ -0,0 +1,56 @@
1
+ import React from "react";
2
+ import "./Nexa.css";
3
+
4
+ const Nexa = () => {
5
+ return (
6
+ <section className="nexa-page">
7
+ <div className="nexa-hero">
8
+ <p className="nexa-eyebrow">Generated Page</p>
9
+
10
+ <h2 className="nexa-title">Welcome to Nexa</h2>
11
+
12
+ <p className="nexa-description">
13
+ This page exists to prove that routing, navigation, and the dynamic
14
+ header are all wired correctly inside the shared application shell.
15
+ </p>
16
+ </div>
17
+
18
+ <div className="nexa-grid">
19
+ <article className="nexa-card">
20
+ <h3>Shared Layout</h3>
21
+ <p>
22
+ This page is rendered inside the same shell as Home, so the sidebar,
23
+ header, and content spacing remain fully consistent.
24
+ </p>
25
+ </article>
26
+
27
+ <article className="nexa-card">
28
+ <h3>Dynamic Header</h3>
29
+ <p>
30
+ The title, subtitle, and tooltip are pulled from the shared route
31
+ metadata, so the header stays synchronized with navigation.
32
+ </p>
33
+ </article>
34
+
35
+ <article className="nexa-card">
36
+ <h3>CLI Ready</h3>
37
+ <p>
38
+ This is the kind of starter page a generator can create instantly so
39
+ users see a working system instead of a blank app.
40
+ </p>
41
+ </article>
42
+ </div>
43
+
44
+ <div className="nexa-section">
45
+ <h3 className="nexa-section-title">Why this page exists</h3>
46
+ <p className="nexa-section-text">
47
+ Nexa is not just about creating files. It is about creating a usable
48
+ application frame with real navigation, responsive behavior, and a
49
+ content area that already understands how the app should work.
50
+ </p>
51
+ </div>
52
+ </section>
53
+ );
54
+ };
55
+
56
+ export default Nexa;
@@ -0,0 +1,16 @@
1
+ export const routeMeta = {
2
+ "/": {
3
+ navLabel: "Home",
4
+ title: "Nexa Home",
5
+ subtitle: "Start building instantly with Nexa CLI",
6
+ tooltip: "This is your main landing page",
7
+ showInNav: true,
8
+ },
9
+ "/nexa": {
10
+ navLabel: "Nexa",
11
+ title: "Nexa Page",
12
+ subtitle: "Generated instantly by Nexa CLI",
13
+ tooltip: "This page was auto-generated by the Nexa CLI",
14
+ showInNav: true,
15
+ },
16
+ };
File without changes
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import App from "./App.jsx";
4
+ import "./index.css";
5
+ import { BrowserRouter } from "react-router-dom";
6
+
7
+ ReactDOM.createRoot(document.getElementById("root")).render(
8
+ <React.StrictMode>
9
+ <BrowserRouter>
10
+ <App />
11
+ </BrowserRouter>
12
+ </React.StrictMode>
13
+ );