@stevederico/skateboard-ui 2.3.1 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # CHANGELOG
2
2
 
3
+ 2.5.0
4
+
5
+ Add configurable LandingView constants
6
+ Add navLinks constant
7
+ Add pricing.title constant
8
+ Add pricing.extras constant
9
+ Add ctaHeading constant
10
+ Add footerLinks constant
11
+ Add copyrightText constant
12
+ Use stripeProducts features and interval
13
+ Conditionally render pricing section
14
+
15
+ 2.4.0
16
+
17
+ Add sidebarCollapsed constant
18
+
3
19
  2.3.1
4
20
 
5
21
  Remove sidebar rail hover border
package/README.md CHANGED
@@ -123,6 +123,24 @@ const constants = {
123
123
  }
124
124
  ],
125
125
 
126
+ // Optional: Landing page customization
127
+ navLinks: [ // Override header nav links
128
+ { label: "Features", href: "#features" },
129
+ { label: "Pricing", href: "#pricing" },
130
+ { label: "Blog", href: "/blog" }
131
+ ],
132
+ pricing: {
133
+ title: "Simple Pricing", // Pricing section heading
134
+ extras: ["Priority Customer Support", "Cancel anytime"] // Extra bullets after product features
135
+ },
136
+ ctaHeading: "Ready To Build?", // CTA section heading
137
+ footerLinks: [ // Override footer links
138
+ { label: "Privacy", href: "/privacy" },
139
+ { label: "Terms", href: "/terms" },
140
+ { label: "EULA", href: "/eula" }
141
+ ],
142
+ copyrightText: "All rights reserved.", // Copyright suffix after "© {year} {companyName}."
143
+
126
144
  // Optional: Legal documents (plain text, supports _COMPANY_, _WEBSITE_, _EMAIL_ placeholders)
127
145
  termsOfService: "Terms of Service for _COMPANY_...",
128
146
  privacyPolicy: "Privacy Policy for _COMPANY_...",
package/layout/Layout.jsx CHANGED
@@ -14,6 +14,9 @@ import { getState } from '../core/Context.jsx';
14
14
  * Set `constants.hideSidebarInsetRounding` to true to remove the
15
15
  * rounded corners on the main content area.
16
16
  *
17
+ * Set `constants.sidebarCollapsed` to true to start the sidebar
18
+ * in its collapsed (icon-only) state.
19
+ *
17
20
  * @param {Object} props
18
21
  * @param {React.ReactNode} [props.children] - Child content (unused, Outlet renders routes)
19
22
  * @returns {JSX.Element} Layout with sidebar, main content, and tab bar
