@farihatang/react-ui 0.1.0-beta.2 → 0.1.0-beta.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/dist/index.css +1 -0
- package/dist/index.js +94 -104
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +94 -104
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -3
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:IBM Plex Sans,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:IBM Plex Mono,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.visible{visibility:visible}.fixed{position:fixed}.inset-x-0{left:0;right:0}.top-0{top:0}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mt-3{margin-top:.75rem}.inline-block{display:inline-block}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.hidden{display:none}.h-11{height:2.75rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-8{height:2rem}.h-9{height:2.25rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-full{width:100%}.max-w-6xl{max-width:72rem}.shrink-0{flex-shrink:0}@keyframes spin{to{transform:rotate(1turn)}}.animate-spin{animation:spin 1s linear infinite}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:8px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:14px}.rounded-md{border-radius:10px}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-\[\#6366f1\]\/30{border-color:rgba(99,102,241,.3)}.border-black\/5{border-color:rgba(0,0,0,.05)}.border-surface-3{--tw-border-opacity:1;border-color:rgb(232 234 237/var(--tw-border-opacity,1))}.border-white\/5{border-color:hsla(0,0%,100%,.05)}.bg-\[\#060912\]\/80{background-color:rgba(6,9,18,.8)}.bg-\[\#060912\]\/95{background-color:rgba(6,9,18,.95)}.bg-\[\#6366f1\]\/10{background-color:rgba(99,102,241,.1)}.bg-\[\#f8f7f4\]\/90{background-color:hsla(45,22%,96%,.9)}.bg-\[\#f8f7f4\]\/95{background-color:hsla(45,22%,96%,.95)}.bg-brand{--tw-bg-opacity:1;background-color:rgb(0 200 150/var(--tw-bg-opacity,1))}.bg-danger{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity,1))}.bg-surface-2{--tw-bg-opacity:1;background-color:rgb(241 243 246/var(--tw-bg-opacity,1))}.bg-transparent{background-color:transparent}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.font-sans{font-family:IBM Plex Sans,sans-serif}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-extrabold{font-weight:800}.font-medium{font-weight:500}.tracking-tight{letter-spacing:-.025em}.text-\[\#0f0f0f\]{--tw-text-opacity:1;color:rgb(15 15 15/var(--tw-text-opacity,1))}.text-\[\#5b50f0\]{--tw-text-opacity:1;color:rgb(91 80 240/var(--tw-text-opacity,1))}.text-\[\#6366f1\]{--tw-text-opacity:1;color:rgb(99 102 241/var(--tw-text-opacity,1))}.text-\[\#64748b\]{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-\[\#6b7280\]{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-ink{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-ink-secondary{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/20{color:hsla(0,0%,100%,.2)}.opacity-25{opacity:.25}.opacity-75{opacity:.75}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-lg{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -4px rgba(0,0,0,.1);--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color),0 4px 6px -4px var(--tw-shadow-color)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-\[\#5b50f0\]\/25{--tw-shadow-color:rgba(91,80,240,.25);--tw-shadow:var(--tw-shadow-colored)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-colors{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-500{transition-duration:.5s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.\[background\:linear-gradient\(135deg\2c \#5b50f0\2c \#7c3aed\)\]{background:linear-gradient(135deg,#5b50f0,#7c3aed)}.hover\:scale-\[1\.03\]:hover{--tw-scale-x:1.03;--tw-scale-y:1.03;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-\[\#6366f1\]:hover{--tw-border-opacity:1;border-color:rgb(99 102 241/var(--tw-border-opacity,1))}.hover\:bg-\[\#6366f1\]:hover{--tw-bg-opacity:1;background-color:rgb(99 102 241/var(--tw-bg-opacity,1))}.hover\:bg-black\/5:hover{background-color:rgba(0,0,0,.05)}.hover\:bg-brand-600:hover{--tw-bg-opacity:1;background-color:rgb(13 148 136/var(--tw-bg-opacity,1))}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-surface-2:hover{--tw-bg-opacity:1;background-color:rgb(241 243 246/var(--tw-bg-opacity,1))}.hover\:bg-surface-3:hover{--tw-bg-opacity:1;background-color:rgb(232 234 237/var(--tw-bg-opacity,1))}.hover\:text-\[\#0f0f0f\]:hover{--tw-text-opacity:1;color:rgb(15 15 15/var(--tw-text-opacity,1))}.hover\:text-\[\#e2e8f0\]:hover{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:shadow-\[\#5b50f0\]\/40:hover{--tw-shadow-color:rgba(91,80,240,.4);--tw-shadow:var(--tw-shadow-colored)}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-brand:focus-visible{--tw-ring-opacity:1;--tw-ring-color:rgb(0 200 150/var(--tw-ring-opacity,1))}.focus-visible\:ring-offset-1:focus-visible{--tw-ring-offset-width:1px}.active\:bg-brand-700:active{--tw-bg-opacity:1;background-color:rgb(15 118 110/var(--tw-bg-opacity,1))}.active\:bg-red-700:active{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.active\:bg-surface-3:active{--tw-bg-opacity:1;background-color:rgb(232 234 237/var(--tw-bg-opacity,1))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}@media (min-width:768px){.md\:flex{display:flex}.md\:inline-flex{display:inline-flex}.md\:hidden{display:none}}
|
package/dist/index.js
CHANGED
|
@@ -140,64 +140,33 @@ var DEFAULT_LINKS = [
|
|
|
140
140
|
{ label: "Contact", href: "#contact" }
|
|
141
141
|
];
|
|
142
142
|
var tokens = {
|
|
143
|
-
|
|
143
|
+
dark: {
|
|
144
144
|
nav: {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
scrolledClass: "backdrop-blur-md shadow-sm"
|
|
148
|
-
},
|
|
149
|
-
logo: { color: "#0f0f0f" },
|
|
150
|
-
logoAccent: { color: "#5b50f0" },
|
|
151
|
-
link: "text-gray-500 hover:bg-black/5 hover:text-gray-900 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200",
|
|
152
|
-
cta: {
|
|
153
|
-
className: "text-white shadow-lg hover:scale-[1.03] transition-all duration-200",
|
|
154
|
-
style: {
|
|
155
|
-
background: "linear-gradient(135deg, #5b50f0, #7c3aed)",
|
|
156
|
-
boxShadow: "0 4px 14px rgba(91,80,240,0.35)"
|
|
157
|
-
}
|
|
145
|
+
base: "bg-transparent",
|
|
146
|
+
scrolled: "bg-[#060912]/80 backdrop-blur-md border-b border-white/5"
|
|
158
147
|
},
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
style: { background: "linear-gradient(135deg, #5b50f0, #7c3aed)" }
|
|
168
|
-
}
|
|
148
|
+
logo: "text-[#6366f1]",
|
|
149
|
+
logoAccent: "text-white/20",
|
|
150
|
+
link: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
151
|
+
cta: "bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1] hover:bg-[#6366f1] hover:text-white hover:border-[#6366f1]",
|
|
152
|
+
menuToggle: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
153
|
+
mobileMenu: "bg-[#060912]/95 backdrop-blur-md border-t border-white/5",
|
|
154
|
+
mobileLink: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
155
|
+
mobileCta: "bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1]"
|
|
169
156
|
},
|
|
170
|
-
|
|
157
|
+
light: {
|
|
171
158
|
nav: {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
scrolledClass: "backdrop-blur-md border-b border-white/5"
|
|
175
|
-
},
|
|
176
|
-
logo: { color: "#6366f1" },
|
|
177
|
-
logoAccent: { color: "rgba(255,255,255,0.20)" },
|
|
178
|
-
link: "text-slate-500 hover:text-slate-100 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200",
|
|
179
|
-
cta: {
|
|
180
|
-
className: "border transition-all duration-200 hover:text-white",
|
|
181
|
-
style: {
|
|
182
|
-
background: "rgba(99,102,241,0.10)",
|
|
183
|
-
borderColor: "rgba(99,102,241,0.30)",
|
|
184
|
-
color: "#6366f1"
|
|
185
|
-
}
|
|
186
|
-
},
|
|
187
|
-
menuToggle: "text-slate-500 hover:text-slate-100",
|
|
188
|
-
mobileMenu: {
|
|
189
|
-
className: "backdrop-blur-md border-t border-white/5",
|
|
190
|
-
style: { background: "rgba(6,9,18,0.95)" }
|
|
159
|
+
base: "bg-transparent",
|
|
160
|
+
scrolled: "bg-[#f8f7f4]/90 backdrop-blur-md shadow-sm"
|
|
191
161
|
},
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
}
|
|
162
|
+
logo: "text-[#0f0f0f]",
|
|
163
|
+
logoAccent: "text-[#5b50f0]",
|
|
164
|
+
link: "text-[#6b7280] hover:bg-black/5 hover:text-[#0f0f0f]",
|
|
165
|
+
cta: "[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white shadow-lg shadow-[#5b50f0]/25 hover:shadow-[#5b50f0]/40 hover:scale-[1.03]",
|
|
166
|
+
menuToggle: "text-[#6b7280] hover:text-[#0f0f0f]",
|
|
167
|
+
mobileMenu: "bg-[#f8f7f4]/95 backdrop-blur-md border-t border-black/5",
|
|
168
|
+
mobileLink: "text-[#6b7280] hover:text-[#0f0f0f]",
|
|
169
|
+
mobileCta: "[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white"
|
|
201
170
|
}
|
|
202
171
|
};
|
|
203
172
|
function NavBar({
|
|
@@ -219,60 +188,81 @@ function NavBar({
|
|
|
219
188
|
window.addEventListener("scroll", handler, { passive: true });
|
|
220
189
|
return () => window.removeEventListener("scroll", handler);
|
|
221
190
|
}, [scrollEffect, scrollThreshold]);
|
|
222
|
-
const
|
|
223
|
-
const
|
|
224
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
"aria-label": menuOpen ? "Close menu" : "Open menu",
|
|
247
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
248
|
-
"svg",
|
|
191
|
+
const navPy = scrolled ? "py-3" : "py-5";
|
|
192
|
+
const navBg = scrolled ? t.nav.scrolled : t.nav.base;
|
|
193
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
194
|
+
"nav",
|
|
195
|
+
{
|
|
196
|
+
role: "navigation",
|
|
197
|
+
"aria-label": "Main navigation",
|
|
198
|
+
className: `fixed top-0 inset-x-0 z-50 transition-all duration-500 ${navPy} ${navBg}`,
|
|
199
|
+
children: [
|
|
200
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-6xl mx-auto px-6 flex items-center justify-between", children: [
|
|
201
|
+
/* @__PURE__ */ jsxRuntime.jsxs("a", { href: "#", className: `font-sans font-extrabold text-lg tracking-tight ${t.logo}`, children: [
|
|
202
|
+
logo,
|
|
203
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: t.logoAccent, children: logoAccent })
|
|
204
|
+
] }),
|
|
205
|
+
/* @__PURE__ */ jsxRuntime.jsx("ul", { className: "hidden md:flex items-center gap-1", role: "list", children: links.map((link) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
206
|
+
"a",
|
|
207
|
+
{
|
|
208
|
+
href: link.href,
|
|
209
|
+
className: `font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200 ${t.link}`,
|
|
210
|
+
children: link.label
|
|
211
|
+
}
|
|
212
|
+
) }, link.label)) }),
|
|
213
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
214
|
+
"a",
|
|
249
215
|
{
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
216
|
+
href: ctaHref,
|
|
217
|
+
className: `hidden md:inline-flex items-center px-5 py-2.5 rounded-full font-sans font-bold text-sm transition-all duration-200 ${t.cta}`,
|
|
218
|
+
children: ctaLabel
|
|
219
|
+
}
|
|
220
|
+
),
|
|
221
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
222
|
+
"button",
|
|
223
|
+
{
|
|
224
|
+
className: `md:hidden transition-colors ${t.menuToggle}`,
|
|
225
|
+
onClick: () => setMenuOpen((prev) => !prev),
|
|
226
|
+
"aria-expanded": menuOpen,
|
|
227
|
+
"aria-label": menuOpen ? "Close menu" : "Open menu",
|
|
228
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
229
|
+
"svg",
|
|
230
|
+
{
|
|
231
|
+
width: "22",
|
|
232
|
+
height: "22",
|
|
233
|
+
viewBox: "0 0 24 24",
|
|
234
|
+
fill: "none",
|
|
235
|
+
stroke: "currentColor",
|
|
236
|
+
strokeWidth: "2",
|
|
237
|
+
children: menuOpen ? /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" }) : /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 12h18M3 6h18M3 18h18" })
|
|
238
|
+
}
|
|
239
|
+
)
|
|
257
240
|
}
|
|
258
241
|
)
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
242
|
+
] }),
|
|
243
|
+
menuOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `md:hidden mt-3 ${t.mobileMenu}`, children: /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: "max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4", role: "list", children: [
|
|
244
|
+
links.map((link) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
245
|
+
"a",
|
|
246
|
+
{
|
|
247
|
+
href: link.href,
|
|
248
|
+
onClick: () => setMenuOpen(false),
|
|
249
|
+
className: `font-sans font-medium text-base transition-colors ${t.mobileLink}`,
|
|
250
|
+
children: link.label
|
|
251
|
+
}
|
|
252
|
+
) }, link.label)),
|
|
253
|
+
/* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
254
|
+
"a",
|
|
255
|
+
{
|
|
256
|
+
href: ctaHref,
|
|
257
|
+
onClick: () => setMenuOpen(false),
|
|
258
|
+
className: `inline-block px-5 py-2.5 rounded-full font-sans font-bold text-sm ${t.mobileCta}`,
|
|
259
|
+
children: ctaLabel
|
|
260
|
+
}
|
|
261
|
+
) })
|
|
262
|
+
] }) })
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
);
|
|
276
266
|
}
|
|
277
267
|
|
|
278
268
|
exports.Button = Button;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cn.ts","../src/components/Button/Button.tsx","../src/components/NavBar/NavBar.tsx"],"names":["clsx","jsxs","jsx","React","useState","useEffect"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEO,SAAS,MAAM,MAAA,EAA8B;AAClD,EAAA,OAAOA,UAAK,MAAM,CAAA;AACpB;ACiBA,IAAM,aAAA,GAA+C;AAAA,EACnD,OAAA,EAAS,sEAAA;AAAA,EACT,SAAA,EAAW,sFAAA;AAAA,EACX,KAAA,EAAO,0EAAA;AAAA,EACP,MAAA,EAAQ;AACV,CAAA;AAEA,IAAM,UAAA,GAAyC;AAAA,EAC7C,EAAA,EAAI,kCAAA;AAAA,EACJ,EAAA,EAAI,mCAAA;AAAA,EACJ,EAAA,EAAI;AACN,CAAA;AAEA,SAAS,OAAA,CAAQ,EAAE,SAAA,EAAU,EAA2B;AACtD,EAAA,uBACEC,eAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA,CAAG,cAAA,EAAgB,SAAS,CAAA;AAAA,MACvC,KAAA,EAAM,4BAAA;AAAA,MACN,IAAA,EAAK,MAAA;AAAA,MACL,OAAA,EAAQ,WAAA;AAAA,MACR,aAAA,EAAY,MAAA;AAAA,MAEZ,QAAA,EAAA;AAAA,wBAAAC,cAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,YAAA,EAAa,EAAA,EAAG,IAAA,EAAK,EAAA,EAAG,IAAA,EAAK,CAAA,EAAE,IAAA,EAAK,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,GAAA,EAAI,CAAA;AAAA,wBAC5FA,cAAA;AAAA,UAAC,MAAA;AAAA,UAAA;AAAA,YACC,SAAA,EAAU,YAAA;AAAA,YACV,IAAA,EAAK,cAAA;AAAA,YACL,CAAA,EAAE;AAAA;AAAA;AACJ;AAAA;AAAA,GACF;AAEJ;AAEO,IAAM,SAASC,sBAAA,CAAM,UAAA;AAAA,EAC1B,CACE,IAYA,GAAA,KACG;AAbH,IAAA,IAAA,EAAA,GAAA,EAAA,EACE;AAAA,MAAA,OAAA,GAAU,SAAA;AAAA,MACV,IAAA,GAAO,IAAA;AAAA,MACP,OAAA,GAAU,KAAA;AAAA,MACV,WAAA;AAAA,MACA,YAAA;AAAA,MACA,SAAA,GAAY,KAAA;AAAA,MACZ,QAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KAhEN,GAuDI,EAAA,EAUK,KAAA,GAAA,SAAA,CAVL,EAAA,EAUK;AAAA,MATH,SAAA;AAAA,MACA,MAAA;AAAA,MACA,SAAA;AAAA,MACA,aAAA;AAAA,MACA,cAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA;AAAA,KAAA,CAAA;AAKF,IAAA,MAAM,aAAa,QAAA,IAAY,OAAA;AAE/B,IAAA,uBACEF,eAAA;AAAA,MAAC,QAAA;AAAA,MAAA,aAAA,CAAA,cAAA,CAAA;AAAA,QACC,GAAA;AAAA,QACA,QAAA,EAAU,UAAA;AAAA,QACV,WAAA,EAAW,OAAA;AAAA,QACX,SAAA,EAAW,EAAA;AAAA,UACT,+DAAA;AAAA,UACA,yCAAA;AAAA,UACA,sGAAA;AAAA,UACA,kDAAA;AAAA,UACA,+BAAA;AAAA,UACA,cAAc,OAAO,CAAA;AAAA,UACrB,WAAW,IAAI,CAAA;AAAA,UACf,SAAA,IAAa,QAAA;AAAA,UACb;AAAA;AACF,OAAA,EACI,KAAA,CAAA,EAfL;AAAA,QAiBE,QAAA,EAAA;AAAA,UAAA,OAAA,mBACCC,cAAA;AAAA,YAAC,OAAA;AAAA,YAAA;AAAA,cACC,SAAA,EAAW,GAAG,IAAA,KAAS,IAAA,GAAO,YAAY,IAAA,KAAS,IAAA,GAAO,YAAY,aAAa;AAAA;AAAA,WACrF,GAEA,+BACEA,cAAA,CAAC,MAAA,EAAA,EAAK,WAAU,UAAA,EAAW,aAAA,EAAY,QACpC,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,UAGH,QAAA,oBAAYA,cAAA,CAAC,MAAA,EAAA,EAAM,QAAA,EAAS,CAAA;AAAA,UAC5B,CAAC,WAAW,YAAA,oBACXA,cAAA,CAAC,UAAK,SAAA,EAAU,UAAA,EAAW,aAAA,EAAY,MAAA,EACpC,QAAA,EAAA,YAAA,EACH;AAAA;AAAA,OAAA;AAAA,KAEJ;AAAA,EAEJ;AACF;AAEA,MAAA,CAAO,WAAA,GAAc,QAAA;AC/ErB,IAAM,aAAA,GAA2B;AAAA,EAC/B,EAAE,KAAA,EAAO,OAAA,EAAS,IAAA,EAAM,QAAA,EAAS;AAAA,EACjC,EAAE,KAAA,EAAO,YAAA,EAAc,IAAA,EAAM,aAAA,EAAc;AAAA,EAC3C,EAAE,KAAA,EAAO,UAAA,EAAY,IAAA,EAAM,WAAA,EAAY;AAAA,EACvC,EAAE,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,UAAA;AAC5B,CAAA;AAqCA,IAAM,MAAA,GAAgD;AAAA,EACpD,KAAA,EAAO;AAAA,IACL,GAAA,EAAK;AAAA,MACH,SAAA,EAAW,EAAE,UAAA,EAAY,aAAA,EAAc;AAAA,MACvC,aAAA,EAAe,EAAE,UAAA,EAAY,wBAAA,EAAyB;AAAA,MACtD,aAAA,EAAe;AAAA,KACjB;AAAA,IACA,IAAA,EAAM,EAAE,KAAA,EAAO,SAAA,EAAU;AAAA,IACzB,UAAA,EAAY,EAAE,KAAA,EAAO,SAAA,EAAU;AAAA,IAC/B,IAAA,EAAM,qIAAA;AAAA,IACN,GAAA,EAAK;AAAA,MACH,SAAA,EAAW,qEAAA;AAAA,MACX,KAAA,EAAO;AAAA,QACL,UAAA,EAAY,2CAAA;AAAA,QACZ,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,UAAA,EAAY,mCAAA;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,SAAA,EAAW,0CAAA;AAAA,MACX,KAAA,EAAO,EAAE,UAAA,EAAY,wBAAA;AAAyB,KAChD;AAAA,IACA,UAAA,EACE,qFAAA;AAAA,IACF,SAAA,EAAW;AAAA,MACT,SAAA,EAAW,wCAAA;AAAA,MACX,KAAA,EAAO,EAAE,UAAA,EAAY,2CAAA;AAA4C;AACnE,GACF;AAAA,EAEA,IAAA,EAAM;AAAA,IACJ,GAAA,EAAK;AAAA,MACH,SAAA,EAAW,EAAE,UAAA,EAAY,aAAA,EAAc;AAAA,MACvC,aAAA,EAAe,EAAE,UAAA,EAAY,mBAAA,EAAoB;AAAA,MACjD,aAAA,EAAe;AAAA,KACjB;AAAA,IACA,IAAA,EAAM,EAAE,KAAA,EAAO,SAAA,EAAU;AAAA,IACzB,UAAA,EAAY,EAAE,KAAA,EAAO,wBAAA,EAAyB;AAAA,IAC9C,IAAA,EAAM,sHAAA;AAAA,IACN,GAAA,EAAK;AAAA,MACH,SAAA,EAAW,qDAAA;AAAA,MACX,KAAA,EAAO;AAAA,QACL,UAAA,EAAY,uBAAA;AAAA,QACZ,WAAA,EAAa,uBAAA;AAAA,QACb,KAAA,EAAO;AAAA;AACT,KACF;AAAA,IACA,UAAA,EAAY,qCAAA;AAAA,IACZ,UAAA,EAAY;AAAA,MACV,SAAA,EAAW,0CAAA;AAAA,MACX,KAAA,EAAO,EAAE,UAAA,EAAY,mBAAA;AAAoB,KAC3C;AAAA,IACA,UAAA,EACE,uFAAA;AAAA,IACF,SAAA,EAAW;AAAA,MACT,SAAA,EAAW,oCAAA;AAAA,MACX,KAAA,EAAO;AAAA,QACL,UAAA,EAAY,uBAAA;AAAA,QACZ,WAAA,EAAa,uBAAA;AAAA,QACb,KAAA,EAAO;AAAA;AACT;AACF;AAEJ,CAAA;AAIO,SAAS,MAAA,CAAO;AAAA,EACrB,KAAA,GAAQ,OAAA;AAAA,EACR,IAAA,GAAO,QAAA;AAAA,EACP,UAAA,GAAa,GAAA;AAAA,EACb,KAAA,GAAQ,aAAA;AAAA,EACR,QAAA,GAAW,SAAA;AAAA,EACX,OAAA,GAAU,UAAA;AAAA,EACV,YAAA,GAAe,IAAA;AAAA,EACf,eAAA,GAAkB;AACpB,CAAA,EAAgB;AACd,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIE,eAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,CAAC,QAAA,EAAU,WAAW,CAAA,GAAIA,eAAS,KAAK,CAAA;AAC9C,EAAA,MAAM,CAAA,GAAI,OAAO,KAAK,CAAA;AAEtB,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,YAAA,EAAc;AACnB,IAAA,MAAM,OAAA,GAAU,MAAM,WAAA,CAAY,MAAA,CAAO,UAAU,eAAe,CAAA;AAClE,IAAA,MAAA,CAAO,iBAAiB,QAAA,EAAU,OAAA,EAAS,EAAE,OAAA,EAAS,MAAM,CAAA;AAC5D,IAAA,OAAO,MAAM,MAAA,CAAO,mBAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AAAA,EAC3D,CAAA,EAAG,CAAC,YAAA,EAAc,eAAe,CAAC,CAAA;AAElC,EAAA,MAAM,WAA0B,QAAA,GAC5B,aAAA,CAAA,cAAA,CAAA,EAAA,EAAK,CAAA,CAAE,GAAA,CAAI,gBAAX,EAA0B,UAAA,EAAY,eAAA,EAAgB,CAAA,GACtD,iCAAK,CAAA,CAAE,GAAA,CAAI,SAAA,CAAA,EAAX,EAAsB,YAAY,eAAA,EAAgB,CAAA;AAEtD,EAAA,MAAM,QAAA,GAAW,8BAA8B,QAAA,GAAW,CAAA,KAAA,EAAQ,EAAE,GAAA,CAAI,aAAa,KAAK,MAAM,CAAA,CAAA;AAEhG,EAAA,uBACEJ,eAAAA,CAAC,KAAA,EAAA,EAAI,IAAA,EAAK,YAAA,EAAa,cAAW,iBAAA,EAAkB,SAAA,EAAW,QAAA,EAAU,KAAA,EAAO,QAAA,EAC9E,QAAA,EAAA;AAAA,oBAAAA,eAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0DAAA,EAEb,QAAA,EAAA;AAAA,sBAAAA,eAAAA,CAAC,OAAE,IAAA,EAAK,GAAA,EAAI,WAAU,iDAAA,EAAkD,KAAA,EAAO,EAAE,IAAA,EAC9E,QAAA,EAAA;AAAA,QAAA,IAAA;AAAA,wBACDC,cAAAA,CAAC,MAAA,EAAA,EAAK,KAAA,EAAO,CAAA,CAAE,YAAa,QAAA,EAAA,UAAA,EAAW;AAAA,OAAA,EACzC,CAAA;AAAA,sBAGAA,cAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,mCAAA,EAAoC,IAAA,EAAK,MAAA,EACpD,QAAA,EAAA,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,qBACTA,cAAAA,CAAC,IAAA,EAAA,EACC,QAAA,kBAAAA,cAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,SAAA,EAAW,CAAA,CAAE,IAAA,EAC9B,QAAA,EAAA,IAAA,CAAK,KAAA,EACR,CAAA,EAAA,EAHO,IAAA,CAAK,KAId,CACD,CAAA,EACH,CAAA;AAAA,sBAGAA,cAAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAM,OAAA;AAAA,UACN,SAAA,EAAW,CAAA,4DAAA,EAA+D,CAAA,CAAE,GAAA,CAAI,SAAS,CAAA,CAAA;AAAA,UACzF,KAAA,EAAO,EAAE,GAAA,CAAI,KAAA;AAAA,UAEZ,QAAA,EAAA;AAAA;AAAA,OACH;AAAA,sBAGAA,cAAAA;AAAA,QAAC,QAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,CAAA,4BAAA,EAA+B,CAAA,CAAE,UAAU,CAAA,CAAA;AAAA,UACtD,OAAA,EAAS,MAAM,WAAA,CAAY,CAAA,IAAA,KAAQ,CAAC,IAAI,CAAA;AAAA,UACxC,eAAA,EAAe,QAAA;AAAA,UACf,YAAA,EAAY,WAAW,YAAA,GAAe,WAAA;AAAA,UAEtC,QAAA,kBAAAA,cAAAA;AAAA,YAAC,KAAA;AAAA,YAAA;AAAA,cACC,KAAA,EAAM,IAAA;AAAA,cACN,MAAA,EAAO,IAAA;AAAA,cACP,OAAA,EAAQ,WAAA;AAAA,cACR,IAAA,EAAK,MAAA;AAAA,cACL,MAAA,EAAO,cAAA;AAAA,cACP,WAAA,EAAY,GAAA;AAAA,cAEX,QAAA,EAAA,QAAA,mBAAWA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sBAAA,EAAuB,CAAA,mBAAKA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,yBAAA,EAA0B;AAAA;AAAA;AACpF;AAAA;AACF,KAAA,EACF,CAAA;AAAA,IAGC,QAAA,oBACCA,cAAAA,CAAC,KAAA,EAAA,EAAI,WAAW,CAAA,eAAA,EAAkB,CAAA,CAAE,WAAW,SAAS,CAAA,CAAA,EAAI,OAAO,CAAA,CAAE,UAAA,CAAW,OAC9E,QAAA,kBAAAD,eAAAA,CAAC,QAAG,SAAA,EAAU,iDAAA,EAAkD,MAAK,MAAA,EAClE,QAAA,EAAA;AAAA,MAAA,KAAA,CAAM,GAAA,CAAI,CAAA,IAAA,qBACTC,cAAAA,CAAC,IAAA,EAAA,EACC,0BAAAA,cAAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAM,IAAA,CAAK,IAAA,EAAM,OAAA,EAAS,MAAM,WAAA,CAAY,KAAK,CAAA,EAAG,SAAA,EAAW,CAAA,CAAE,UAAA,EACjE,eAAK,KAAA,EACR,CAAA,EAAA,EAHO,IAAA,CAAK,KAId,CACD,CAAA;AAAA,sBACDA,cAAAA,CAAC,IAAA,EAAA,EACC,QAAA,kBAAAA,cAAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAM,OAAA;AAAA,UACN,OAAA,EAAS,MAAM,WAAA,CAAY,KAAK,CAAA;AAAA,UAChC,SAAA,EAAW,CAAA,sCAAA,EAAyC,CAAA,CAAE,SAAA,CAAU,SAAS,CAAA,CAAA;AAAA,UACzE,KAAA,EAAO,EAAE,SAAA,CAAU,KAAA;AAAA,UAElB,QAAA,EAAA;AAAA;AAAA,OACH,EACF;AAAA,KAAA,EACF,CAAA,EACF;AAAA,GAAA,EAEJ,CAAA;AAEJ","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return clsx(inputs);\n}\n","import React from 'react';\nimport { cn } from '@/lib/cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant */\n variant?: ButtonVariant;\n /** Size preset */\n size?: ButtonSize;\n /** Show loading spinner and disable interaction */\n loading?: boolean;\n /** Icon rendered before label */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after label */\n trailingIcon?: React.ReactNode;\n /** Stretch to fill container width */\n fullWidth?: boolean;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary: 'bg-brand text-white hover:bg-brand-600 active:bg-brand-700 shadow-sm',\n secondary: 'bg-surface-2 text-ink border border-surface-3 hover:bg-surface-3 active:bg-surface-3',\n ghost: 'bg-transparent text-ink-secondary hover:bg-surface-2 active:bg-surface-3',\n danger: 'bg-danger text-white hover:bg-red-600 active:bg-red-700 shadow-sm',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: 'h-8 px-3 text-xs gap-1.5 rounded',\n md: 'h-9 px-4 text-sm gap-2 rounded-md',\n lg: 'h-11 px-6 text-sm gap-2.5 rounded-lg',\n};\n\nfunction Spinner({ className }: { className?: string }) {\n return (\n <svg\n className={cn('animate-spin', className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const isDisabled = disabled || loading;\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-busy={loading}\n className={cn(\n 'inline-flex items-center justify-center font-sans font-medium',\n 'transition-all duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1',\n 'disabled:opacity-50 disabled:pointer-events-none',\n 'select-none whitespace-nowrap',\n variantStyles[variant],\n sizeStyles[size],\n fullWidth && 'w-full',\n className\n )}\n {...props}\n >\n {loading ? (\n <Spinner\n className={cn(size === 'sm' ? 'h-3 w-3' : size === 'lg' ? 'h-4 w-4' : 'h-3.5 w-3.5')}\n />\n ) : (\n leadingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {leadingIcon}\n </span>\n )\n )}\n {children && <span>{children}</span>}\n {!loading && trailingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {trailingIcon}\n </span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n","'use client';\n\nimport { useState, useEffect, CSSProperties } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavBarProps {\n /** Visual theme. \"dark\" = glass/blur on dark bg. \"light\" = white/shadow on light bg. */\n theme?: 'dark' | 'light';\n /** Logo text displayed on the left. */\n logo?: string;\n /** Accent character appended to the logo (e.g. \".\"). */\n logoAccent?: string;\n /** Navigation links rendered in the centre. */\n links?: NavLink[];\n /** Label for the CTA button on the right. */\n ctaLabel?: string;\n /** href for the CTA button. */\n ctaHref?: string;\n /** Whether the nav background changes on scroll. */\n scrollEffect?: boolean;\n /** Scroll threshold in px before the effect triggers. Default 50. */\n scrollThreshold?: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_LINKS: NavLink[] = [\n { label: 'About', href: '#about' },\n { label: 'Experience', href: '#experience' },\n { label: 'Projects', href: '#projects' },\n { label: 'Contact', href: '#contact' },\n];\n\n// ─── Theme tokens ─────────────────────────────────────────────────────────────\n//\n// Rule: className strings must only use standard Tailwind utilities.\n// Any value that contains a custom color or arbitrary CSS goes into\n// the companion `*Style` field as a CSSProperties object, applied via\n// the `style` prop. This ensures the component works in any project\n// regardless of whether that project's Tailwind config has seen these\n// class names during its own build scan.\n\ninterface ThemeTokens {\n nav: {\n baseStyle: CSSProperties;\n scrolledStyle: CSSProperties;\n scrolledClass: string;\n };\n logo: { color: string };\n logoAccent: { color: string };\n link: string;\n cta: {\n className: string;\n style: CSSProperties;\n hoverStyle?: CSSProperties;\n };\n menuToggle: string;\n mobileMenu: {\n className: string;\n style: CSSProperties;\n };\n mobileLink: string;\n mobileCta: {\n className: string;\n style: CSSProperties;\n };\n}\n\nconst tokens: Record<'light' | 'dark', ThemeTokens> = {\n light: {\n nav: {\n baseStyle: { background: 'transparent' },\n scrolledStyle: { background: 'rgba(248,247,244,0.90)' },\n scrolledClass: 'backdrop-blur-md shadow-sm',\n },\n logo: { color: '#0f0f0f' },\n logoAccent: { color: '#5b50f0' },\n link: 'text-gray-500 hover:bg-black/5 hover:text-gray-900 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200',\n cta: {\n className: 'text-white shadow-lg hover:scale-[1.03] transition-all duration-200',\n style: {\n background: 'linear-gradient(135deg, #5b50f0, #7c3aed)',\n boxShadow: '0 4px 14px rgba(91,80,240,0.35)',\n },\n },\n menuToggle: 'text-gray-500 hover:text-gray-900',\n mobileMenu: {\n className: 'backdrop-blur-md border-t border-black/5',\n style: { background: 'rgba(248,247,244,0.95)' },\n },\n mobileLink:\n 'text-gray-500 hover:text-gray-900 font-sans font-medium text-base transition-colors',\n mobileCta: {\n className: 'text-white font-sans font-bold text-sm',\n style: { background: 'linear-gradient(135deg, #5b50f0, #7c3aed)' },\n },\n },\n\n dark: {\n nav: {\n baseStyle: { background: 'transparent' },\n scrolledStyle: { background: 'rgba(6,9,18,0.80)' },\n scrolledClass: 'backdrop-blur-md border-b border-white/5',\n },\n logo: { color: '#6366f1' },\n logoAccent: { color: 'rgba(255,255,255,0.20)' },\n link: 'text-slate-500 hover:text-slate-100 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200',\n cta: {\n className: 'border transition-all duration-200 hover:text-white',\n style: {\n background: 'rgba(99,102,241,0.10)',\n borderColor: 'rgba(99,102,241,0.30)',\n color: '#6366f1',\n },\n },\n menuToggle: 'text-slate-500 hover:text-slate-100',\n mobileMenu: {\n className: 'backdrop-blur-md border-t border-white/5',\n style: { background: 'rgba(6,9,18,0.95)' },\n },\n mobileLink:\n 'text-slate-500 hover:text-slate-100 font-sans font-medium text-base transition-colors',\n mobileCta: {\n className: 'border font-sans font-bold text-sm',\n style: {\n background: 'rgba(99,102,241,0.10)',\n borderColor: 'rgba(99,102,241,0.30)',\n color: '#6366f1',\n },\n },\n },\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport function NavBar({\n theme = 'light',\n logo = 'Fariha',\n logoAccent = '.',\n links = DEFAULT_LINKS,\n ctaLabel = 'Hire me',\n ctaHref = '#contact',\n scrollEffect = true,\n scrollThreshold = 50,\n}: NavBarProps) {\n const [scrolled, setScrolled] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const t = tokens[theme];\n\n useEffect(() => {\n if (!scrollEffect) return;\n const handler = () => setScrolled(window.scrollY > scrollThreshold);\n window.addEventListener('scroll', handler, { passive: true });\n return () => window.removeEventListener('scroll', handler);\n }, [scrollEffect, scrollThreshold]);\n\n const navStyle: CSSProperties = scrolled\n ? { ...t.nav.scrolledStyle, transition: 'all 0.5s ease' }\n : { ...t.nav.baseStyle, transition: 'all 0.5s ease' };\n\n const navClass = `fixed top-0 inset-x-0 z-50 ${scrolled ? `py-3 ${t.nav.scrolledClass}` : 'py-5'}`;\n\n return (\n <nav role=\"navigation\" aria-label=\"Main navigation\" className={navClass} style={navStyle}>\n <div className=\"max-w-6xl mx-auto px-6 flex items-center justify-between\">\n {/* Logo */}\n <a href=\"#\" className=\"font-sans font-extrabold text-lg tracking-tight\" style={t.logo}>\n {logo}\n <span style={t.logoAccent}>{logoAccent}</span>\n </a>\n\n {/* Desktop links */}\n <ul className=\"hidden md:flex items-center gap-1\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a href={link.href} className={t.link}>\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n\n {/* Desktop CTA */}\n <a\n href={ctaHref}\n className={`hidden md:inline-flex items-center px-5 py-2.5 rounded-full ${t.cta.className}`}\n style={t.cta.style}\n >\n {ctaLabel}\n </a>\n\n {/* Mobile toggle */}\n <button\n className={`md:hidden transition-colors ${t.menuToggle}`}\n onClick={() => setMenuOpen(prev => !prev)}\n aria-expanded={menuOpen}\n aria-label={menuOpen ? 'Close menu' : 'Open menu'}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n {menuOpen ? <path d=\"M18 6L6 18M6 6l12 12\" /> : <path d=\"M3 12h18M3 6h18M3 18h18\" />}\n </svg>\n </button>\n </div>\n\n {/* Mobile menu */}\n {menuOpen && (\n <div className={`md:hidden mt-3 ${t.mobileMenu.className}`} style={t.mobileMenu.style}>\n <ul className=\"max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a href={link.href} onClick={() => setMenuOpen(false)} className={t.mobileLink}>\n {link.label}\n </a>\n </li>\n ))}\n <li>\n <a\n href={ctaHref}\n onClick={() => setMenuOpen(false)}\n className={`inline-block px-5 py-2.5 rounded-full ${t.mobileCta.className}`}\n style={t.mobileCta.style}\n >\n {ctaLabel}\n </a>\n </li>\n </ul>\n </div>\n )}\n </nav>\n );\n}\n\nexport default NavBar;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/cn.ts","../src/components/Button/Button.tsx","../src/components/NavBar/NavBar.tsx"],"names":["clsx","jsxs","jsx","React","useState","useEffect"],"mappings":"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","file":"index.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return clsx(inputs);\n}\n","import React from 'react';\nimport { cn } from '@/lib/cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant */\n variant?: ButtonVariant;\n /** Size preset */\n size?: ButtonSize;\n /** Show loading spinner and disable interaction */\n loading?: boolean;\n /** Icon rendered before label */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after label */\n trailingIcon?: React.ReactNode;\n /** Stretch to fill container width */\n fullWidth?: boolean;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary: 'bg-brand text-white hover:bg-brand-600 active:bg-brand-700 shadow-sm',\n secondary: 'bg-surface-2 text-ink border border-surface-3 hover:bg-surface-3 active:bg-surface-3',\n ghost: 'bg-transparent text-ink-secondary hover:bg-surface-2 active:bg-surface-3',\n danger: 'bg-danger text-white hover:bg-red-600 active:bg-red-700 shadow-sm',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: 'h-8 px-3 text-xs gap-1.5 rounded',\n md: 'h-9 px-4 text-sm gap-2 rounded-md',\n lg: 'h-11 px-6 text-sm gap-2.5 rounded-lg',\n};\n\nfunction Spinner({ className }: { className?: string }) {\n return (\n <svg\n className={cn('animate-spin', className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const isDisabled = disabled || loading;\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-busy={loading}\n className={cn(\n 'inline-flex items-center justify-center font-sans font-medium',\n 'transition-all duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1',\n 'disabled:opacity-50 disabled:pointer-events-none',\n 'select-none whitespace-nowrap',\n variantStyles[variant],\n sizeStyles[size],\n fullWidth && 'w-full',\n className\n )}\n {...props}\n >\n {loading ? (\n <Spinner\n className={cn(size === 'sm' ? 'h-3 w-3' : size === 'lg' ? 'h-4 w-4' : 'h-3.5 w-3.5')}\n />\n ) : (\n leadingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {leadingIcon}\n </span>\n )\n )}\n {children && <span>{children}</span>}\n {!loading && trailingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {trailingIcon}\n </span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavBarProps {\n /** Visual theme. \"dark\" = glass/blur on dark bg. \"light\" = white/shadow on light bg. */\n theme?: 'dark' | 'light';\n /** Logo text displayed on the left. */\n logo?: string;\n /** Accent character appended to the logo (e.g. \".\"). */\n logoAccent?: string;\n /** Navigation links rendered in the centre. */\n links?: NavLink[];\n /** Label for the CTA button on the right. */\n ctaLabel?: string;\n /** href for the CTA button. */\n ctaHref?: string;\n /** Whether the nav background changes on scroll. */\n scrollEffect?: boolean;\n /** Scroll threshold in px before the effect triggers. Default 50. */\n scrollThreshold?: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_LINKS: NavLink[] = [\n { label: 'About', href: '#about' },\n { label: 'Experience', href: '#experience' },\n { label: 'Projects', href: '#projects' },\n { label: 'Contact', href: '#contact' },\n];\n\n// ─── Theme tokens ─────────────────────────────────────────────────────────────\n\nconst tokens = {\n dark: {\n nav: {\n base: 'bg-transparent',\n scrolled: 'bg-[#060912]/80 backdrop-blur-md border-b border-white/5',\n },\n logo: 'text-[#6366f1]',\n logoAccent: 'text-white/20',\n link: 'text-[#64748b] hover:text-[#e2e8f0]',\n cta: 'bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1] hover:bg-[#6366f1] hover:text-white hover:border-[#6366f1]',\n menuToggle: 'text-[#64748b] hover:text-[#e2e8f0]',\n mobileMenu: 'bg-[#060912]/95 backdrop-blur-md border-t border-white/5',\n mobileLink: 'text-[#64748b] hover:text-[#e2e8f0]',\n mobileCta: 'bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1]',\n },\n light: {\n nav: {\n base: 'bg-transparent',\n scrolled: 'bg-[#f8f7f4]/90 backdrop-blur-md shadow-sm',\n },\n logo: 'text-[#0f0f0f]',\n logoAccent: 'text-[#5b50f0]',\n link: 'text-[#6b7280] hover:bg-black/5 hover:text-[#0f0f0f]',\n cta: '[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white shadow-lg shadow-[#5b50f0]/25 hover:shadow-[#5b50f0]/40 hover:scale-[1.03]',\n menuToggle: 'text-[#6b7280] hover:text-[#0f0f0f]',\n mobileMenu: 'bg-[#f8f7f4]/95 backdrop-blur-md border-t border-black/5',\n mobileLink: 'text-[#6b7280] hover:text-[#0f0f0f]',\n mobileCta: '[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white',\n },\n} as const;\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport function NavBar({\n theme = 'light',\n logo = 'Fariha',\n logoAccent = '.',\n links = DEFAULT_LINKS,\n ctaLabel = 'Hire me',\n ctaHref = '#contact',\n scrollEffect = true,\n scrollThreshold = 50,\n}: NavBarProps) {\n const [scrolled, setScrolled] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const t = tokens[theme];\n\n useEffect(() => {\n if (!scrollEffect) return;\n const handler = () => setScrolled(window.scrollY > scrollThreshold);\n window.addEventListener('scroll', handler, { passive: true });\n return () => window.removeEventListener('scroll', handler);\n }, [scrollEffect, scrollThreshold]);\n\n const navPy = scrolled ? 'py-3' : 'py-5';\n const navBg = scrolled ? t.nav.scrolled : t.nav.base;\n\n return (\n <nav\n role=\"navigation\"\n aria-label=\"Main navigation\"\n className={`fixed top-0 inset-x-0 z-50 transition-all duration-500 ${navPy} ${navBg}`}\n >\n <div className=\"max-w-6xl mx-auto px-6 flex items-center justify-between\">\n {/* Logo */}\n <a href=\"#\" className={`font-sans font-extrabold text-lg tracking-tight ${t.logo}`}>\n {logo}\n <span className={t.logoAccent}>{logoAccent}</span>\n </a>\n\n {/* Desktop links */}\n <ul className=\"hidden md:flex items-center gap-1\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a\n href={link.href}\n className={`font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200 ${t.link}`}\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n\n {/* Desktop CTA */}\n <a\n href={ctaHref}\n className={`hidden md:inline-flex items-center px-5 py-2.5 rounded-full font-sans font-bold text-sm transition-all duration-200 ${t.cta}`}\n >\n {ctaLabel}\n </a>\n\n {/* Mobile toggle */}\n <button\n className={`md:hidden transition-colors ${t.menuToggle}`}\n onClick={() => setMenuOpen(prev => !prev)}\n aria-expanded={menuOpen}\n aria-label={menuOpen ? 'Close menu' : 'Open menu'}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n {menuOpen ? <path d=\"M18 6L6 18M6 6l12 12\" /> : <path d=\"M3 12h18M3 6h18M3 18h18\" />}\n </svg>\n </button>\n </div>\n\n {/* Mobile menu */}\n {menuOpen && (\n <div className={`md:hidden mt-3 ${t.mobileMenu}`}>\n <ul className=\"max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a\n href={link.href}\n onClick={() => setMenuOpen(false)}\n className={`font-sans font-medium text-base transition-colors ${t.mobileLink}`}\n >\n {link.label}\n </a>\n </li>\n ))}\n <li>\n <a\n href={ctaHref}\n onClick={() => setMenuOpen(false)}\n className={`inline-block px-5 py-2.5 rounded-full font-sans font-bold text-sm ${t.mobileCta}`}\n >\n {ctaLabel}\n </a>\n </li>\n </ul>\n </div>\n )}\n </nav>\n );\n}\n\nexport default NavBar;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -134,64 +134,33 @@ var DEFAULT_LINKS = [
|
|
|
134
134
|
{ label: "Contact", href: "#contact" }
|
|
135
135
|
];
|
|
136
136
|
var tokens = {
|
|
137
|
-
|
|
137
|
+
dark: {
|
|
138
138
|
nav: {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
scrolledClass: "backdrop-blur-md shadow-sm"
|
|
142
|
-
},
|
|
143
|
-
logo: { color: "#0f0f0f" },
|
|
144
|
-
logoAccent: { color: "#5b50f0" },
|
|
145
|
-
link: "text-gray-500 hover:bg-black/5 hover:text-gray-900 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200",
|
|
146
|
-
cta: {
|
|
147
|
-
className: "text-white shadow-lg hover:scale-[1.03] transition-all duration-200",
|
|
148
|
-
style: {
|
|
149
|
-
background: "linear-gradient(135deg, #5b50f0, #7c3aed)",
|
|
150
|
-
boxShadow: "0 4px 14px rgba(91,80,240,0.35)"
|
|
151
|
-
}
|
|
139
|
+
base: "bg-transparent",
|
|
140
|
+
scrolled: "bg-[#060912]/80 backdrop-blur-md border-b border-white/5"
|
|
152
141
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
style: { background: "linear-gradient(135deg, #5b50f0, #7c3aed)" }
|
|
162
|
-
}
|
|
142
|
+
logo: "text-[#6366f1]",
|
|
143
|
+
logoAccent: "text-white/20",
|
|
144
|
+
link: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
145
|
+
cta: "bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1] hover:bg-[#6366f1] hover:text-white hover:border-[#6366f1]",
|
|
146
|
+
menuToggle: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
147
|
+
mobileMenu: "bg-[#060912]/95 backdrop-blur-md border-t border-white/5",
|
|
148
|
+
mobileLink: "text-[#64748b] hover:text-[#e2e8f0]",
|
|
149
|
+
mobileCta: "bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1]"
|
|
163
150
|
},
|
|
164
|
-
|
|
151
|
+
light: {
|
|
165
152
|
nav: {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
scrolledClass: "backdrop-blur-md border-b border-white/5"
|
|
169
|
-
},
|
|
170
|
-
logo: { color: "#6366f1" },
|
|
171
|
-
logoAccent: { color: "rgba(255,255,255,0.20)" },
|
|
172
|
-
link: "text-slate-500 hover:text-slate-100 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200",
|
|
173
|
-
cta: {
|
|
174
|
-
className: "border transition-all duration-200 hover:text-white",
|
|
175
|
-
style: {
|
|
176
|
-
background: "rgba(99,102,241,0.10)",
|
|
177
|
-
borderColor: "rgba(99,102,241,0.30)",
|
|
178
|
-
color: "#6366f1"
|
|
179
|
-
}
|
|
180
|
-
},
|
|
181
|
-
menuToggle: "text-slate-500 hover:text-slate-100",
|
|
182
|
-
mobileMenu: {
|
|
183
|
-
className: "backdrop-blur-md border-t border-white/5",
|
|
184
|
-
style: { background: "rgba(6,9,18,0.95)" }
|
|
153
|
+
base: "bg-transparent",
|
|
154
|
+
scrolled: "bg-[#f8f7f4]/90 backdrop-blur-md shadow-sm"
|
|
185
155
|
},
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
156
|
+
logo: "text-[#0f0f0f]",
|
|
157
|
+
logoAccent: "text-[#5b50f0]",
|
|
158
|
+
link: "text-[#6b7280] hover:bg-black/5 hover:text-[#0f0f0f]",
|
|
159
|
+
cta: "[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white shadow-lg shadow-[#5b50f0]/25 hover:shadow-[#5b50f0]/40 hover:scale-[1.03]",
|
|
160
|
+
menuToggle: "text-[#6b7280] hover:text-[#0f0f0f]",
|
|
161
|
+
mobileMenu: "bg-[#f8f7f4]/95 backdrop-blur-md border-t border-black/5",
|
|
162
|
+
mobileLink: "text-[#6b7280] hover:text-[#0f0f0f]",
|
|
163
|
+
mobileCta: "[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white"
|
|
195
164
|
}
|
|
196
165
|
};
|
|
197
166
|
function NavBar({
|
|
@@ -213,60 +182,81 @@ function NavBar({
|
|
|
213
182
|
window.addEventListener("scroll", handler, { passive: true });
|
|
214
183
|
return () => window.removeEventListener("scroll", handler);
|
|
215
184
|
}, [scrollEffect, scrollThreshold]);
|
|
216
|
-
const
|
|
217
|
-
const
|
|
218
|
-
return /* @__PURE__ */ jsxs(
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
"aria-label": menuOpen ? "Close menu" : "Open menu",
|
|
241
|
-
children: /* @__PURE__ */ jsx(
|
|
242
|
-
"svg",
|
|
185
|
+
const navPy = scrolled ? "py-3" : "py-5";
|
|
186
|
+
const navBg = scrolled ? t.nav.scrolled : t.nav.base;
|
|
187
|
+
return /* @__PURE__ */ jsxs(
|
|
188
|
+
"nav",
|
|
189
|
+
{
|
|
190
|
+
role: "navigation",
|
|
191
|
+
"aria-label": "Main navigation",
|
|
192
|
+
className: `fixed top-0 inset-x-0 z-50 transition-all duration-500 ${navPy} ${navBg}`,
|
|
193
|
+
children: [
|
|
194
|
+
/* @__PURE__ */ jsxs("div", { className: "max-w-6xl mx-auto px-6 flex items-center justify-between", children: [
|
|
195
|
+
/* @__PURE__ */ jsxs("a", { href: "#", className: `font-sans font-extrabold text-lg tracking-tight ${t.logo}`, children: [
|
|
196
|
+
logo,
|
|
197
|
+
/* @__PURE__ */ jsx("span", { className: t.logoAccent, children: logoAccent })
|
|
198
|
+
] }),
|
|
199
|
+
/* @__PURE__ */ jsx("ul", { className: "hidden md:flex items-center gap-1", role: "list", children: links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
200
|
+
"a",
|
|
201
|
+
{
|
|
202
|
+
href: link.href,
|
|
203
|
+
className: `font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200 ${t.link}`,
|
|
204
|
+
children: link.label
|
|
205
|
+
}
|
|
206
|
+
) }, link.label)) }),
|
|
207
|
+
/* @__PURE__ */ jsx(
|
|
208
|
+
"a",
|
|
243
209
|
{
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
210
|
+
href: ctaHref,
|
|
211
|
+
className: `hidden md:inline-flex items-center px-5 py-2.5 rounded-full font-sans font-bold text-sm transition-all duration-200 ${t.cta}`,
|
|
212
|
+
children: ctaLabel
|
|
213
|
+
}
|
|
214
|
+
),
|
|
215
|
+
/* @__PURE__ */ jsx(
|
|
216
|
+
"button",
|
|
217
|
+
{
|
|
218
|
+
className: `md:hidden transition-colors ${t.menuToggle}`,
|
|
219
|
+
onClick: () => setMenuOpen((prev) => !prev),
|
|
220
|
+
"aria-expanded": menuOpen,
|
|
221
|
+
"aria-label": menuOpen ? "Close menu" : "Open menu",
|
|
222
|
+
children: /* @__PURE__ */ jsx(
|
|
223
|
+
"svg",
|
|
224
|
+
{
|
|
225
|
+
width: "22",
|
|
226
|
+
height: "22",
|
|
227
|
+
viewBox: "0 0 24 24",
|
|
228
|
+
fill: "none",
|
|
229
|
+
stroke: "currentColor",
|
|
230
|
+
strokeWidth: "2",
|
|
231
|
+
children: menuOpen ? /* @__PURE__ */ jsx("path", { d: "M18 6L6 18M6 6l12 12" }) : /* @__PURE__ */ jsx("path", { d: "M3 12h18M3 6h18M3 18h18" })
|
|
232
|
+
}
|
|
233
|
+
)
|
|
251
234
|
}
|
|
252
235
|
)
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
236
|
+
] }),
|
|
237
|
+
menuOpen && /* @__PURE__ */ jsx("div", { className: `md:hidden mt-3 ${t.mobileMenu}`, children: /* @__PURE__ */ jsxs("ul", { className: "max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4", role: "list", children: [
|
|
238
|
+
links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
239
|
+
"a",
|
|
240
|
+
{
|
|
241
|
+
href: link.href,
|
|
242
|
+
onClick: () => setMenuOpen(false),
|
|
243
|
+
className: `font-sans font-medium text-base transition-colors ${t.mobileLink}`,
|
|
244
|
+
children: link.label
|
|
245
|
+
}
|
|
246
|
+
) }, link.label)),
|
|
247
|
+
/* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
248
|
+
"a",
|
|
249
|
+
{
|
|
250
|
+
href: ctaHref,
|
|
251
|
+
onClick: () => setMenuOpen(false),
|
|
252
|
+
className: `inline-block px-5 py-2.5 rounded-full font-sans font-bold text-sm ${t.mobileCta}`,
|
|
253
|
+
children: ctaLabel
|
|
254
|
+
}
|
|
255
|
+
) })
|
|
256
|
+
] }) })
|
|
257
|
+
]
|
|
258
|
+
}
|
|
259
|
+
);
|
|
270
260
|
}
|
|
271
261
|
|
|
272
262
|
export { Button, NavBar, cn };
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/cn.ts","../src/components/Button/Button.tsx","../src/components/NavBar/NavBar.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return clsx(inputs);\n}\n","import React from 'react';\nimport { cn } from '@/lib/cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant */\n variant?: ButtonVariant;\n /** Size preset */\n size?: ButtonSize;\n /** Show loading spinner and disable interaction */\n loading?: boolean;\n /** Icon rendered before label */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after label */\n trailingIcon?: React.ReactNode;\n /** Stretch to fill container width */\n fullWidth?: boolean;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary: 'bg-brand text-white hover:bg-brand-600 active:bg-brand-700 shadow-sm',\n secondary: 'bg-surface-2 text-ink border border-surface-3 hover:bg-surface-3 active:bg-surface-3',\n ghost: 'bg-transparent text-ink-secondary hover:bg-surface-2 active:bg-surface-3',\n danger: 'bg-danger text-white hover:bg-red-600 active:bg-red-700 shadow-sm',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: 'h-8 px-3 text-xs gap-1.5 rounded',\n md: 'h-9 px-4 text-sm gap-2 rounded-md',\n lg: 'h-11 px-6 text-sm gap-2.5 rounded-lg',\n};\n\nfunction Spinner({ className }: { className?: string }) {\n return (\n <svg\n className={cn('animate-spin', className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const isDisabled = disabled || loading;\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-busy={loading}\n className={cn(\n 'inline-flex items-center justify-center font-sans font-medium',\n 'transition-all duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1',\n 'disabled:opacity-50 disabled:pointer-events-none',\n 'select-none whitespace-nowrap',\n variantStyles[variant],\n sizeStyles[size],\n fullWidth && 'w-full',\n className\n )}\n {...props}\n >\n {loading ? (\n <Spinner\n className={cn(size === 'sm' ? 'h-3 w-3' : size === 'lg' ? 'h-4 w-4' : 'h-3.5 w-3.5')}\n />\n ) : (\n leadingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {leadingIcon}\n </span>\n )\n )}\n {children && <span>{children}</span>}\n {!loading && trailingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {trailingIcon}\n </span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n","'use client';\n\nimport { useState, useEffect, CSSProperties } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavBarProps {\n /** Visual theme. \"dark\" = glass/blur on dark bg. \"light\" = white/shadow on light bg. */\n theme?: 'dark' | 'light';\n /** Logo text displayed on the left. */\n logo?: string;\n /** Accent character appended to the logo (e.g. \".\"). */\n logoAccent?: string;\n /** Navigation links rendered in the centre. */\n links?: NavLink[];\n /** Label for the CTA button on the right. */\n ctaLabel?: string;\n /** href for the CTA button. */\n ctaHref?: string;\n /** Whether the nav background changes on scroll. */\n scrollEffect?: boolean;\n /** Scroll threshold in px before the effect triggers. Default 50. */\n scrollThreshold?: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_LINKS: NavLink[] = [\n { label: 'About', href: '#about' },\n { label: 'Experience', href: '#experience' },\n { label: 'Projects', href: '#projects' },\n { label: 'Contact', href: '#contact' },\n];\n\n// ─── Theme tokens ─────────────────────────────────────────────────────────────\n//\n// Rule: className strings must only use standard Tailwind utilities.\n// Any value that contains a custom color or arbitrary CSS goes into\n// the companion `*Style` field as a CSSProperties object, applied via\n// the `style` prop. This ensures the component works in any project\n// regardless of whether that project's Tailwind config has seen these\n// class names during its own build scan.\n\ninterface ThemeTokens {\n nav: {\n baseStyle: CSSProperties;\n scrolledStyle: CSSProperties;\n scrolledClass: string;\n };\n logo: { color: string };\n logoAccent: { color: string };\n link: string;\n cta: {\n className: string;\n style: CSSProperties;\n hoverStyle?: CSSProperties;\n };\n menuToggle: string;\n mobileMenu: {\n className: string;\n style: CSSProperties;\n };\n mobileLink: string;\n mobileCta: {\n className: string;\n style: CSSProperties;\n };\n}\n\nconst tokens: Record<'light' | 'dark', ThemeTokens> = {\n light: {\n nav: {\n baseStyle: { background: 'transparent' },\n scrolledStyle: { background: 'rgba(248,247,244,0.90)' },\n scrolledClass: 'backdrop-blur-md shadow-sm',\n },\n logo: { color: '#0f0f0f' },\n logoAccent: { color: '#5b50f0' },\n link: 'text-gray-500 hover:bg-black/5 hover:text-gray-900 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200',\n cta: {\n className: 'text-white shadow-lg hover:scale-[1.03] transition-all duration-200',\n style: {\n background: 'linear-gradient(135deg, #5b50f0, #7c3aed)',\n boxShadow: '0 4px 14px rgba(91,80,240,0.35)',\n },\n },\n menuToggle: 'text-gray-500 hover:text-gray-900',\n mobileMenu: {\n className: 'backdrop-blur-md border-t border-black/5',\n style: { background: 'rgba(248,247,244,0.95)' },\n },\n mobileLink:\n 'text-gray-500 hover:text-gray-900 font-sans font-medium text-base transition-colors',\n mobileCta: {\n className: 'text-white font-sans font-bold text-sm',\n style: { background: 'linear-gradient(135deg, #5b50f0, #7c3aed)' },\n },\n },\n\n dark: {\n nav: {\n baseStyle: { background: 'transparent' },\n scrolledStyle: { background: 'rgba(6,9,18,0.80)' },\n scrolledClass: 'backdrop-blur-md border-b border-white/5',\n },\n logo: { color: '#6366f1' },\n logoAccent: { color: 'rgba(255,255,255,0.20)' },\n link: 'text-slate-500 hover:text-slate-100 font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200',\n cta: {\n className: 'border transition-all duration-200 hover:text-white',\n style: {\n background: 'rgba(99,102,241,0.10)',\n borderColor: 'rgba(99,102,241,0.30)',\n color: '#6366f1',\n },\n },\n menuToggle: 'text-slate-500 hover:text-slate-100',\n mobileMenu: {\n className: 'backdrop-blur-md border-t border-white/5',\n style: { background: 'rgba(6,9,18,0.95)' },\n },\n mobileLink:\n 'text-slate-500 hover:text-slate-100 font-sans font-medium text-base transition-colors',\n mobileCta: {\n className: 'border font-sans font-bold text-sm',\n style: {\n background: 'rgba(99,102,241,0.10)',\n borderColor: 'rgba(99,102,241,0.30)',\n color: '#6366f1',\n },\n },\n },\n};\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport function NavBar({\n theme = 'light',\n logo = 'Fariha',\n logoAccent = '.',\n links = DEFAULT_LINKS,\n ctaLabel = 'Hire me',\n ctaHref = '#contact',\n scrollEffect = true,\n scrollThreshold = 50,\n}: NavBarProps) {\n const [scrolled, setScrolled] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const t = tokens[theme];\n\n useEffect(() => {\n if (!scrollEffect) return;\n const handler = () => setScrolled(window.scrollY > scrollThreshold);\n window.addEventListener('scroll', handler, { passive: true });\n return () => window.removeEventListener('scroll', handler);\n }, [scrollEffect, scrollThreshold]);\n\n const navStyle: CSSProperties = scrolled\n ? { ...t.nav.scrolledStyle, transition: 'all 0.5s ease' }\n : { ...t.nav.baseStyle, transition: 'all 0.5s ease' };\n\n const navClass = `fixed top-0 inset-x-0 z-50 ${scrolled ? `py-3 ${t.nav.scrolledClass}` : 'py-5'}`;\n\n return (\n <nav role=\"navigation\" aria-label=\"Main navigation\" className={navClass} style={navStyle}>\n <div className=\"max-w-6xl mx-auto px-6 flex items-center justify-between\">\n {/* Logo */}\n <a href=\"#\" className=\"font-sans font-extrabold text-lg tracking-tight\" style={t.logo}>\n {logo}\n <span style={t.logoAccent}>{logoAccent}</span>\n </a>\n\n {/* Desktop links */}\n <ul className=\"hidden md:flex items-center gap-1\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a href={link.href} className={t.link}>\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n\n {/* Desktop CTA */}\n <a\n href={ctaHref}\n className={`hidden md:inline-flex items-center px-5 py-2.5 rounded-full ${t.cta.className}`}\n style={t.cta.style}\n >\n {ctaLabel}\n </a>\n\n {/* Mobile toggle */}\n <button\n className={`md:hidden transition-colors ${t.menuToggle}`}\n onClick={() => setMenuOpen(prev => !prev)}\n aria-expanded={menuOpen}\n aria-label={menuOpen ? 'Close menu' : 'Open menu'}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n {menuOpen ? <path d=\"M18 6L6 18M6 6l12 12\" /> : <path d=\"M3 12h18M3 6h18M3 18h18\" />}\n </svg>\n </button>\n </div>\n\n {/* Mobile menu */}\n {menuOpen && (\n <div className={`md:hidden mt-3 ${t.mobileMenu.className}`} style={t.mobileMenu.style}>\n <ul className=\"max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a href={link.href} onClick={() => setMenuOpen(false)} className={t.mobileLink}>\n {link.label}\n </a>\n </li>\n ))}\n <li>\n <a\n href={ctaHref}\n onClick={() => setMenuOpen(false)}\n className={`inline-block px-5 py-2.5 rounded-full ${t.mobileCta.className}`}\n style={t.mobileCta.style}\n >\n {ctaLabel}\n </a>\n </li>\n </ul>\n </div>\n )}\n </nav>\n );\n}\n\nexport default NavBar;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/lib/cn.ts","../src/components/Button/Button.tsx","../src/components/NavBar/NavBar.tsx"],"names":["jsxs","jsx"],"mappings":"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","file":"index.mjs","sourcesContent":["import { clsx, type ClassValue } from \"clsx\";\n\nexport function cn(...inputs: ClassValue[]): string {\n return clsx(inputs);\n}\n","import React from 'react';\nimport { cn } from '@/lib/cn';\n\nexport type ButtonVariant = 'primary' | 'secondary' | 'ghost' | 'danger';\nexport type ButtonSize = 'sm' | 'md' | 'lg';\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n /** Visual style variant */\n variant?: ButtonVariant;\n /** Size preset */\n size?: ButtonSize;\n /** Show loading spinner and disable interaction */\n loading?: boolean;\n /** Icon rendered before label */\n leadingIcon?: React.ReactNode;\n /** Icon rendered after label */\n trailingIcon?: React.ReactNode;\n /** Stretch to fill container width */\n fullWidth?: boolean;\n}\n\nconst variantStyles: Record<ButtonVariant, string> = {\n primary: 'bg-brand text-white hover:bg-brand-600 active:bg-brand-700 shadow-sm',\n secondary: 'bg-surface-2 text-ink border border-surface-3 hover:bg-surface-3 active:bg-surface-3',\n ghost: 'bg-transparent text-ink-secondary hover:bg-surface-2 active:bg-surface-3',\n danger: 'bg-danger text-white hover:bg-red-600 active:bg-red-700 shadow-sm',\n};\n\nconst sizeStyles: Record<ButtonSize, string> = {\n sm: 'h-8 px-3 text-xs gap-1.5 rounded',\n md: 'h-9 px-4 text-sm gap-2 rounded-md',\n lg: 'h-11 px-6 text-sm gap-2.5 rounded-lg',\n};\n\nfunction Spinner({ className }: { className?: string }) {\n return (\n <svg\n className={cn('animate-spin', className)}\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <circle className=\"opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" strokeWidth=\"4\" />\n <path\n className=\"opacity-75\"\n fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z\"\n />\n </svg>\n );\n}\n\nexport const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n variant = 'primary',\n size = 'md',\n loading = false,\n leadingIcon,\n trailingIcon,\n fullWidth = false,\n disabled,\n children,\n className,\n ...props\n },\n ref\n ) => {\n const isDisabled = disabled || loading;\n\n return (\n <button\n ref={ref}\n disabled={isDisabled}\n aria-busy={loading}\n className={cn(\n 'inline-flex items-center justify-center font-sans font-medium',\n 'transition-all duration-150 ease-in-out',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-1',\n 'disabled:opacity-50 disabled:pointer-events-none',\n 'select-none whitespace-nowrap',\n variantStyles[variant],\n sizeStyles[size],\n fullWidth && 'w-full',\n className\n )}\n {...props}\n >\n {loading ? (\n <Spinner\n className={cn(size === 'sm' ? 'h-3 w-3' : size === 'lg' ? 'h-4 w-4' : 'h-3.5 w-3.5')}\n />\n ) : (\n leadingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {leadingIcon}\n </span>\n )\n )}\n {children && <span>{children}</span>}\n {!loading && trailingIcon && (\n <span className=\"shrink-0\" aria-hidden=\"true\">\n {trailingIcon}\n </span>\n )}\n </button>\n );\n }\n);\n\nButton.displayName = 'Button';\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\nexport interface NavLink {\n label: string;\n href: string;\n}\n\nexport interface NavBarProps {\n /** Visual theme. \"dark\" = glass/blur on dark bg. \"light\" = white/shadow on light bg. */\n theme?: 'dark' | 'light';\n /** Logo text displayed on the left. */\n logo?: string;\n /** Accent character appended to the logo (e.g. \".\"). */\n logoAccent?: string;\n /** Navigation links rendered in the centre. */\n links?: NavLink[];\n /** Label for the CTA button on the right. */\n ctaLabel?: string;\n /** href for the CTA button. */\n ctaHref?: string;\n /** Whether the nav background changes on scroll. */\n scrollEffect?: boolean;\n /** Scroll threshold in px before the effect triggers. Default 50. */\n scrollThreshold?: number;\n}\n\n// ─── Constants ───────────────────────────────────────────────────────────────\n\nconst DEFAULT_LINKS: NavLink[] = [\n { label: 'About', href: '#about' },\n { label: 'Experience', href: '#experience' },\n { label: 'Projects', href: '#projects' },\n { label: 'Contact', href: '#contact' },\n];\n\n// ─── Theme tokens ─────────────────────────────────────────────────────────────\n\nconst tokens = {\n dark: {\n nav: {\n base: 'bg-transparent',\n scrolled: 'bg-[#060912]/80 backdrop-blur-md border-b border-white/5',\n },\n logo: 'text-[#6366f1]',\n logoAccent: 'text-white/20',\n link: 'text-[#64748b] hover:text-[#e2e8f0]',\n cta: 'bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1] hover:bg-[#6366f1] hover:text-white hover:border-[#6366f1]',\n menuToggle: 'text-[#64748b] hover:text-[#e2e8f0]',\n mobileMenu: 'bg-[#060912]/95 backdrop-blur-md border-t border-white/5',\n mobileLink: 'text-[#64748b] hover:text-[#e2e8f0]',\n mobileCta: 'bg-[#6366f1]/10 border border-[#6366f1]/30 text-[#6366f1]',\n },\n light: {\n nav: {\n base: 'bg-transparent',\n scrolled: 'bg-[#f8f7f4]/90 backdrop-blur-md shadow-sm',\n },\n logo: 'text-[#0f0f0f]',\n logoAccent: 'text-[#5b50f0]',\n link: 'text-[#6b7280] hover:bg-black/5 hover:text-[#0f0f0f]',\n cta: '[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white shadow-lg shadow-[#5b50f0]/25 hover:shadow-[#5b50f0]/40 hover:scale-[1.03]',\n menuToggle: 'text-[#6b7280] hover:text-[#0f0f0f]',\n mobileMenu: 'bg-[#f8f7f4]/95 backdrop-blur-md border-t border-black/5',\n mobileLink: 'text-[#6b7280] hover:text-[#0f0f0f]',\n mobileCta: '[background:linear-gradient(135deg,#5b50f0,#7c3aed)] text-white',\n },\n} as const;\n\n// ─── Component ────────────────────────────────────────────────────────────────\n\nexport function NavBar({\n theme = 'light',\n logo = 'Fariha',\n logoAccent = '.',\n links = DEFAULT_LINKS,\n ctaLabel = 'Hire me',\n ctaHref = '#contact',\n scrollEffect = true,\n scrollThreshold = 50,\n}: NavBarProps) {\n const [scrolled, setScrolled] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const t = tokens[theme];\n\n useEffect(() => {\n if (!scrollEffect) return;\n const handler = () => setScrolled(window.scrollY > scrollThreshold);\n window.addEventListener('scroll', handler, { passive: true });\n return () => window.removeEventListener('scroll', handler);\n }, [scrollEffect, scrollThreshold]);\n\n const navPy = scrolled ? 'py-3' : 'py-5';\n const navBg = scrolled ? t.nav.scrolled : t.nav.base;\n\n return (\n <nav\n role=\"navigation\"\n aria-label=\"Main navigation\"\n className={`fixed top-0 inset-x-0 z-50 transition-all duration-500 ${navPy} ${navBg}`}\n >\n <div className=\"max-w-6xl mx-auto px-6 flex items-center justify-between\">\n {/* Logo */}\n <a href=\"#\" className={`font-sans font-extrabold text-lg tracking-tight ${t.logo}`}>\n {logo}\n <span className={t.logoAccent}>{logoAccent}</span>\n </a>\n\n {/* Desktop links */}\n <ul className=\"hidden md:flex items-center gap-1\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a\n href={link.href}\n className={`font-sans font-medium text-sm px-4 py-2 rounded-full transition-all duration-200 ${t.link}`}\n >\n {link.label}\n </a>\n </li>\n ))}\n </ul>\n\n {/* Desktop CTA */}\n <a\n href={ctaHref}\n className={`hidden md:inline-flex items-center px-5 py-2.5 rounded-full font-sans font-bold text-sm transition-all duration-200 ${t.cta}`}\n >\n {ctaLabel}\n </a>\n\n {/* Mobile toggle */}\n <button\n className={`md:hidden transition-colors ${t.menuToggle}`}\n onClick={() => setMenuOpen(prev => !prev)}\n aria-expanded={menuOpen}\n aria-label={menuOpen ? 'Close menu' : 'Open menu'}\n >\n <svg\n width=\"22\"\n height=\"22\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n >\n {menuOpen ? <path d=\"M18 6L6 18M6 6l12 12\" /> : <path d=\"M3 12h18M3 6h18M3 18h18\" />}\n </svg>\n </button>\n </div>\n\n {/* Mobile menu */}\n {menuOpen && (\n <div className={`md:hidden mt-3 ${t.mobileMenu}`}>\n <ul className=\"max-w-6xl mx-auto px-6 py-5 flex flex-col gap-4\" role=\"list\">\n {links.map(link => (\n <li key={link.label}>\n <a\n href={link.href}\n onClick={() => setMenuOpen(false)}\n className={`font-sans font-medium text-base transition-colors ${t.mobileLink}`}\n >\n {link.label}\n </a>\n </li>\n ))}\n <li>\n <a\n href={ctaHref}\n onClick={() => setMenuOpen(false)}\n className={`inline-block px-5 py-2.5 rounded-full font-sans font-bold text-sm ${t.mobileCta}`}\n >\n {ctaLabel}\n </a>\n </li>\n </ul>\n </div>\n )}\n </nav>\n );\n}\n\nexport default NavBar;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@farihatang/react-ui",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.3",
|
|
4
4
|
"description": "A React component library to help you build your own GitHub projects more easily.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
".": {
|
|
9
9
|
"import": "./dist/index.mjs",
|
|
10
10
|
"require": "./dist/index.js"
|
|
11
|
-
}
|
|
11
|
+
},
|
|
12
|
+
"./styles": "./dist/index.css"
|
|
12
13
|
},
|
|
13
14
|
"files": [
|
|
14
15
|
"dist"
|
|
@@ -30,7 +31,7 @@
|
|
|
30
31
|
},
|
|
31
32
|
"scripts": {
|
|
32
33
|
"dev": "storybook dev -p 6006",
|
|
33
|
-
"build": "tsup src/index.ts --format cjs,esm --dts --clean",
|
|
34
|
+
"build": "tsup src/index.ts --format cjs,esm --dts --clean && npx tailwindcss -i ./src/styles.css -o ./dist/index.css --minify",
|
|
34
35
|
"build-storybook": "storybook build",
|
|
35
36
|
"lint": "eslint src --ext .ts,.tsx",
|
|
36
37
|
"type-check": "tsc --noEmit"
|