brand-shell 0.3.0 → 0.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/README.md +38 -265
- package/dist/default.css +8 -2
- package/package.json +9 -1
package/README.md
CHANGED
|
@@ -1,44 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
# Brand Shell
|
|
2
2
|
|
|
3
|
-
Reusable header and footer
|
|
3
|
+
Reusable, validated header and footer UI with one shared contract across React, Next.js, TanStack Router, Vue, Svelte, and Web Components.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
bun add brand-shell
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
## Quick Start (React)
|
|
12
12
|
|
|
13
13
|
```tsx
|
|
14
|
-
import {
|
|
14
|
+
import { Footer, Header, type BrandDetails, type BrandTheme } from "brand-shell";
|
|
15
15
|
import "brand-shell/default.css";
|
|
16
16
|
|
|
17
17
|
const details: BrandDetails = {
|
|
18
|
-
name: "
|
|
18
|
+
name: "Brand Shell",
|
|
19
19
|
homeHref: "/",
|
|
20
20
|
navLinks: [
|
|
21
|
-
{ label: "Blog", href: "/blog" },
|
|
22
21
|
{ label: "Docs", href: "/docs" },
|
|
22
|
+
{ label: "Blog", href: "/blog" },
|
|
23
23
|
],
|
|
24
|
-
primaryAction: { label: "
|
|
25
|
-
secondaryAction: { label: "
|
|
26
|
-
linkedin: "https://linkedin.com/in/example",
|
|
24
|
+
primaryAction: { label: "Contact", href: "mailto:hello@example.com" },
|
|
25
|
+
secondaryAction: { label: "GitHub", href: "https://github.com/example", target: "_blank" },
|
|
27
26
|
github: "https://github.com/example",
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
tagline: "Design-system quality shell for every project.",
|
|
27
|
+
linkedin: "https://linkedin.com/in/example",
|
|
28
|
+
tagline: "Build once. Reuse everywhere.",
|
|
31
29
|
};
|
|
32
30
|
|
|
33
31
|
const theme: BrandTheme = {
|
|
34
|
-
primaryColor: "#
|
|
32
|
+
primaryColor: "#2563eb",
|
|
35
33
|
backgroundColor: "#0f172a",
|
|
36
34
|
textColor: "#f8fafc",
|
|
37
|
-
fontFamily: '"Inter", system-ui, sans-serif',
|
|
38
|
-
socialIconSize: "2.25rem",
|
|
39
35
|
};
|
|
40
36
|
|
|
41
|
-
export function
|
|
37
|
+
export function AppShell({ children }: { children: React.ReactNode }) {
|
|
42
38
|
return (
|
|
43
39
|
<>
|
|
44
40
|
<Header details={details} theme={theme} />
|
|
@@ -49,268 +45,45 @@ export function Layout({ children }: { children: React.ReactNode }) {
|
|
|
49
45
|
}
|
|
50
46
|
```
|
|
51
47
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
The package now exports pure TypeScript helpers you can reuse in other framework adapters:
|
|
55
|
-
|
|
56
|
-
```ts
|
|
57
|
-
import {
|
|
58
|
-
buildShellViewModel,
|
|
59
|
-
validateBrandDetails,
|
|
60
|
-
validateBrandTheme,
|
|
61
|
-
} from "brand-shell";
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
`buildShellViewModel` normalizes nav links and CTA behavior (target/rel/variants) so framework adapters share the same rules.
|
|
65
|
-
|
|
66
|
-
Validation + normalization are also exported for external integrations. The adapters run these checks in development mode.
|
|
48
|
+
## Framework Adapters
|
|
67
49
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
if (!detailsCheck.valid || !themeCheck.valid) {
|
|
73
|
-
throw new Error([...detailsCheck.errors, ...themeCheck.errors].join("\n"));
|
|
74
|
-
}
|
|
50
|
+
- React/Next/TanStack: `import { Header, Footer } from "brand-shell"`
|
|
51
|
+
- Vue: `import { BrandHeader, BrandFooter } from "brand-shell/vue"`
|
|
52
|
+
- Svelte: `import { brandShell } from "brand-shell/svelte"`
|
|
53
|
+
- Web Components: `import { registerBrandShellElements, applyBrandShellProps } from "brand-shell/web"`
|
|
75
54
|
|
|
76
|
-
|
|
77
|
-
const normalizedTheme = themeCheck.normalized;
|
|
78
|
-
```
|
|
55
|
+
All adapters use the same `BrandDetails` + `BrandTheme` contract.
|
|
79
56
|
|
|
80
|
-
|
|
57
|
+
## Validation + Schema
|
|
81
58
|
|
|
82
|
-
|
|
59
|
+
Use runtime validators and exported JSON Schema before rendering external payloads.
|
|
83
60
|
|
|
84
61
|
```ts
|
|
62
|
+
import { validateBrandDetails, validateBrandTheme } from "brand-shell";
|
|
85
63
|
import schema from "brand-shell/schema";
|
|
86
|
-
// also available as: brand-shell/schema.json
|
|
87
64
|
```
|
|
88
65
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Package publish surface is also guarded by `bun run pack:check` (allowed files + unpacked size budget) so docs/dev-webapp files cannot bloat the npm package.
|
|
92
|
-
|
|
93
|
-
### Web Components adapter
|
|
94
|
-
|
|
95
|
-
You can also use framework-agnostic custom elements:
|
|
96
|
-
|
|
97
|
-
```ts
|
|
98
|
-
import { applyBrandShellProps, registerBrandShellElements } from "brand-shell/web";
|
|
99
|
-
import "brand-shell/default.css";
|
|
100
|
-
|
|
101
|
-
registerBrandShellElements();
|
|
102
|
-
```
|
|
66
|
+
## Security Defaults
|
|
103
67
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
const details = {
|
|
111
|
-
name: "Brand Shell",
|
|
112
|
-
homeHref: "/",
|
|
113
|
-
navLinks: [{ label: "Docs", href: "/docs" }],
|
|
114
|
-
primaryAction: { label: "Contact", href: "mailto:hello@example.com" },
|
|
115
|
-
linkedin: "https://linkedin.com/in/example",
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const theme = {
|
|
119
|
-
primaryColor: "#0ea5e9",
|
|
120
|
-
backgroundColor: "#0f172a",
|
|
121
|
-
textColor: "#f8fafc",
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
const header = document.getElementById("app-header");
|
|
125
|
-
const footer = document.getElementById("app-footer");
|
|
126
|
-
|
|
127
|
-
if (header && footer) {
|
|
128
|
-
applyBrandShellProps(header, { details, theme });
|
|
129
|
-
applyBrandShellProps(footer, { details, theme });
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
### Vue adapter
|
|
134
|
-
|
|
135
|
-
Use framework-native Vue components:
|
|
136
|
-
|
|
137
|
-
```vue
|
|
138
|
-
<script setup>
|
|
139
|
-
import { BrandFooter, BrandHeader } from "brand-shell/vue";
|
|
140
|
-
import "brand-shell/default.css";
|
|
141
|
-
|
|
142
|
-
const details = { name: "Brand Shell" };
|
|
143
|
-
const theme = { primaryColor: "#0ea5e9" };
|
|
144
|
-
</script>
|
|
145
|
-
|
|
146
|
-
<template>
|
|
147
|
-
<BrandHeader :details="details" :theme="theme" />
|
|
148
|
-
<BrandFooter :details="details" :theme="theme" />
|
|
149
|
-
</template>
|
|
150
|
-
```
|
|
68
|
+
- Unsafe link protocols are rejected during normalization.
|
|
69
|
+
- `target="_blank"` links are hardened with `noopener noreferrer`.
|
|
70
|
+
- Renderers use text/attributes only (no raw HTML rendering path).
|
|
151
71
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
Use a Svelte action on the custom element tags:
|
|
155
|
-
|
|
156
|
-
```svelte
|
|
157
|
-
<script>
|
|
158
|
-
import { brandShell } from "brand-shell/svelte";
|
|
159
|
-
import "brand-shell/default.css";
|
|
160
|
-
|
|
161
|
-
const shellProps = {
|
|
162
|
-
details: { name: "Brand Shell" },
|
|
163
|
-
theme: { primaryColor: "#0ea5e9" },
|
|
164
|
-
};
|
|
165
|
-
</script>
|
|
166
|
-
|
|
167
|
-
<brand-header use:brandShell={shellProps}></brand-header>
|
|
168
|
-
<brand-footer use:brandShell={shellProps}></brand-footer>
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### Props reference
|
|
172
|
-
|
|
173
|
-
#### `BrandDetails`
|
|
174
|
-
|
|
175
|
-
| Field | Type | Description |
|
|
176
|
-
| --- | --- | --- |
|
|
177
|
-
| `name` | `string` | Required brand name shown in header/footer |
|
|
178
|
-
| `homeHref` | `string` | Optional link applied to the header name/logo |
|
|
179
|
-
| `navLinks` | `BrandNavLink[]` | Optional text links (e.g. Blog, Docs, About) |
|
|
180
|
-
| `primaryAction` | `BrandAction` | Highlighted CTA button (e.g. Hire me) |
|
|
181
|
-
| `secondaryAction` | `BrandAction` | Optional secondary CTA button |
|
|
182
|
-
| `linkedin`, `github`, `twitter`, `discord`, `website` | `string` | Social/profile URLs rendered as icon buttons |
|
|
183
|
-
| `gmail` | `string` | Email address or `mailto:` link |
|
|
184
|
-
| `tagline` | `string` | Short line shown in the footer |
|
|
185
|
-
|
|
186
|
-
#### `BrandNavLink`
|
|
187
|
-
|
|
188
|
-
| Field | Type | Description |
|
|
189
|
-
| --- | --- | --- |
|
|
190
|
-
| `label` | `string` | Visible text |
|
|
191
|
-
| `href` | `string` | Destination |
|
|
192
|
-
| `ariaLabel` | `string` | Optional accessible label override |
|
|
193
|
-
| `target` | `_blank \| _self \| _parent \| _top` | Optional target |
|
|
194
|
-
| `rel` | `string` | Optional rel attribute |
|
|
195
|
-
|
|
196
|
-
#### `BrandAction`
|
|
197
|
-
|
|
198
|
-
| Field | Type | Description |
|
|
199
|
-
| --- | --- | --- |
|
|
200
|
-
| `label` | `string` | CTA text |
|
|
201
|
-
| `href` | `string` | Destination URL |
|
|
202
|
-
| `ariaLabel` | `string` | Optional accessible label |
|
|
203
|
-
| `target` | `_blank \| _self \| _parent \| _top` | Optional target |
|
|
204
|
-
| `rel` | `string` | Optional rel |
|
|
205
|
-
| `variant` | `"primary" \| "secondary" \| "ghost"` | Optional style hint (defaults to primary for the last CTA) |
|
|
206
|
-
|
|
207
|
-
#### `BrandTheme`
|
|
208
|
-
|
|
209
|
-
| Field | Type | Description |
|
|
210
|
-
| --- | --- | --- |
|
|
211
|
-
| `primaryColor` | `string` | Accent color for links/buttons |
|
|
212
|
-
| `backgroundColor` | `string` | Header/footer background |
|
|
213
|
-
| `textColor` | `string` | Primary text color |
|
|
214
|
-
| `fontFamily` | `string` | Font stack |
|
|
215
|
-
| `linkColor` | `string` | Optional base link color |
|
|
216
|
-
| `socialIconSize` | `string` | Size of the circular social buttons (defaults to `2.5rem`) |
|
|
217
|
-
| `buttonTextColor` | `string` | Optional primary CTA text color override |
|
|
218
|
-
| `ctaLayout` | `"inline" \| "stacked"` | Mobile CTA layout: side-by-side (`inline`) or one-per-row (`stacked`) |
|
|
219
|
-
|
|
220
|
-
### Theming via CSS variables
|
|
221
|
-
|
|
222
|
-
`styles/default.css` exposes CSS custom properties you can override globally:
|
|
223
|
-
|
|
224
|
-
| Variable | Defaults to | Purpose |
|
|
225
|
-
| --- | --- | --- |
|
|
226
|
-
| `--brand-primary` | `#2563eb` | Accent + CTA background |
|
|
227
|
-
| `--brand-bg` | `#0f172a` | Header/footer background |
|
|
228
|
-
| `--brand-text` | `#f1f5f9` | Base text color |
|
|
229
|
-
| `--brand-font` | `"Inter", system-ui` | Font stack |
|
|
230
|
-
| `--brand-link` | `#94a3b8` | Link color |
|
|
231
|
-
| `--brand-social-size` | `2.5rem` | Icon button size |
|
|
232
|
-
| `--brand-button-text` | `#f8fafc` | Primary button text color |
|
|
233
|
-
|
|
234
|
-
Set them once in your consuming app:
|
|
235
|
-
|
|
236
|
-
```css
|
|
237
|
-
:root {
|
|
238
|
-
--brand-primary: #ec4899;
|
|
239
|
-
--brand-font: "Space Grotesk", system-ui, sans-serif;
|
|
240
|
-
--brand-social-size: 2rem;
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
### Storybook
|
|
245
|
-
|
|
246
|
-
Run Storybook locally to explore examples and tweak controls:
|
|
247
|
-
|
|
248
|
-
```bash
|
|
249
|
-
bun run storybook
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
The stories showcase default, themed, and minimal configurations and expose controls for nav links, CTA buttons, and theme tokens.
|
|
253
|
-
|
|
254
|
-
### Framework demo consumers
|
|
255
|
-
|
|
256
|
-
Minimal demo apps for React (Vite), Next.js, TanStack Router (Vite), Vue, and Svelte are available under `examples/` and all share
|
|
257
|
-
`examples/shared/brand-contract.json`.
|
|
258
|
-
|
|
259
|
-
- `examples/react-vite`
|
|
260
|
-
- `examples/next-app`
|
|
261
|
-
- `examples/tanstack-vite`
|
|
262
|
-
- `examples/vue-vite`
|
|
263
|
-
- `examples/svelte-vite`
|
|
264
|
-
|
|
265
|
-
Quick commands from repo root:
|
|
266
|
-
|
|
267
|
-
```bash
|
|
268
|
-
bun run demo:setup
|
|
269
|
-
bun run demo:dev:react
|
|
270
|
-
bun run demo:dev:vue
|
|
271
|
-
bun run demo:dev:svelte
|
|
272
|
-
bun run demo:build:all
|
|
273
|
-
bun run test:smoke
|
|
274
|
-
```
|
|
275
|
-
|
|
276
|
-
See `examples/README.md` for details.
|
|
277
|
-
|
|
278
|
-
### Dev Webapp Docs
|
|
279
|
-
|
|
280
|
-
An interactive docs/playground app lives in `apps/docs` and is intentionally excluded from npm package publish size.
|
|
281
|
-
|
|
282
|
-
```bash
|
|
283
|
-
bun run docs:setup
|
|
284
|
-
bun run docs:dev
|
|
285
|
-
bun run docs:build
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### Versioning and release
|
|
289
|
-
|
|
290
|
-
This repo uses Changesets for controlled SemVer bumps.
|
|
291
|
-
|
|
292
|
-
- every PR must include a changeset (minimum `patch`)
|
|
293
|
-
|
|
294
|
-
```bash
|
|
295
|
-
bun run changeset
|
|
296
|
-
```
|
|
72
|
+
## Docs and Examples
|
|
297
73
|
|
|
298
|
-
|
|
74
|
+
- Dev docs web app: `apps/docs`
|
|
75
|
+
- Storybook: [Chromatic live preview](https://6992723e39539a58d711f188-ceiwmlxyrh.chromatic.com/)
|
|
76
|
+
- Consumer demos: `examples/react-vite`, `examples/next-app`, `examples/tanstack-vite`, `examples/vue-vite`, `examples/svelte-vite`
|
|
299
77
|
|
|
300
|
-
|
|
301
|
-
- `minor`: backward-compatible features (new optional fields/exports/adapters)
|
|
302
|
-
- `major`: breaking API/schema/peer range changes
|
|
78
|
+
## Package Surface
|
|
303
79
|
|
|
304
|
-
|
|
80
|
+
- Main: `brand-shell`
|
|
81
|
+
- Adapters: `brand-shell/web`, `brand-shell/vue`, `brand-shell/svelte`
|
|
82
|
+
- Schema: `brand-shell/schema` (or `brand-shell/schema.json`)
|
|
83
|
+
- Styles: `brand-shell/default.css`
|
|
305
84
|
|
|
306
|
-
|
|
307
|
-
- every PR must include a `.changeset/*.md` bump entry for `brand-shell` (`patch`/`minor`/`major`)
|
|
308
|
-
- bump intent is auto-checked from commits:
|
|
309
|
-
- `feat` => at least `minor`
|
|
310
|
-
- `fix` / `perf` / `refactor` => at least `patch`
|
|
311
|
-
- `!` or `BREAKING CHANGE:` => `major`
|
|
85
|
+
## Versioning
|
|
312
86
|
|
|
313
|
-
|
|
87
|
+
SemVer is managed with Changesets.
|
|
314
88
|
|
|
315
|
-
-
|
|
316
|
-
- once that release PR is merged, it publishes to npm with provenance
|
|
89
|
+
See [CONTRIBUTING.md](https://github.com/venwork-dev/brand-shell/blob/main/CONTRIBUTING.md) for development, commit policy, and release flow.
|
package/dist/default.css
CHANGED
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
--_space: var(--brand-space-md);
|
|
41
41
|
|
|
42
42
|
position: relative;
|
|
43
|
-
overflow:
|
|
43
|
+
overflow: visible;
|
|
44
44
|
isolation: isolate;
|
|
45
45
|
font-family: var(--_font);
|
|
46
46
|
background:
|
|
@@ -349,8 +349,14 @@
|
|
|
349
349
|
flex-wrap: nowrap;
|
|
350
350
|
gap: 0.36rem;
|
|
351
351
|
margin-top: 0.12rem;
|
|
352
|
-
padding-
|
|
352
|
+
padding-block: 0.08rem 0.12rem;
|
|
353
353
|
overflow-x: auto;
|
|
354
|
+
position: relative;
|
|
355
|
+
z-index: 1;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.brand-shell-header__social-link:hover {
|
|
359
|
+
transform: none;
|
|
354
360
|
}
|
|
355
361
|
}
|
|
356
362
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brand-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Reusable Header and Footer components with typed details and theme. Premium default UX, works in React, Vite, Next.js.",
|
|
5
|
+
"homepage": "https://github.com/venwork-dev/brand-shell#readme",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/venwork-dev/brand-shell.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/venwork-dev/brand-shell/issues"
|
|
12
|
+
},
|
|
5
13
|
"type": "module",
|
|
6
14
|
"main": "./dist/index.mjs",
|
|
7
15
|
"module": "./dist/index.mjs",
|