@stevederico/skateboard-ui 0.7.3 → 0.7.6

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,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(git push:*)"
5
+ ],
6
+ "deny": []
7
+ }
8
+ }
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # CHANGELOG
2
2
 
3
+ 0.7.6
4
+
5
+ Reduce sidebar width
6
+
7
+ 0.7.5
8
+
9
+ Use constants for features
10
+ Update pricing section text
11
+ Simplify feature rendering
12
+
13
+ 0.7.4
14
+
15
+ Enhanced landing page design
16
+ Add dark mode toggle
17
+ Implement modern hero section
18
+ Add features pricing sections
19
+
3
20
  0.7.3
4
21
  auth improvements
5
22
 
package/LandingView.jsx CHANGED
@@ -1,4 +1,5 @@
1
- import React from 'react';
1
+ import React, { useState, useEffect } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
2
3
  import constants from "@/constants.json";
3
4
  import * as LucideIcons from "lucide-react";
4
5
 
@@ -11,33 +12,404 @@ const DynamicIcon = ({ name, size = 24, color = 'currentColor', strokeWidth = 2,
11
12
  };
12
13
 
13
14
  export default function LandingView() {
15
+ const navigate = useNavigate();
16
+ const [isDarkMode, setIsDarkMode] = useState(false);
17
+
18
+ // Initialize dark mode from localStorage or system preference
19
+ useEffect(() => {
20
+ const savedMode = localStorage.getItem('darkMode');
21
+ const systemPrefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
22
+
23
+ if (savedMode !== null) {
24
+ setIsDarkMode(savedMode === 'true');
25
+ } else {
26
+ setIsDarkMode(systemPrefersDark);
27
+ }
28
+ }, []);
29
+
30
+ // Apply dark mode to document
31
+ useEffect(() => {
32
+ if (isDarkMode) {
33
+ document.documentElement.classList.add('dark');
34
+ } else {
35
+ document.documentElement.classList.remove('dark');
36
+ }
37
+ localStorage.setItem('darkMode', isDarkMode.toString());
38
+ }, [isDarkMode]);
39
+
40
+ const toggleDarkMode = () => {
41
+ setIsDarkMode(!isDarkMode);
42
+ };
43
+
44
+ const renderHeroContent = () => {
45
+ return (
46
+ <div className="max-w-7xl mx-auto px-8 md:px-6">
47
+ <div className="relative min-h-[120px] md:h-[140px] flex flex-col items-center justify-center py-8">
48
+ {/* CTA in Hero */}
49
+ <div className="text-center">
50
+ <button
51
+ onClick={() => navigate('/app')}
52
+ className="relative group bg-gradient-to-br text-white px-6 py-3 sm:px-8 sm:py-4 md:px-12 md:py-6 rounded-2xl font-semibold text-base sm:text-lg md:text-xl lg:text-2xl transition-all duration-300 shadow-xl backdrop-blur-sm overflow-hidden cursor-pointer"
53
+ style={{
54
+ backgroundImage: `linear-gradient(to bottom right,
55
+ var(--color-app),
56
+ oklch(from var(--color-app) calc(l - 0.05) c h),
57
+ oklch(from var(--color-app) calc(l - 0.08) c h),
58
+ oklch(from var(--color-app) calc(l - 0.12) c h))`,
59
+ boxShadow: `0 25px 50px -12px var(--shadow-color)`
60
+ }}
61
+ onMouseEnter={(e) => {
62
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
63
+ oklch(from var(--color-app) calc(l - 0.05) c h),
64
+ oklch(from var(--color-app) calc(l - 0.08) c h),
65
+ oklch(from var(--color-app) calc(l - 0.12) c h),
66
+ oklch(from var(--color-app) calc(l - 0.16) c h))`;
67
+ e.currentTarget.style.boxShadow = '0 25px 50px -12px var(--shadow-color)'
68
+ }}
69
+ onMouseLeave={(e) => {
70
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
71
+ var(--color-app),
72
+ oklch(from var(--color-app) calc(l - 0.05) c h),
73
+ oklch(from var(--color-app) calc(l - 0.08) c h),
74
+ oklch(from var(--color-app) calc(l - 0.12) c h))`;
75
+ e.currentTarget.style.boxShadow = '0 25px 50px -12px var(--shadow-color)'
76
+ }}
77
+ >
78
+ <span className="relative z-20 flex items-center justify-center gap-3 md:gap-4 drop-shadow-sm">
79
+ <DynamicIcon name="sparkles" size={20} color="currentColor" strokeWidth={2} className="animate-pulse -ml-1 md:w-6 md:h-6 lg:w-7 lg:h-7" />
80
+ {constants.cta}
81
+ </span>
82
+ <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/15 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-800 skew-x-12"></div>
83
+ </button>
84
+ </div>
85
+ </div>
86
+
87
+ <style jsx>{`
88
+ @keyframes springOutLong {
89
+ 0% {
90
+ opacity: 0;
91
+ transform: translateY(-60px) scale(0.1);
92
+ }
93
+ 50% {
94
+ opacity: 1;
95
+ transform: translateY(0) scale(1.2);
96
+ }
97
+ 100% {
98
+ opacity: 1;
99
+ transform: translateY(0) scale(1);
100
+ }
101
+ }
102
+
103
+ @keyframes rollingGrid {
104
+ 0% {
105
+ transform: rotateX(75deg) translateZ(-100px) scale(3) translateY(0px);
106
+ }
107
+ 100% {
108
+ transform: rotateX(75deg) translateZ(-100px) scale(3) translateY(-300px);
109
+ }
110
+ }
111
+
112
+ .perspective-grid-container {
113
+ perspective: 800px;
114
+ overflow: hidden;
115
+ z-index: 1;
116
+ transform: translateY(-150px);
117
+ pointer-events: none;
118
+ }
119
+
120
+ .perspective-grid {
121
+ position: absolute;
122
+ top: 0;
123
+ left: -200vw;
124
+ right: -200vw;
125
+ bottom: 0;
126
+ width: 500vw;
127
+ background-image:
128
+ linear-gradient(color-mix(in srgb, var(--color-app) 50%, transparent 50%) 5px, transparent 5px),
129
+ linear-gradient(90deg, color-mix(in srgb, var(--color-app) 40%, transparent 60%) 5px, transparent 5px);
130
+ background-size: 300px 300px;
131
+ animation: rollingGrid 6s linear infinite;
132
+ transform: none;
133
+ transform-origin: center bottom;
134
+ mask-image: linear-gradient(to bottom,
135
+ transparent 0%,
136
+ rgba(0,0,0,0.1) 20%,
137
+ rgba(0,0,0,0.8) 40%,
138
+ rgba(0,0,0,0.3) 80%,
139
+ transparent 100%);
140
+ -webkit-mask-image: linear-gradient(to bottom,
141
+ transparent 0%,
142
+ rgba(0,0,0,0.1) 20%,
143
+ rgba(0,0,0,0.8) 40%,
144
+ rgba(0,0,0,0.3) 80%,
145
+ transparent 100%);
146
+ height: 300%;
147
+ }
148
+ `}</style>
149
+ </div>
150
+ );
151
+ };
152
+
14
153
  return (
15
- <div className="flex flex-col bg-white h-screen">
16
- <header className="py-2 ">
17
- <div className="flex items-center m-2 mx-auto">
18
- <div className="bg-app rounded-lg flex items-center justify-center ml-3 w-8 h-8">
19
- <DynamicIcon name={constants.appIcon} size={18} color="white" strokeWidth={2} />
154
+ <div
155
+ className="min-h-screen bg-white dark:bg-gray-900 text-gray-900 dark:text-white relative transition-colors duration-300"
156
+ style={{
157
+ '--gradient-from': 'color-mix(in srgb, var(--color-app) 90%, white 10%)',
158
+ '--gradient-via': 'var(--color-app)',
159
+ '--gradient-to': 'oklch(from var(--color-app) calc(l - 0.1) calc(c * 1.2) calc(h + 30))',
160
+ '--gradient-light': 'color-mix(in srgb, var(--color-app) 10%, white 90%)',
161
+ '--shadow-color': 'color-mix(in srgb, var(--color-app) 40%, transparent 60%)',
162
+ '--text-gradient-from': 'oklch(from var(--color-app) calc(l - 0.05) c h)',
163
+ '--text-gradient-to': 'oklch(from var(--color-app) l c calc(h + 30))'
164
+ }}
165
+ >
166
+
167
+ {/* Subtle Grid Pattern */}
168
+ <div className="absolute inset-0">
169
+ <div className="absolute inset-0" style={{
170
+ backgroundImage: `
171
+ linear-gradient(color-mix(in srgb, var(--color-app) 2%, transparent 98%) 1px, transparent 1px),
172
+ linear-gradient(90deg, color-mix(in srgb, var(--color-app) 2%, transparent 98%) 1px, transparent 1px)
173
+ `,
174
+ backgroundSize: '80px 80px'
175
+ }}></div>
176
+ </div>
177
+
178
+ {/* Header */}
179
+ <header className="relative z-10 pt-4 px-6">
180
+ <nav className="max-w-6xl mx-auto bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm border border-gray-200 dark:border-gray-700 rounded-2xl shadow-lg px-6 py-4 flex justify-between items-center transition-colors duration-300">
181
+ <div className="flex items-center gap-2">
182
+ <DynamicIcon name={constants.appIcon} size={28} color="var(--color-app)" strokeWidth={2} />
183
+ <div
184
+ className="text-2xl font-bold bg-clip-text text-transparent"
185
+ style={{
186
+ backgroundImage: `linear-gradient(90deg, var(--text-gradient-from), var(--text-gradient-to))`
187
+ }}
188
+ >
189
+ {constants.appName}
20
190
  </div>
21
- <div className="font-semibold ml-2 text-2xl text-gray-700">{constants.appName}</div>
22
191
  </div>
192
+
193
+ <ul className="hidden md:flex gap-8 list-none">
194
+ <li><a href="#features" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">Features</a></li>
195
+ <li><a href="#pricing" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">Pricing</a></li>
196
+ <li><a href="/terms" className="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">Terms</a></li>
197
+ </ul>
198
+
199
+ <div className="flex gap-3 items-center">
200
+ {/* Dark Mode Toggle */}
201
+ <button
202
+ onClick={toggleDarkMode}
203
+ className="p-2 rounded-lg bg-gray-100 dark:bg-gray-700 hover:bg-gray-200 dark:hover:bg-gray-600 transition-colors duration-200"
204
+ aria-label="Toggle dark mode"
205
+ >
206
+ <DynamicIcon
207
+ name={isDarkMode ? "sun" : "moon"}
208
+ size={18}
209
+ color="currentColor"
210
+ strokeWidth={2}
211
+ className="text-gray-600 dark:text-gray-300"
212
+ />
213
+ </button>
214
+
215
+ <button
216
+ onClick={() => navigate('/app')}
217
+ className="relative group bg-gradient-to-br text-white px-4 py-3 rounded-xl font-semibold text-sm transition-all duration-300 shadow-lg backdrop-blur-sm overflow-hidden cursor-pointer"
218
+ style={{
219
+ backgroundImage: `linear-gradient(to bottom right,
220
+ var(--color-app),
221
+ oklch(from var(--color-app) calc(l - 0.05) c h),
222
+ oklch(from var(--color-app) calc(l - 0.08) c h),
223
+ oklch(from var(--color-app) calc(l - 0.12) c h))`,
224
+ boxShadow: `0 8px 32px var(--shadow-color)`
225
+ }}
226
+ onMouseEnter={(e) => {
227
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
228
+ oklch(from var(--color-app) calc(l - 0.05) c h),
229
+ oklch(from var(--color-app) calc(l - 0.08) c h),
230
+ oklch(from var(--color-app) calc(l - 0.12) c h),
231
+ oklch(from var(--color-app) calc(l - 0.16) c h))`;
232
+ e.currentTarget.style.boxShadow = '0 8px 32px var(--shadow-color)'
233
+ }}
234
+ onMouseLeave={(e) => {
235
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
236
+ var(--color-app),
237
+ oklch(from var(--color-app) calc(l - 0.05) c h),
238
+ oklch(from var(--color-app) calc(l - 0.08) c h),
239
+ oklch(from var(--color-app) calc(l - 0.12) c h))`;
240
+ e.currentTarget.style.boxShadow = '0 8px 32px var(--shadow-color)'
241
+ }}
242
+ >
243
+ <span className="relative z-20 flex items-center justify-center gap-2 drop-shadow-sm">
244
+ <DynamicIcon name="sparkles" size={14} color="currentColor" strokeWidth={2} className="animate-pulse" />
245
+ {constants.cta}
246
+ </span>
247
+ <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/15 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-800 skew-x-12"></div>
248
+ </button>
249
+ </div>
250
+ </nav>
23
251
  </header>
24
- <main className="py-24 md:py-48 bg-app">
25
- <div className="flex flex-col items-center mb-6">
26
- <h1 className="text-center tracking-tight font-bold text-5xl md:text-7xl mb-10 text-white">{constants.tagline}</h1>
27
- <a href={'/app'} target="_blank" className="mx-auto bg-white font-medium text-app shadow-sm rounded-3xl px-4 md:px-8 py-4 cursor-pointer">
28
- Get Started
29
- </a>
30
- </div>
252
+
253
+ <main className="relative z-10">
254
+ {/* Hero Section */}
255
+ <section className="text-center flex flex-col justify-start relative pt-48 pb-12 md:pt-56 md:min-h-screen md:pb-0">
256
+ {/* Perspective Grid Background */}
257
+ <div className="absolute inset-0 perspective-grid-container hidden md:block">
258
+ <div className="perspective-grid"></div>
259
+ </div>
260
+ <div className="max-w-7xl mx-auto px-6 relative z-20 flex flex-col justify-center min-h-[30vh] md:min-h-[40vh]">
261
+ <div className="max-w-4xl mx-auto mb-12">
262
+ <h1
263
+ className="text-5xl sm:text-6xl md:text-7xl lg:text-8xl font-bold mb-0 leading-tight bg-clip-text text-transparent"
264
+ style={{
265
+ backgroundImage: `linear-gradient(90deg, var(--text-gradient-from), var(--text-gradient-to))`
266
+ }}
267
+ >
268
+ {constants.tagline}
269
+ </h1>
270
+ </div>
271
+
272
+ {/* Hero Content */}
273
+ {renderHeroContent()}
274
+ </div>
275
+ </section>
276
+
277
+ {/* Features Section */}
278
+ <section id="features" className="bg-slate-100 dark:bg-gray-800 py-12 md:py-20 transition-colors duration-300">
279
+ <div className="max-w-7xl mx-auto px-6">
280
+ <h2 className="text-center text-4xl md:text-5xl font-bold mb-16 text-gray-900 dark:text-white">{constants.features.title}</h2>
281
+
282
+ {/* Feature Grid */}
283
+ <div className="grid grid-cols-1 md:grid-cols-3 gap-8 max-w-5xl mx-auto">
284
+ {constants.features.items.map((feature, index) => (
285
+ <div key={index} className="bg-white dark:bg-gray-700 rounded-2xl p-8 shadow-lg text-center transition-colors duration-300">
286
+ <div className="text-4xl mb-6">{feature.icon}</div>
287
+ <h3 className="text-xl font-bold mb-4 text-gray-900 dark:text-white">{feature.title}</h3>
288
+ <p className="text-gray-600 dark:text-gray-300">{feature.description}</p>
289
+ </div>
290
+ ))}
291
+ </div>
292
+ </div>
293
+ </section>
294
+
295
+ {/* Pricing Section */}
296
+ <section
297
+ id="pricing"
298
+ className="py-20 transition-colors duration-300"
299
+ style={{
300
+ background: isDarkMode
301
+ ? 'linear-gradient(135deg, oklch(0.25 0 0), oklch(0.2 0 0))'
302
+ : `linear-gradient(135deg, color-mix(in srgb, var(--gradient-light) 80%, white 20%), color-mix(in srgb, var(--gradient-light) 60%, white 40%))`
303
+ }}
304
+ >
305
+ <div className="max-w-7xl mx-auto px-6">
306
+ <h2 className="text-center text-4xl md:text-5xl font-bold mb-16 text-gray-900 dark:text-white">Pricing</h2>
307
+ <div className="max-w-md mx-auto">
308
+ <div
309
+ className="bg-white dark:bg-gray-700 rounded-2xl p-8 shadow-lg border-2 transition-colors duration-300"
310
+ style={{
311
+ borderColor: isDarkMode
312
+ ? `color-mix(in srgb, var(--color-app) 40%, transparent 60%)`
313
+ : `color-mix(in srgb, var(--color-app) 20%, transparent 80%)`
314
+ }}
315
+ >
316
+ <div className="text-center">
317
+ <h3 className="text-2xl font-bold mb-4 text-gray-900 dark:text-white">{constants.stripeProducts[0]?.title || 'Monthly Plan'}</h3>
318
+ <div
319
+ className="text-5xl font-bold mb-2"
320
+ style={{ color: 'var(--color-app)' }}
321
+ >{constants.stripeProducts[0]?.price || '$5.00'}</div>
322
+ <p className="text-gray-600 dark:text-gray-300 mb-8">per month</p>
323
+ <ul className="text-left space-y-4 mb-8">
324
+ {constants.features.items.map((feature, index) => (
325
+ <li key={index} className="flex items-center">
326
+ ✅ {feature.title}
327
+ </li>
328
+ ))}
329
+ <li className="flex items-center">
330
+ ✅ Priority Customer Support
331
+ </li>
332
+ <li className="flex items-center">
333
+ ✅ Cancel anytime
334
+ </li>
335
+ </ul>
336
+ <button
337
+ onClick={() => navigate('/app')}
338
+ className="relative group w-full bg-gradient-to-br text-white text-lg px-8 py-4 rounded-xl font-semibold transition-all duration-300 shadow-xl backdrop-blur-sm overflow-hidden cursor-pointer"
339
+ style={{
340
+ backgroundImage: `linear-gradient(to bottom right,
341
+ var(--color-app),
342
+ oklch(from var(--color-app) calc(l - 0.05) c h),
343
+ oklch(from var(--color-app) calc(l - 0.08) c h),
344
+ oklch(from var(--color-app) calc(l - 0.12) c h))`,
345
+ boxShadow: `0 25px 50px -12px var(--shadow-color)`
346
+ }}
347
+ onMouseEnter={(e) => {
348
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
349
+ oklch(from var(--color-app) calc(l - 0.05) c h),
350
+ oklch(from var(--color-app) calc(l - 0.08) c h),
351
+ oklch(from var(--color-app) calc(l - 0.12) c h),
352
+ oklch(from var(--color-app) calc(l - 0.16) c h))`;
353
+ e.currentTarget.style.boxShadow = '0 25px 50px -12px var(--shadow-color)'
354
+ }}
355
+ onMouseLeave={(e) => {
356
+ e.currentTarget.style.backgroundImage = `linear-gradient(to bottom right,
357
+ var(--color-app),
358
+ oklch(from var(--color-app) calc(l - 0.05) c h),
359
+ oklch(from var(--color-app) calc(l - 0.08) c h),
360
+ oklch(from var(--color-app) calc(l - 0.12) c h))`;
361
+ e.currentTarget.style.boxShadow = '0 25px 50px -12px var(--shadow-color)'
362
+ }}
363
+ >
364
+ <span className="relative z-20 flex items-center justify-center gap-2 drop-shadow-sm">
365
+ <DynamicIcon name="sparkles" size={16} color="currentColor" strokeWidth={2} className="animate-pulse" />
366
+ {constants.cta}
367
+ </span>
368
+ <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/15 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-800 skew-x-12"></div>
369
+ </button>
370
+ </div>
371
+ </div>
372
+ </div>
373
+ </div>
374
+ </section>
375
+
376
+ {/* CTA Section */}
377
+ <section className="py-20">
378
+ <div className="max-w-7xl mx-auto px-6">
379
+ <div
380
+ className="py-16 text-center rounded-3xl text-white"
381
+ style={{
382
+ background: `linear-gradient(90deg, var(--gradient-from), var(--gradient-to))`
383
+ }}
384
+ >
385
+ <h2 className="text-4xl md:text-5xl font-bold mb-10">Ready To Build?</h2>
386
+ <button
387
+ onClick={() => navigate('/app')}
388
+ className="relative group bg-white hover:bg-gray-50 text-lg px-8 py-4 rounded-xl font-semibold transition-all duration-300 shadow-xl hover:shadow-white/40 backdrop-blur-sm overflow-hidden border-2 border-white/20 cursor-pointer"
389
+ style={{ color: 'var(--color-app)' }}
390
+ >
391
+ <span className="relative z-20 flex items-center justify-center gap-2 drop-shadow-sm">
392
+ <DynamicIcon name="sparkles" size={16} color="currentColor" strokeWidth={2} className="animate-pulse" />
393
+ {constants.cta}
394
+ </span>
395
+ <div className="absolute inset-0 bg-gradient-to-r from-transparent via-white/15 to-transparent -translate-x-full group-hover:translate-x-full transition-transform duration-800 skew-x-12"></div>
396
+ </button>
397
+ </div>
398
+ </div>
399
+ </section>
31
400
  </main>
32
- <footer className="py-4 mx-3">
33
- <div className="flex gap-3 text-gray-500 hover:text-gray-600 cursor-pointer">
34
- <div className="mr-auto">&copy; {new Date().getFullYear()} {constants.companyName}</div>
35
- <a href={'/privacy'} target="_blank">Privacy</a>
36
- <a href={'/terms'} target="_blank">Terms</a>
37
- <a href={'/eula'} target="_blank" className="mr-3">EULA</a>
38
- </div>
39
401
 
402
+ {/* Footer */}
403
+ <footer className="border-t border-gray-200 dark:border-gray-700 py-10 text-center text-gray-600 dark:text-gray-300 relative z-10 bg-white dark:bg-gray-900 transition-colors duration-300">
404
+ <div className="max-w-7xl mx-auto px-6">
405
+ <div className="flex justify-center gap-8 mb-6">
406
+ <a href="/privacy" className="hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">Privacy</a>
407
+ <a href="/terms" className="hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">Terms</a>
408
+ <a href="/eula" className="hover:text-gray-900 dark:hover:text-white transition-colors font-semibold">EULA</a>
409
+ </div>
410
+ <p>&copy; {new Date().getFullYear()} {constants.companyName}. All rights reserved.</p>
411
+ </div>
40
412
  </footer>
41
413
  </div>
42
- )
43
- }
414
+ );
415
+ }
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import constants from "@/constants.json";
3
+ import * as LucideIcons from "lucide-react";
4
+
5
+ // Dynamic Icon Component
6
+ const DynamicIcon = ({ name, size = 24, color = 'currentColor', strokeWidth = 2, ...props }) => {
7
+ const toPascalCase = (str) => str.split(/[-_\s]/).map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join('');
8
+ const possibleNames = [name, toPascalCase(name), name.charAt(0).toUpperCase() + name.slice(1)];
9
+ const LucideIcon = possibleNames.find(n => LucideIcons[n]) ? LucideIcons[possibleNames.find(n => LucideIcons[n])] : null;
10
+ return LucideIcon ? React.createElement(LucideIcon, { size, color, strokeWidth, ...props }) : null;
11
+ };
12
+
13
+ export default function LandingView() {
14
+ return (
15
+ <div className="flex flex-col bg-white h-screen">
16
+ <header className="py-2 ">
17
+ <div className="flex items-center m-2 mx-auto">
18
+ <div className="bg-app rounded-lg flex items-center justify-center ml-3 w-8 h-8">
19
+ <DynamicIcon name={constants.appIcon} size={18} color="white" strokeWidth={2} />
20
+ </div>
21
+ <div className="font-semibold ml-2 text-2xl text-gray-700">{constants.appName}</div>
22
+ </div>
23
+ </header>
24
+ <main className="py-24 md:py-48 bg-app">
25
+ <div className="flex flex-col items-center mb-6">
26
+ <h1 className="text-center tracking-tight font-bold text-5xl md:text-7xl mb-10 text-white">{constants.tagline}</h1>
27
+ <a href={'/app'} target="_blank" className="mx-auto bg-white font-medium text-app shadow-sm rounded-3xl px-4 md:px-8 py-4 cursor-pointer">
28
+ Get Started
29
+ </a>
30
+ </div>
31
+ </main>
32
+ <footer className="py-4 mx-3">
33
+ <div className="flex gap-3 text-gray-500 hover:text-gray-600 cursor-pointer">
34
+ <div className="mr-auto">&copy; {new Date().getFullYear()} {constants.companyName}</div>
35
+ <a href={'/privacy'} target="_blank">Privacy</a>
36
+ <a href={'/terms'} target="_blank">Terms</a>
37
+ <a href={'/eula'} target="_blank" className="mr-3">EULA</a>
38
+ </div>
39
+
40
+ </footer>
41
+ </div>
42
+ )
43
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stevederico/skateboard-ui",
3
3
  "private": false,
4
- "version": "0.7.3",
4
+ "version": "0.7.6",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./AppSidebar": {
@@ -25,7 +25,7 @@ import {
25
25
 
26
26
  const SIDEBAR_COOKIE_NAME = "sidebar_state"
27
27
  const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7
28
- const SIDEBAR_WIDTH = "16rem"
28
+ const SIDEBAR_WIDTH = "12rem"
29
29
  const SIDEBAR_WIDTH_MOBILE = "18rem"
30
30
  const SIDEBAR_WIDTH_ICON = "3rem"
31
31
  const SIDEBAR_KEYBOARD_SHORTCUT = "b"