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 CHANGED
@@ -1,44 +1,40 @@
1
- ## Brand Shell
1
+ # Brand Shell
2
2
 
3
- Reusable header and footer components that ship with a premium default theme, typed props, and Storybook-based docs. Drop the package into React, Next.js, TanStack Router, Vue, or Svelte apps to keep your brand chrome consistent across projects.
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
- ### Installation
5
+ ## Install
6
6
 
7
7
  ```bash
8
8
  bun add brand-shell
9
9
  ```
10
10
 
11
- ### Basic usage
11
+ ## Quick Start (React)
12
12
 
13
13
  ```tsx
14
- import { Header, Footer, type BrandDetails, type BrandTheme } from "brand-shell";
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: "Mounika Thota",
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: "Hire Me", href: "mailto:hello@example.com" },
25
- secondaryAction: { label: "Resume", href: "/resume.pdf", target: "_blank" },
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
- twitter: "https://twitter.com/example",
29
- gmail: "hello@example.com",
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: "#0ea5e9",
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 Layout({ children }: { children: React.ReactNode }) {
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
- ### Framework-agnostic core helpers
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
- ```ts
69
- const detailsCheck = validateBrandDetails(input.details);
70
- const themeCheck = validateBrandTheme(input.theme);
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
- const normalizedDetails = detailsCheck.normalized;
77
- const normalizedTheme = themeCheck.normalized;
78
- ```
55
+ All adapters use the same `BrandDetails` + `BrandTheme` contract.
79
56
 
80
- ### JSON schema
57
+ ## Validation + Schema
81
58
 
82
- You can validate payloads in any runtime using the published schema:
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
- This repo validates the schema with Ajv in unit tests (`src/core/schema.test.ts`) to catch contract regressions before release.
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
- ```html
105
- <brand-header id="app-header"></brand-header>
106
- <brand-footer id="app-footer"></brand-footer>
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
- ### Svelte adapter
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
- Bump policy:
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
- - `patch`: bug fixes and non-breaking internal changes
301
- - `minor`: backward-compatible features (new optional fields/exports/adapters)
302
- - `major`: breaking API/schema/peer range changes
78
+ ## Package Surface
303
79
 
304
- Commit enforcement:
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
- - PR commits must follow Conventional Commits (checked by `.github/workflows/ci.yml`)
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
- Release automation runs in `.github/workflows/release.yml`, which calls the same reusable verification workflow as CI before running Changesets publish steps:
87
+ SemVer is managed with Changesets.
314
88
 
315
- - if pending changesets exist, it opens/updates a release PR
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: hidden;
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-bottom: 0.12rem;
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.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",