@@ -37,10 +40,12 @@ export default function Layout({ children }) {
37
40
 
38
41
  return (
39
42
  <div className="min-h-screen flex flex-col pt-[env(safe-area-inset-top)] pb-[calc(5rem+env(safe-area-inset-bottom))] md:pb-[env(safe-area-inset-bottom)] pl-[env(safe-area-inset-left)] pr-[env(safe-area-inset-right)]">
40
- <SidebarProvider style={{
41
- '--sidebar-width': 'calc(var(--spacing) * 72)',
42
- '--header-height': '3.5rem',
43
- }}>
43
+ <SidebarProvider
44
+ defaultOpen={!constants.sidebarCollapsed}
45
+ style={{
46
+ '--sidebar-width': 'calc(var(--spacing) * 72)',
47
+ '--header-height': '3.5rem',
48
+ }}>
44
49
  {showSidebar && <Sidebar variant="inset" />}
45
50
  <SidebarInset className={constants.hideSidebarInsetRounding ? "md:peer-data-[variant=inset]:rounded-none" : ""}>
46
51
  <Outlet />
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stevederico/skateboard-ui",
3
3
  "private": false,
4
- "version": "2.3.1",
4
+ "version": "2.5.0",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./Sidebar": {
@@ -13,8 +13,8 @@ import { Separator } from '../shadcn/ui/separator.jsx';
13
13
  * Default landing page with hero section, features grid, pricing card,
14
14
  * CTA section, and footer.
15
15
  *
16
- * Reads app branding, tagline, features, and pricing from constants.
17
- * Uses shadcn defaults for all styling no inline styles or custom animations.
16
+ * Reads app branding, tagline, features, pricing, and layout from constants.
17
+ * All sections are configurable via optional constants keys with sensible defaults.
18
18
  *
19
19
  * @returns {JSX.Element} Full landing page
20
20
  *
@@ -43,9 +43,13 @@ export default function LandingView() {
43
43
  </div>
44
44
 
45
45
  <div className="hidden md:flex gap-6">
46
- <a href="#features" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">Features</a>
47
- <a href="#pricing" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">Pricing</a>
48
- <a href="/terms" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">Terms</a>
46
+ {(constants.navLinks || [
47
+ { label: 'Features', href: '#features' },
48
+ ...(constants.stripeProducts?.length > 0 ? [{ label: 'Pricing', href: '#pricing' }] : []),
49
+ { label: 'Terms', href: '/terms' },
50
+ ]).map((link, index) => (
51
+ <a key={index} href={link.href} className="text-muted-foreground hover:text-foreground transition-colors font-semibold">{link.label}</a>
52
+ ))}
49
53
  </div>
50
54
 
51
55
  <div className="flex gap-3 items-center">
@@ -91,50 +95,50 @@ export default function LandingView() {
91
95
  </section>
92
96
 
93
97
  {/* Pricing Section */}
94
- <section id="pricing" className="py-16 md:py-24">
95
- <div className="max-w-7xl mx-auto px-6">
96
- <h2 className="text-center text-4xl md:text-5xl font-bold mb-16">Pricing</h2>
97
- <div className="max-w-md mx-auto">
98
- <Card>
99
- <CardHeader className="text-center">
100
- <CardTitle className="text-2xl font-bold">{constants.stripeProducts[0]?.title || 'Monthly Plan'}</CardTitle>
101
- <CardDescription>per month</CardDescription>
102
- </CardHeader>
103
- <CardContent className="text-center">
104
- <div className="text-5xl font-bold text-foreground mb-8">{constants.stripeProducts[0]?.price || '$5.00'}</div>
105
- <ul className="text-left space-y-4 mb-8">
106
- {(constants.features?.items || []).map((feature, index) => (
107
- <li key={index} className="flex items-center gap-2">
108
- <Check size={16} className="text-primary shrink-0" />
109
- {feature.title}
110
- </li>
111
- ))}
112
- <li className="flex items-center gap-2">
113
- <Check size={16} className="text-primary shrink-0" />
114
- Priority Customer Support
115
- </li>
116
- <li className="flex items-center gap-2">
117
- <Check size={16} className="text-primary shrink-0" />
118
- Cancel anytime
119
- </li>
120
- </ul>
121
- </CardContent>
122
- <CardFooter>
123
- <Button variant="default" size="cta" className="w-full" onClick={() => navigate('/app')}>
124
- {constants.cta}
125
- </Button>
126
- </CardFooter>
127
- </Card>
98
+ {constants.stripeProducts?.length > 0 && (
99
+ <section id="pricing" className="py-16 md:py-24">
100
+ <div className="max-w-7xl mx-auto px-6">
101
+ <h2 className="text-center text-4xl md:text-5xl font-bold mb-16">{constants.pricing?.title || 'Pricing'}</h2>
102
+ <div className="max-w-md mx-auto">
103
+ <Card>
104
+ <CardHeader className="text-center">
105
+ <CardTitle className="text-2xl font-bold">{constants.stripeProducts[0]?.title || 'Monthly Plan'}</CardTitle>
106
+ <CardDescription>per {constants.stripeProducts[0]?.interval || 'month'}</CardDescription>
107
+ </CardHeader>
108
+ <CardContent className="text-center">
109
+ <div className="text-5xl font-bold text-foreground mb-8">{constants.stripeProducts[0]?.price || '$5.00'}</div>
110
+ <ul className="text-left space-y-4 mb-8">
111
+ {(constants.stripeProducts[0]?.features || []).map((feature, index) => (
112
+ <li key={index} className="flex items-center gap-2">
113
+ <Check size={16} className="text-primary shrink-0" />
114
+ {feature}
115
+ </li>
116
+ ))}
117
+ {(constants.pricing?.extras || []).map((extra, index) => (
118
+ <li key={`extra-${index}`} className="flex items-center gap-2">
119
+ <Check size={16} className="text-primary shrink-0" />
120
+ {extra}
121
+ </li>
122
+ ))}
123
+ </ul>
124
+ </CardContent>
125
+ <CardFooter>
126
+ <Button variant="default" size="cta" className="w-full" onClick={() => navigate('/app')}>
127
+ {constants.cta}
128
+ </Button>
129
+ </CardFooter>
130
+ </Card>
131
+ </div>
128
132
  </div>
129
- </div>
130
- </section>
133
+ </section>
134
+ )}
131
135
 
132
136
  {/* CTA Section */}
133
137
  <section className="py-16 md:py-24">
134
138
  <div className="max-w-7xl mx-auto px-6">
135
139
  <Card className="bg-primary text-primary-foreground py-16 text-center">
136
140
  <CardContent>
137
- <h2 className="text-4xl md:text-5xl font-bold mb-10">Ready To Build?</h2>
141
+ <h2 className="text-4xl md:text-5xl font-bold mb-10">{constants.ctaHeading || 'Ready To Build?'}</h2>
138
142
  <Button variant="secondary" size="cta" onClick={() => navigate('/app')}>
139
143
  {constants.cta}
140
144
  </Button>
@@ -149,11 +153,15 @@ export default function LandingView() {
149
153
  <div className="max-w-7xl mx-auto px-6">
150
154
  <Separator className="mb-8" />
151
155
  <div className="flex justify-center gap-8 mb-6">
152
- <a href="/privacy" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">Privacy</a>
153
- <a href="/terms" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">Terms</a>
154
- <a href="/eula" className="text-muted-foreground hover:text-foreground transition-colors font-semibold">EULA</a>
156
+ {(constants.footerLinks || [
157
+ ...(constants.privacyPolicy ? [{ label: 'Privacy', href: '/privacy' }] : []),
158
+ ...(constants.termsOfService ? [{ label: 'Terms', href: '/terms' }] : []),
159
+ ...(constants.EULA ? [{ label: 'EULA', href: '/eula' }] : []),
160
+ ]).map((link, index) => (
161
+ <a key={index} href={link.href} className="text-muted-foreground hover:text-foreground transition-colors font-semibold">{link.label}</a>
162
+ ))}
155
163
  </div>
156
- <p className="text-center text-muted-foreground">&copy; {new Date().getFullYear()} {constants.companyName}. All rights reserved.</p>
164
+ <p className="text-center text-muted-foreground">&copy; {new Date().getFullYear()} {constants.companyName}. {constants.copyrightText || 'All rights reserved.'}</p>
157
165
  </div>
158
166
  </footer>
159
167
  </div>