Skip to content
← Save
Edit Save
Name
Also known as (comma separated)
Brief definition
Persists changes.
Notes
Tier
Core
Useful
Reference
Deleted
Controls schema (JSON array)
[ { "id": "label", "type": "text", "label": "Label", "default": "Save" }, { "id": "busy", "type": "toggle", "label": "Busy", "default": false }, { "id": "bg", "type": "color", "label": "Colour", "default": "#241430", "presets": [ "#241430", "#A8E6C1", "#F5C2E0", "#BFD9F2", "#D9C8F0", "#E8A020" ] }, { "id": "radius", "type": "number", "label": "Corner radius", "default": 10, "min": 0, "max": 24, "step": 1 }, { "id": "disabled", "type": "toggle", "label": "Disabled", "default": false } ]
Templates (JSON object keyed by format)
{ "html": "<button type=\"button\" class=\"btn-save\" style=\"--bg:{{bg}};border-radius:{{radius}}px\" aria-busy=\"{{busy}}\"{{#if disabled}} disabled{{/if}}>\n {{#if busy}}<span class=\"btn-save__spinner\"><svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"9\" stroke-opacity=\".25\"/><path d=\"M21 12a9 9 0 00-9-9\"/></svg></span>{{/if}}\n {{#unless busy}}{{label}}{{/unless}}\n {{#if busy}}Saving{{/if}}\n</button>\n<style>\n.btn-save {\n display: inline-flex; align-items: center; justify-content: center; gap: 8px;\n min-width: 110px;\n font: 600 15px/1 system-ui, sans-serif;\n padding: 11px 20px;\n border: none;\n background: var(--bg);\n color: #FAF7F2;\n cursor: pointer;\n}\n.btn-save:hover:not(:disabled) { filter: brightness(1.1); }\n.btn-save:focus-visible { outline:2px solid #241430;outline-offset:2px; }\n.btn-save:disabled { opacity: .5; cursor: not-allowed; }\n.btn-save__spinner { display: inline-flex; }\n@keyframes btn-save-spin { to { transform: rotate(360deg); } }\n@media (prefers-reduced-motion: no-preference) {\n .btn-save__spinner { animation: btn-save-spin .2s linear infinite; }\n}\n</style>", "tailwind": "<button type=\"button\" class=\"inline-flex items-center justify-center gap-2 min-w-[110px] text-sm font-semibold text-[#FAF7F2] border-none cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed hover:brightness-110 btn-save-tw\" style=\"background:{{bg}};border-radius:{{radius}}px\" aria-busy=\"{{busy}}\"{{#if disabled}} disabled{{/if}}>\n {{#if busy}}<span class=\"inline-flex motion-safe:animate-spin\"><svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><circle cx=\"12\" cy=\"12\" r=\"9\" stroke-opacity=\".25\"/><path d=\"M21 12a9 9 0 00-9-9\"/></svg></span>{{/if}}\n {{#unless busy}}{{label}}{{/unless}}\n {{#if busy}}Saving{{/if}}\n</button>", "react": "export function SaveButton({\n label = \"{{label}}\",\n busy = {{busy}},\n bg = \"{{bg}}\",\n radius = {{radius}},\n disabled = {{disabled}},\n}) {\n return (\n <>\n <button\n type=\"button\"\n aria-busy={busy}\n disabled={disabled}\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n gap: 8,\n minWidth: 110,\n padding: \"11px 20px\",\n borderRadius: radius,\n border: \"none\",\n background: bg,\n color: \"#FAF7F2\",\n font: \"600 15px/1 system-ui, sans-serif\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n opacity: disabled ? 0.5 : 1,\n }}\n >\n {busy && (\n <svg width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" className=\"save-spin\" aria-hidden=\"true\">\n <circle cx=\"12\" cy=\"12\" r=\"9\" strokeOpacity=\".25\" />\n <path d=\"M21 12a9 9 0 00-9-9\" />\n </svg>\n )}\n {busy ? \"Saving\" : label}\n </button>\n <style>{`\n @media (prefers-reduced-motion: no-preference) {\n .save-spin { animation: save-spin .8s linear infinite; }\n @keyframes save-spin { to { transform: rotate(360deg); } }\n }\n `}</style>\n </>\n );\n}" }
Save
History