hermesbuttons 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 hermesbuttons contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,397 @@
1
+ # hermesbuttons
2
+
3
+ Drop-in **"Run on Hermes"** and **"Run on Hermes Skills"** buttons for any website or framework. Built as framework-agnostic Web Components with zero dependencies.
4
+
5
+ **Hermes button** (`<hermes-button>`) copies a full CLI invocation using `hermes -p "..."` so users can paste into a terminal. **Hermes skill button** (`<hermes-skill-button>`) guides skill installation and ties into Hermes Agent workflows with persistent memory.
6
+
7
+ <p align="center">
8
+ <img src="https://img.shields.io/npm/v/hermesbuttons?color=%237C3AED&label=npm" alt="npm version">
9
+ <img src="https://img.shields.io/bundlephobia/minzip/hermesbuttons?color=%237C3AED" alt="bundle size">
10
+ <img src="https://img.shields.io/npm/l/hermesbuttons?color=%237C3AED" alt="license">
11
+ </p>
12
+
13
+ ---
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npm install hermesbuttons
19
+ ```
20
+
21
+ **Or use the CDN** (no build step):
22
+
23
+ ```html
24
+ <script src="https://unpkg.com/hermesbuttons"></script>
25
+ ```
26
+
27
+ ---
28
+
29
+ ## Quick Start
30
+
31
+ ```html
32
+ <hermes-button command="/research deep-dive on React Server Components" theme="branded"></hermes-button>
33
+ <hermes-skill-button
34
+ command="/competitive-analysis"
35
+ skill-url="https://example.com/skills/competitive-analysis.zip"
36
+ ></hermes-skill-button>
37
+ ```
38
+
39
+ ---
40
+
41
+ ## Framework Integration
42
+
43
+ ### Vanilla HTML / CDN
44
+
45
+ ```html
46
+ <script src="https://unpkg.com/hermesbuttons"></script>
47
+
48
+ <hermes-button command="/weekly-standup" theme="branded"></hermes-button>
49
+ <hermes-skill-button command="/draft-blog-post" theme="dark"></hermes-skill-button>
50
+
51
+ <script>
52
+ document.querySelector('hermes-button')
53
+ .addEventListener('hb-copy', (e) => console.log('Copied:', e.detail.command));
54
+ </script>
55
+ ```
56
+
57
+ ### React / Next.js
58
+
59
+ Use the dedicated React wrappers (handles SSR, hydration, and prop forwarding):
60
+
61
+ ```tsx
62
+ import { HermesButton, HermesSkillButton } from 'hermesbuttons/react';
63
+
64
+ function App() {
65
+ return (
66
+ <>
67
+ <HermesButton
68
+ command="/research deep-dive on React Server Components"
69
+ theme="branded"
70
+ onCopy={(cmd) => console.log('Copied:', cmd)}
71
+ onHbCopy={(e) => console.log('Event:', e.detail.command)}
72
+ />
73
+ <HermesSkillButton
74
+ command="/competitive-analysis"
75
+ skillUrl="https://example.com/skills/competitive-analysis.zip"
76
+ theme="dark"
77
+ />
78
+ </>
79
+ );
80
+ }
81
+ ```
82
+
83
+ The React wrapper:
84
+
85
+ - Includes `'use client'` for Next.js App Router
86
+ - Handles SSR/hydration with `suppressHydrationWarning`
87
+ - Lazy-loads the Web Components to avoid SSR crashes
88
+ - Forwards both property callbacks (`onCopy`, `onDownload`) and CustomEvent listeners (`onHbCopy`, `onHbDownload`, etc.)
89
+
90
+ ### Vue / Nuxt
91
+
92
+ **Option A: Vue Plugin (recommended)**
93
+
94
+ ```ts
95
+ // main.ts
96
+ import { createApp } from 'vue';
97
+ import { HermesButtonsPlugin } from 'hermesbuttons/vue';
98
+ import App from './App.vue';
99
+
100
+ const app = createApp(App);
101
+ app.use(HermesButtonsPlugin); // auto-configures isCustomElement
102
+ app.mount('#app');
103
+ ```
104
+
105
+ ```vue
106
+ <template>
107
+ <hermes-button
108
+ command="/weekly-standup"
109
+ theme="branded"
110
+ @hb-copy="onCopy"
111
+ />
112
+ <hermes-skill-button
113
+ command="/draft-blog-post"
114
+ theme="dark"
115
+ @hb-download="onDownload"
116
+ />
117
+ </template>
118
+
119
+ <script setup>
120
+ function onCopy(e) {
121
+ console.log('Copied:', e.detail.command);
122
+ }
123
+ function onDownload(e) {
124
+ console.log('Downloaded:', e.detail.url);
125
+ }
126
+ </script>
127
+ ```
128
+
129
+ **Option B: Manual setup**
130
+
131
+ ```ts
132
+ // vite.config.ts
133
+ import vue from '@vitejs/plugin-vue';
134
+
135
+ export default {
136
+ plugins: [
137
+ vue({
138
+ template: {
139
+ compilerOptions: {
140
+ isCustomElement: (tag) =>
141
+ ['hermes-button', 'hermes-skill-button', 'hermes-popup-dialog'].includes(tag),
142
+ },
143
+ },
144
+ }),
145
+ ],
146
+ };
147
+ ```
148
+
149
+ ```vue
150
+ <script setup>
151
+ import 'hermesbuttons';
152
+ </script>
153
+
154
+ <template>
155
+ <hermes-button command="/weekly-standup" theme="branded" @hb-copy="onCopy" />
156
+ </template>
157
+ ```
158
+
159
+ ### Svelte / SvelteKit
160
+
161
+ ```svelte
162
+ <script>
163
+ import 'hermesbuttons';
164
+
165
+ function handleCopy(e) {
166
+ console.log('Copied:', e.detail.command);
167
+ }
168
+ </script>
169
+
170
+ <hermes-button
171
+ command="/research deep-dive on React Server Components"
172
+ theme="branded"
173
+ on:hb-copy={handleCopy}
174
+ />
175
+ <hermes-skill-button command="/competitive-analysis" theme="dark" />
176
+ ```
177
+
178
+ ### Angular
179
+
180
+ ```typescript
181
+ // app.module.ts
182
+ import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
183
+ import 'hermesbuttons';
184
+
185
+ @NgModule({
186
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
187
+ // ...
188
+ })
189
+ export class AppModule {}
190
+ ```
191
+
192
+ ```html
193
+ <!-- component.html -->
194
+ <hermes-button
195
+ command="/weekly-standup"
196
+ theme="branded"
197
+ (hb-copy)="onCopy($event)"
198
+ ></hermes-button>
199
+
200
+ <hermes-skill-button
201
+ command="/draft-blog-post"
202
+ skill-url="https://example.com/skills/draft-blog.zip"
203
+ theme="dark"
204
+ (hb-download)="onDownload($event)"
205
+ ></hermes-skill-button>
206
+ ```
207
+
208
+ ### Solid
209
+
210
+ ```tsx
211
+ import 'hermesbuttons';
212
+
213
+ function App() {
214
+ return (
215
+ <>
216
+ <hermes-button
217
+ command="/research deep-dive on React Server Components"
218
+ theme="branded"
219
+ on:hb-copy={(e) => console.log(e.detail.command)}
220
+ />
221
+ <hermes-skill-button command="/competitive-analysis" theme="dark" />
222
+ </>
223
+ );
224
+ }
225
+ ```
226
+
227
+ ### Astro
228
+
229
+ ```astro
230
+ ---
231
+ ---
232
+ <script>
233
+ import 'hermesbuttons';
234
+ </script>
235
+
236
+ <hermes-button command="/weekly-standup" theme="branded" />
237
+ <hermes-skill-button command="/draft-blog-post" theme="dark" />
238
+
239
+ <script>
240
+ document.querySelector('hermes-button')
241
+ ?.addEventListener('hb-copy', (e) => console.log(e.detail.command));
242
+ </script>
243
+ ```
244
+
245
+ ### Programmatic JavaScript API
246
+
247
+ ```js
248
+ import { createHermesButton, createHermesSkillButton } from 'hermesbuttons';
249
+
250
+ const btn = createHermesButton({
251
+ command: '/competitive-analysis',
252
+ theme: 'branded',
253
+ onCopy: (cmd) => console.log('Copied:', cmd),
254
+ });
255
+
256
+ document.getElementById('container').appendChild(btn);
257
+ ```
258
+
259
+ When using the global build:
260
+
261
+ ```js
262
+ const btn = HermesButtons.createHermesButton({ command: '/weekly-standup', theme: 'branded' });
263
+ document.body.appendChild(btn);
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Themes
269
+
270
+ | Theme | Description |
271
+ |-------|-------------|
272
+ | `branded` | Violet primary (`#7C3AED`), white text **(default)** |
273
+ | `branded-alt` | Teal primary (`#14B8A6`), white text — secondary accent |
274
+ | `dark` | Dark surface, light text, violet accents |
275
+ | `light` | Light surface, dark text, violet accents |
276
+ | `system` | Auto-switches between `light`/`dark` based on `prefers-color-scheme` |
277
+
278
+ ## Sizes
279
+
280
+ | Size | Height |
281
+ |------|--------|
282
+ | `sm` | 2rem (32px at default font size) |
283
+ | `md` | 2.5rem (40px) **(default)** |
284
+ | `lg` | 3rem (48px) |
285
+
286
+ Sizes use `rem` units and scale with the user's browser font preferences.
287
+
288
+ ---
289
+
290
+ ## Events
291
+
292
+ All buttons dispatch native `CustomEvent`s with `bubbles: true` and `composed: true` (crosses Shadow DOM).
293
+
294
+ | Event | Detail | Fired when |
295
+ |-------|--------|------------|
296
+ | `hb-copy` | `{ command: string }` | Command copied to clipboard |
297
+ | `hb-open` | `{ command: string }` | Button clicked / popup opens |
298
+ | `hb-close` | — | Popup closed |
299
+ | `hb-download` | `{ url: string }` | Skill package downloaded (Hermes skill button only) |
300
+
301
+ ```js
302
+ el.addEventListener('hb-copy', (e) => {
303
+ console.log('Copied:', e.detail.command);
304
+ });
305
+ ```
306
+
307
+ ---
308
+
309
+ ## API Reference
310
+
311
+ ### `<hermes-button>` Attributes
312
+
313
+ | Attribute | Type | Default | Description |
314
+ |-----------|------|---------|-------------|
315
+ | `command` | `string` | — | The prompt/command to run |
316
+ | `theme` | `'branded' \| 'branded-alt' \| 'dark' \| 'light' \| 'system'` | `'branded'` | Theme variant |
317
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
318
+ | `variant` | `'filled' \| 'outline' \| 'ghost'` | `'filled'` | Visual style |
319
+ | `shape` | `'rounded' \| 'pill' \| 'square'` | `'rounded'` | Border radius |
320
+ | `popup` | `'true' \| 'false'` | `'true'` | Show popup dialog on click |
321
+ | `prompt-flag` | `'true' \| 'false'` | `'true'` | Prepend `hermes -p` to the command |
322
+ | `popup-title` | `string` | `'Run on Hermes'` | Custom popup title |
323
+ | `popup-description` | `string` | — | Custom popup description |
324
+
325
+ ### `<hermes-skill-button>` Attributes
326
+
327
+ | Attribute | Type | Default | Description |
328
+ |-----------|------|---------|-------------|
329
+ | `command` | `string` | — | The slash command to run |
330
+ | `skill-url` | `string` | — | URL to downloadable skill package |
331
+ | `theme` | `'branded' \| 'branded-alt' \| 'dark' \| 'light' \| 'system'` | `'branded'` | Theme variant |
332
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
333
+ | `variant` | `'filled' \| 'outline' \| 'ghost'` | `'filled'` | Visual style |
334
+ | `shape` | `'rounded' \| 'pill' \| 'square'` | `'rounded'` | Border radius |
335
+ | `popup` | `'true' \| 'false'` | `'true'` | Show popup dialog on click |
336
+ | `popup-title` | `string` | `'Run on Hermes Skills'` | Custom popup title |
337
+ | `popup-description` | `string` | — | Custom popup description |
338
+
339
+ ### JavaScript Exports
340
+
341
+ ```ts
342
+ // Web Components + factories
343
+ import {
344
+ HermesButton, // Web Component class
345
+ HermesSkillButton, // Web Component class
346
+ createHermesButton, // Factory function
347
+ createHermesSkillButton,// Factory function
348
+ showPopup, // Show popup programmatically
349
+ register, // Manually register all custom elements
350
+ registerHermesButton, // Register only hermes-button
351
+ registerHermesSkillButton, // Register only hermes-skill-button
352
+ } from 'hermesbuttons';
353
+
354
+ // React wrappers (SSR-safe, includes 'use client')
355
+ import { HermesButton, HermesSkillButton } from 'hermesbuttons/react';
356
+
357
+ // Vue plugin
358
+ import { HermesButtonsPlugin } from 'hermesbuttons/vue';
359
+
360
+ // Raw SVG icons + theme tokens
361
+ import { HERMES_ICON, HERMES_SKILL_ICON, BRAND_COLOR, ALT_BRAND_COLOR } from 'hermesbuttons';
362
+ ```
363
+
364
+ ### Explicit Registration
365
+
366
+ Registration happens automatically on import. For frameworks that need timing control:
367
+
368
+ ```ts
369
+ import { register } from 'hermesbuttons';
370
+
371
+ // Call when you're ready to register the custom elements
372
+ register();
373
+ ```
374
+
375
+ Or register individually with custom tag names:
376
+
377
+ ```ts
378
+ import { registerHermesButton, registerHermesSkillButton } from 'hermesbuttons';
379
+
380
+ registerHermesButton('my-hermes-btn');
381
+ registerHermesSkillButton('my-hermes-skill-btn');
382
+ ```
383
+
384
+ ---
385
+
386
+ ## Browser Support
387
+
388
+ Works in all browsers that support [Custom Elements v1](https://caniuse.com/custom-elementsv1):
389
+
390
+ - Chrome 67+
391
+ - Firefox 63+
392
+ - Safari 10.1+
393
+ - Edge 79+
394
+
395
+ ## License
396
+
397
+ MIT