keystone-design-bootstrap 1.0.11 → 1.0.12
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/README.md +43 -24
- package/package.json +1 -1
- package/src/design_system/sections/about-home.tsx +3 -0
- package/src/design_system/sections/blog-section.barelux.tsx +6 -6
- package/src/design_system/sections/header-navigation.barelux.tsx +0 -5
- package/src/design_system/sections/services-home.barelux.tsx +6 -6
- package/src/design_system/sections/testimonials-home.barelux.tsx +6 -6
- package/src/styles/style-overrides.aman.css +3 -4
- package/src/styles/style-overrides.barelux.css +9 -9
package/README.md
CHANGED
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
A comprehensive design system for Keystone customer websites. Provides themed sections, elements, and utilities for building consistent, server-rendered Next.js sites.
|
|
4
4
|
|
|
5
5
|
**Rules:**
|
|
6
|
+
- Theme variants MUST use identical props interface as base component (e.g., if base uses `title`, variant must use `title`, not `headline`)
|
|
6
7
|
- Use CSS variables only (no hardcoded colors/fonts in components)
|
|
7
|
-
-
|
|
8
|
+
- Add theme fonts to customer template's `globals.css` (see below)
|
|
8
9
|
- Use semantic classes (`bg-primary`, `text-fg-primary`, `font-display`)
|
|
9
10
|
- Keep CSS overrides minimal (~100 lines max)
|
|
10
11
|
- Mirror color variables to both `--color-*` and `--background-*` prefixes
|
|
@@ -121,13 +122,24 @@ export const THEME_CONFIG = {
|
|
|
121
122
|
} as const;
|
|
122
123
|
```
|
|
123
124
|
|
|
124
|
-
### 2.
|
|
125
|
+
### 2. Add Fonts to Customer Template
|
|
126
|
+
In customer template's `app/globals.css`, add font imports after `@import "tailwindcss"`:
|
|
127
|
+
```css
|
|
128
|
+
@import "tailwindcss";
|
|
129
|
+
|
|
130
|
+
/* Add your theme fonts here */
|
|
131
|
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600&family=Playfair+Display:wght@400;700&display=swap');
|
|
132
|
+
|
|
133
|
+
/* Rest of file... */
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 3. Create CSS Overrides
|
|
125
137
|
`src/styles/style-overrides.mytheme.css`:
|
|
126
138
|
```css
|
|
127
139
|
[data-theme="mytheme"] {
|
|
128
140
|
/* Typography */
|
|
129
|
-
--font-body:
|
|
130
|
-
--font-display:
|
|
141
|
+
--font-body: "Inter", sans-serif;
|
|
142
|
+
--font-display: "Playfair Display", serif;
|
|
131
143
|
|
|
132
144
|
/* Colors - set both prefixes */
|
|
133
145
|
--color-bg-primary: #FFFFFF;
|
|
@@ -146,24 +158,39 @@ export const THEME_CONFIG = {
|
|
|
146
158
|
}
|
|
147
159
|
```
|
|
148
160
|
|
|
149
|
-
###
|
|
150
|
-
|
|
161
|
+
### 4. Test Theme
|
|
162
|
+
Set in customer site's `config/index.ts`:
|
|
151
163
|
```typescript
|
|
152
|
-
|
|
164
|
+
export const config: SiteConfig = {
|
|
165
|
+
site: {
|
|
166
|
+
theme: "mytheme"
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
**Note:** Fonts are loaded in `globals.css` for all themes. While this means all theme fonts load upfront, it's simpler than dynamic loading and fonts are cached anyway. For ~5-10 themes this is acceptable overhead.
|
|
153
172
|
|
|
154
|
-
|
|
155
|
-
|
|
173
|
+
### 5. Create Component Variants (Optional)
|
|
174
|
+
Use the exact same props interface as the base component (otherwise switching between themes will break).
|
|
156
175
|
|
|
157
|
-
|
|
176
|
+
Check the base component first:
|
|
177
|
+
```typescript
|
|
178
|
+
// Check: src/design_system/sections/hero-home.tsx
|
|
179
|
+
interface HeroHomeProps {
|
|
180
|
+
headline?: string; // ← Use these prop names
|
|
181
|
+
subhead?: string;
|
|
182
|
+
// ...
|
|
183
|
+
}
|
|
158
184
|
```
|
|
159
185
|
|
|
160
|
-
|
|
161
|
-
`src/design_system/sections/hero-home.mytheme.tsx`:
|
|
186
|
+
Then create variant with matching interface:
|
|
162
187
|
```typescript
|
|
163
|
-
|
|
188
|
+
// src/design_system/sections/hero-home.mytheme.tsx
|
|
189
|
+
export const HeroHome = ({ headline, subhead, ctaText, ctaHref }: HeroHomeProps) => (
|
|
164
190
|
<section className="bg-primary py-20">
|
|
165
|
-
<h1 className="font-display text-display-xl">{
|
|
166
|
-
<
|
|
191
|
+
<h1 className="font-display text-display-xl">{headline}</h1>
|
|
192
|
+
<p className="font-body text-lg">{subhead}</p>
|
|
193
|
+
<Button href={ctaHref} color="primary" size="md">{ctaText}</Button>
|
|
167
194
|
</section>
|
|
168
195
|
);
|
|
169
196
|
|
|
@@ -171,16 +198,8 @@ import { registerThemeVariant } from '../../lib/component-registry';
|
|
|
171
198
|
registerThemeVariant('hero-home', 'mytheme', HeroHome);
|
|
172
199
|
```
|
|
173
200
|
|
|
174
|
-
###
|
|
201
|
+
### 6. Register Component Variants
|
|
175
202
|
`src/design_system/sections/index.tsx`:
|
|
176
203
|
```typescript
|
|
177
204
|
import './hero-home.mytheme';
|
|
178
205
|
```
|
|
179
|
-
|
|
180
|
-
### 6. Use Theme
|
|
181
|
-
Customer site's `config/index.ts`:
|
|
182
|
-
```typescript
|
|
183
|
-
export const config = {
|
|
184
|
-
site: { theme: "mytheme" }
|
|
185
|
-
}
|
|
186
|
-
```
|
package/package.json
CHANGED
|
@@ -4,6 +4,7 @@ import { Button } from '../elements';
|
|
|
4
4
|
import { FeatureTextFeaturedIconCard } from './feature-text';
|
|
5
5
|
import { mapIcon } from '../utils/icon-mapping';
|
|
6
6
|
import type { CompanyInformation } from '../../types/api/company-information';
|
|
7
|
+
import type { WebsitePhotos } from '../../types/api/website-photos';
|
|
7
8
|
|
|
8
9
|
interface Value {
|
|
9
10
|
id?: string;
|
|
@@ -15,6 +16,7 @@ interface Value {
|
|
|
15
16
|
|
|
16
17
|
interface AboutHomeProps {
|
|
17
18
|
companyInformation?: CompanyInformation | null;
|
|
19
|
+
websitePhotos?: WebsitePhotos | null;
|
|
18
20
|
title?: string;
|
|
19
21
|
subtitle?: string;
|
|
20
22
|
values?: Value[];
|
|
@@ -24,6 +26,7 @@ interface AboutHomeProps {
|
|
|
24
26
|
|
|
25
27
|
export const AboutHome = ({
|
|
26
28
|
companyInformation,
|
|
29
|
+
websitePhotos,
|
|
27
30
|
title = "",
|
|
28
31
|
subtitle = "",
|
|
29
32
|
values = [],
|
|
@@ -5,15 +5,15 @@ import { ChevronLeft, ChevronRight } from '@untitledui/icons';
|
|
|
5
5
|
|
|
6
6
|
interface BlogSectionProps {
|
|
7
7
|
blogPosts?: BlogPost[] | null;
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
title?: string;
|
|
9
|
+
subtitle?: string;
|
|
10
10
|
maxPosts?: number;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const BlogSection = ({
|
|
14
14
|
blogPosts: postsData,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
title = "*TR* Latest from Our Blog",
|
|
16
|
+
subtitle = "*TR* Stay updated with our latest news, tips, and insights.",
|
|
17
17
|
maxPosts,
|
|
18
18
|
}: BlogSectionProps) => {
|
|
19
19
|
|
|
@@ -38,10 +38,10 @@ export const BlogSection = ({
|
|
|
38
38
|
{/* Section Header - Centered */}
|
|
39
39
|
<div className="mx-auto max-w-3xl text-center mb-12 md:mb-16">
|
|
40
40
|
<h2 className="font-display text-4xl font-medium text-fg-primary md:text-5xl mb-4">
|
|
41
|
-
{
|
|
41
|
+
{title}
|
|
42
42
|
</h2>
|
|
43
43
|
<p className="font-body text-lg text-secondary leading-normal">
|
|
44
|
-
{
|
|
44
|
+
{subtitle}
|
|
45
45
|
</p>
|
|
46
46
|
</div>
|
|
47
47
|
|
|
@@ -53,11 +53,6 @@ export function HeaderNavigation({
|
|
|
53
53
|
const handleMouseEnter = useCallback((item: NavItem, e: React.MouseEvent<HTMLDivElement>) => {
|
|
54
54
|
cancelCloseTimeout();
|
|
55
55
|
if (item.children && item.children.length > 0) {
|
|
56
|
-
const target = e.currentTarget.closest('nav');
|
|
57
|
-
if (target) {
|
|
58
|
-
const rect = target.getBoundingClientRect();
|
|
59
|
-
setDropdownTop(rect.bottom);
|
|
60
|
-
}
|
|
61
56
|
setActiveDropdown(item.label);
|
|
62
57
|
}
|
|
63
58
|
}, [cancelCloseTimeout]);
|
|
@@ -4,14 +4,14 @@ import type { Service } from '../../types/api/service';
|
|
|
4
4
|
|
|
5
5
|
interface ServicesHomeProps {
|
|
6
6
|
services: Service[];
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
title?: string;
|
|
8
|
+
subtitle?: string;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
export const ServicesHome = ({
|
|
12
12
|
services = [],
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
title = "*TR* Explore Our Signature Services",
|
|
14
|
+
subtitle = "*TR* Discover our comprehensive menu of expertly curated, non-invasive treatments. Each service is designed to help you achieve your aesthetic goals, enhance your natural beauty, and boost your confidence.",
|
|
15
15
|
}: ServicesHomeProps) => {
|
|
16
16
|
// Show all services
|
|
17
17
|
const displayServices = services;
|
|
@@ -22,10 +22,10 @@ export const ServicesHome = ({
|
|
|
22
22
|
{/* Section Header - Centered */}
|
|
23
23
|
<div className="mx-auto max-w-3xl text-center mb-12">
|
|
24
24
|
<h2 className="font-display text-display-md font-normal text-fg-primary mb-4">
|
|
25
|
-
{
|
|
25
|
+
{title}
|
|
26
26
|
</h2>
|
|
27
27
|
<p className="font-body text-base text-secondary leading-normal">
|
|
28
|
-
{
|
|
28
|
+
{subtitle}
|
|
29
29
|
</p>
|
|
30
30
|
</div>
|
|
31
31
|
|
|
@@ -6,14 +6,14 @@ import { ChevronLeft, ChevronRight } from '@untitledui/icons';
|
|
|
6
6
|
|
|
7
7
|
interface TestimonialsHomeProps {
|
|
8
8
|
testimonials?: Testimonial[] | null;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
title?: string;
|
|
10
|
+
subtitle?: string;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
export const TestimonialsHome = ({
|
|
14
14
|
testimonials: testimonialsData,
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
title = "*TR* What Our Clients Say",
|
|
16
|
+
subtitle = "*TR* Discover the transformative experiences of our clients. Read their testimonials to hear firsthand about their journeys to enhanced natural beauty, renewed confidence, and the exceptional care they received at Bare Lux Studio.",
|
|
17
17
|
}: TestimonialsHomeProps) => {
|
|
18
18
|
const testimonials = Array.isArray(testimonialsData) ? testimonialsData : [];
|
|
19
19
|
|
|
@@ -23,10 +23,10 @@ export const TestimonialsHome = ({
|
|
|
23
23
|
{/* Section Header - Centered */}
|
|
24
24
|
<div className="mx-auto max-w-3xl text-center mb-12 md:mb-16">
|
|
25
25
|
<h2 className="font-display text-4xl font-medium text-fg-primary md:text-5xl mb-4">
|
|
26
|
-
{
|
|
26
|
+
{title}
|
|
27
27
|
</h2>
|
|
28
28
|
<p className="font-body text-lg text-secondary leading-normal">
|
|
29
|
-
{
|
|
29
|
+
{subtitle}
|
|
30
30
|
</p>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/* Aman Theme Overrides */
|
|
2
2
|
|
|
3
|
-
/* Aman theme typography and colors */
|
|
4
3
|
[data-theme="aman"] {
|
|
5
|
-
/* Typography
|
|
6
|
-
--font-body: "Inter",
|
|
7
|
-
--font-display: "Playfair Display", "
|
|
4
|
+
/* Typography */
|
|
5
|
+
--font-body: "Inter", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
6
|
+
--font-display: "Playfair Display", "Didot", "Georgia", serif;
|
|
8
7
|
|
|
9
8
|
/* Aman color palette - warm, elegant tones */
|
|
10
9
|
--color-bg-primary: #F9F7F0; /* Light warm beige */
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
/* Bare Lux Studio Theme Overrides */
|
|
2
2
|
|
|
3
|
-
/* Bare Lux theme typography and colors */
|
|
4
3
|
[data-theme="barelux"] {
|
|
5
4
|
/* Typography - Merriweather for headings, Poppins for body */
|
|
6
|
-
--font-body:
|
|
7
|
-
--font-display:
|
|
5
|
+
--font-body: "Poppins", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
6
|
+
--font-display: "Merriweather", "Georgia", serif;
|
|
8
7
|
|
|
9
8
|
/* Bare Lux color palette - soft peachy rose aesthetic */
|
|
10
9
|
--color-bg-primary: #FDFCFB;
|
|
@@ -45,7 +44,7 @@
|
|
|
45
44
|
|
|
46
45
|
/* Body text uses Poppins */
|
|
47
46
|
[data-theme="barelux"] body {
|
|
48
|
-
font-family:
|
|
47
|
+
font-family: "Poppins", -apple-system, "Segoe UI", Roboto, Arial, sans-serif !important;
|
|
49
48
|
background-color: #FDFCFB;
|
|
50
49
|
}
|
|
51
50
|
|
|
@@ -56,19 +55,19 @@
|
|
|
56
55
|
[data-theme="barelux"] h4,
|
|
57
56
|
[data-theme="barelux"] h5,
|
|
58
57
|
[data-theme="barelux"] h6 {
|
|
59
|
-
font-family:
|
|
58
|
+
font-family: "Merriweather", "Georgia", serif !important;
|
|
60
59
|
font-weight: 400;
|
|
61
60
|
}
|
|
62
61
|
|
|
63
62
|
/* .font-display class uses Merriweather */
|
|
64
63
|
[data-theme="barelux"] .font-display {
|
|
65
|
-
font-family:
|
|
64
|
+
font-family: "Merriweather", "Georgia", serif !important;
|
|
66
65
|
font-weight: 400;
|
|
67
66
|
}
|
|
68
67
|
|
|
69
68
|
/* .font-body class uses Poppins */
|
|
70
69
|
[data-theme="barelux"] .font-body {
|
|
71
|
-
font-family:
|
|
70
|
+
font-family: "Poppins", -apple-system, "Segoe UI", Roboto, Arial, sans-serif !important;
|
|
72
71
|
}
|
|
73
72
|
|
|
74
73
|
/* Fix header background */
|
|
@@ -84,13 +83,14 @@
|
|
|
84
83
|
|
|
85
84
|
/* Navigation styling */
|
|
86
85
|
[data-theme="barelux"] nav {
|
|
87
|
-
font-family:
|
|
86
|
+
font-family: "Poppins", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
87
|
+
font-weight: 600;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
/* Button text */
|
|
91
91
|
[data-theme="barelux"] button,
|
|
92
92
|
[data-theme="barelux"] .btn {
|
|
93
|
-
font-family:
|
|
93
|
+
font-family: "Poppins", -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
/* Sections background */
|