{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "buttons", "type": "registry:item", "title": "aesthetic Button", "description": "Aesthetic Button primitive, v0.25.0. Installs ae-button, ae-button-compact, ae-button-quiet, ae-icon, ae-send, ae-send-done, ae-send-label without the full stylesheet. Recipes: send.js.", "registryDependencies": [ "https://aesthetic.mistystep.io/r/aesthetic-base.json" ], "meta": { "version": "0.25.0", "tier": "primitive", "route": "buttons", "classes": [ "ae-button", "ae-button-compact", "ae-button-quiet", "ae-icon", "ae-send", "ae-send-done", "ae-send-label" ], "attributes": [], "tokens": [ "--ae-surface", "--ae-wash", "--ae-ink", "--ae-ink-faint", "--ae-accent", "--ae-surface-dark", "--ae-wash-dark", "--ae-ink-dark", "--ae-ink-faint-dark", "--ae-accent-dark", "--ae-font", "--ae-font-mono", "--ae-w-regular", "--ae-ease", "--ae-quick", "--ae-w-medium", "--ae-radius", "--ae-space-2", "--ae-gentle" ], "recipes": ["send.js"] }, "files": [ { "path": "registry/buttons/aesthetic.buttons.css", "type": "registry:file", "target": "~/aesthetic.buttons.css", "content": "/* aesthetic buttons v0.25.0 — generated by scripts/build-registry.mjs. */\n@import './aesthetic.base.css';\n\n:root {\n --ae-w-medium: 550;\n --ae-radius: 0;\n --ae-space-2: 0.5em;\n --ae-gentle: 480ms;\n}\n\n.light,\n[data-ae-mode='light'] {\n color-scheme: light;\n}\n\n.ae-icon {\nwidth: 1.2em;\n height: 1.2em;\n stroke: currentColor;\n stroke-width: 1.5;\n stroke-linecap: round;\n stroke-linejoin: round;\n fill: none;\n vertical-align: -0.2em;\n}\n\n.ae-button {\ndisplay: inline-flex;\n align-items: center;\n justify-content: center;\n gap: var(--ae-space-2);\n background: var(--ae-ink);\n border: 1px solid var(--ae-ink);\n border-radius: var(--ae-radius);\n color: var(--ae-surface);\n font-weight: var(--ae-w-medium);\n padding: 0.55em 1.5em;\n min-height: 44px;\n cursor: pointer;\n transition:\n opacity var(--ae-quick) var(--ae-ease),\n background-color var(--ae-quick) var(--ae-ease),\n transform var(--ae-quick) var(--ae-ease);\n}\n\n.ae-button:hover {\nopacity: 0.9;\n}\n\n.ae-button:active {\ntransform: translateY(1px) scale(0.99);\n}\n\n.ae-button:disabled {\ncursor: default;\n opacity: 0.7;\n transform: none;\n}\n\n.ae-button-quiet {\nbackground: transparent;\n color: var(--ae-ink);\n}\n\n.ae-button-quiet:hover {\nbackground: var(--ae-wash);\n opacity: 1;\n}\n\n.ae-button-compact {\nfont-size: 13px;\n padding: 0.35em 1em;\n min-height: 32px;\n}\n\n.ae-send {\nposition: relative;\n overflow: hidden;\n}\n\n.ae-send .ae-send-label,\n.ae-send .ae-send-done {\ndisplay: inline-flex;\n align-items: center;\n gap: var(--ae-space-2);\n transition:\n opacity var(--ae-gentle) var(--ae-ease),\n transform var(--ae-gentle) var(--ae-ease);\n}\n\n.ae-send .ae-send-done {\nposition: absolute;\n inset: 0;\n justify-content: center;\n opacity: 0;\n transform: translateY(45%);\n}\n\n.ae-send.is-sent .ae-send-label {\nopacity: 0;\n transform: translateY(-55%);\n}\n\n.ae-send.is-sent .ae-send-done {\nopacity: 1;\n transform: translateY(0);\n}\n\n.ae-send.is-sent,\n.ae-send.is-sent:disabled {\nopacity: 1;\n}\n" }, { "path": "recipes/send.js", "type": "registry:file", "target": "~/aesthetic.send.js", "content": "/* the send moment: resolve once, persist, and say so. Call\n window.aeSend(button, 'Sent') on success — it flips the costume,\n disables the control (success is never rewound), and announces the\n resolved state to assistive tech: the aria-hidden done layer is\n silent on its own, so a live region speaks for it.\n\n Forms marked data-ae-demo resolve on submit without a network —\n the site's demo hook; real consumers call aeSend from their own\n submit handling. */\n(() => {\n if (window.aeSend) return;\n const live = document.createElement('span');\n live.className = 'ae-sr';\n live.setAttribute('role', 'status');\n (document.body || document.documentElement).appendChild(live);\n\n window.aeSend = (btn, done) => {\n if (!btn || btn.classList.contains('is-sent')) return;\n btn.classList.add('is-sent');\n btn.disabled = true;\n live.textContent = '';\n requestAnimationFrame(() => {\n live.textContent =\n done ||\n btn.dataset.aeDone ||\n (btn.querySelector('.ae-send-done') || {}).textContent ||\n 'Done';\n });\n };\n\n document.querySelectorAll('form[data-ae-demo]').forEach((form) => {\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n window.aeSend(form.querySelector('.ae-send'));\n });\n });\n})();\n" } ] }