Instantly share code, notes, and snippets.
Last active
April 15, 2026 12:02
-
Star
0
(0)
You must be signed in to star a gist -
Fork
0
(0)
You must be signed in to fork a gist
-
-
Save Markus-ipse/3fc48929c2b8ddc2701f6af5365f6c89 to your computer and use it in GitHub Desktop.
Howwe — AI button explorations (6 variants, light + dark)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title>Howwe — AI Button Explorations</title> | |
| <meta name="viewport" content="width=device-width,initial-scale=1" /> | |
| <style> | |
| :root { | |
| --space: 16px; | |
| --radius: 12px; | |
| } | |
| body { | |
| margin: 0; | |
| font-family: | |
| -apple-system, BlinkMacSystemFont, 'Segoe UI', Mulish, Roboto, | |
| sans-serif; | |
| background: #f4f5f8; | |
| } | |
| .page { | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| min-height: 100vh; | |
| } | |
| @media (max-width: 900px) { | |
| .page { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| .pane { | |
| padding: 32px; | |
| overflow-x: hidden; | |
| } | |
| .pane h1 { | |
| margin: 0 0 8px; | |
| font-size: 22px; | |
| font-weight: 700; | |
| } | |
| .pane p.intro { | |
| margin: 0 0 24px; | |
| font-size: 13px; | |
| line-height: 1.5; | |
| max-width: 56ch; | |
| } | |
| /* light pane */ | |
| .pane--light { | |
| --surface: #ffffff; | |
| --main-font: #1f2937; | |
| --secondary-font: #6b7280; | |
| --divider: #e5e7eb; | |
| --frames-and-lines: #d1d5db; | |
| --disabled-fonts: #9ca3af; | |
| --disabled-lines: #e5e7eb; | |
| --action-blue: #1582c5; | |
| --status-future-purple: #9427ca; | |
| background: #f4f5f8; | |
| color: var(--main-font); | |
| } | |
| /* dark pane */ | |
| .pane--dark { | |
| --surface: #1f2230; | |
| --main-font: #e5e7eb; | |
| --secondary-font: #9ca3af; | |
| --divider: #2d3142; | |
| --frames-and-lines: #3a3f55; | |
| --disabled-fonts: #6b7280; | |
| --disabled-lines: #3a3f55; | |
| --action-blue: #5ab3e8; | |
| --status-future-purple: #c895ff; | |
| background: #14161f; | |
| color: var(--main-font); | |
| } | |
| .AiButtonLab { | |
| overflow-x: hidden; | |
| --ai-grad-start: var(--action-blue); | |
| --ai-grad-end: var(--status-future-purple); | |
| --ai-grad-mid: color-mix( | |
| in oklch, | |
| var(--ai-grad-start), | |
| var(--ai-grad-end) | |
| ); | |
| --ai-gradient: linear-gradient( | |
| 120deg, | |
| var(--ai-grad-start) 0%, | |
| var(--ai-grad-mid) 50%, | |
| var(--ai-grad-end) 100% | |
| ); | |
| --ai-soft-bg: color-mix(in srgb, var(--ai-grad-end) 8%, transparent); | |
| --ai-soft-border: color-mix( | |
| in srgb, | |
| var(--ai-grad-end) 35%, | |
| transparent | |
| ); | |
| --ai-glow: 0 0 0 3px | |
| color-mix(in srgb, var(--ai-grad-end) 18%, transparent); | |
| } | |
| .AiShimmerIcon__stopA { | |
| stop-color: var(--action-blue); | |
| } | |
| .AiShimmerIcon__stopB { | |
| stop-color: var(--status-future-purple); | |
| } | |
| .AiButtonLab__variantGrid { | |
| display: grid; | |
| grid-template-columns: 1fr; | |
| gap: 16px; | |
| } | |
| .AiButtonLab__variant { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 8px; | |
| padding: 16px; | |
| border: 1px solid var(--divider); | |
| border-radius: var(--radius); | |
| background: var(--surface); | |
| } | |
| .AiButtonLab__variantTitle { | |
| font-size: 14px; | |
| font-weight: 600; | |
| margin: 0; | |
| } | |
| .AiButtonLab__variantDesc { | |
| font-size: 12px; | |
| color: var(--secondary-font); | |
| margin: 0; | |
| } | |
| .AiButtonLab__row { | |
| display: flex; | |
| flex-wrap: wrap; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .AiBtn { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 6px; | |
| height: 32px; | |
| padding: 0 14px; | |
| border-radius: 999px; | |
| font-weight: 600; | |
| font-size: 13px; | |
| border: 1px solid transparent; | |
| background: transparent; | |
| cursor: pointer; | |
| transition: all 0.2s ease; | |
| line-height: 1; | |
| } | |
| .AiIconBtn { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 28px; | |
| height: 28px; | |
| border-radius: 8px; | |
| border: 1px solid transparent; | |
| background: transparent; | |
| cursor: pointer; | |
| padding: 0; | |
| transition: all 0.2s ease; | |
| } | |
| /* 1. Fill */ | |
| .AiBtn--fill, | |
| .AiIconBtn--fill { | |
| color: #fff; | |
| background: var(--ai-gradient); | |
| background-size: 200% 200%; | |
| background-position: 0% 50%; | |
| } | |
| .AiBtn--fill:hover, | |
| .AiIconBtn--fill:hover { | |
| background-position: 100% 50%; | |
| box-shadow: var(--ai-glow); | |
| } | |
| /* 2. Outline (animated) */ | |
| .AiBtn--outline { | |
| color: transparent; | |
| background: var(--surface); | |
| background-image: | |
| linear-gradient(var(--surface), var(--surface)), | |
| linear-gradient( | |
| 120deg, | |
| var(--ai-grad-start) 0%, | |
| var(--ai-grad-end) 25%, | |
| var(--ai-grad-start) 50%, | |
| var(--ai-grad-end) 75%, | |
| var(--ai-grad-start) 100% | |
| ); | |
| background-size: | |
| 100% 100%, | |
| 300% 100%; | |
| background-position: | |
| 0 0, | |
| 0% 50%; | |
| background-origin: border-box; | |
| background-clip: padding-box, border-box; | |
| animation: ai-outline-sweep 3s linear infinite; | |
| } | |
| .AiBtn--outline .AiBtn__label { | |
| line-height: 1.4; | |
| padding: 2px 0; | |
| background: linear-gradient( | |
| 120deg, | |
| var(--ai-grad-start) 0%, | |
| var(--ai-grad-end) 25%, | |
| var(--ai-grad-start) 50%, | |
| var(--ai-grad-end) 75%, | |
| var(--ai-grad-start) 100% | |
| ); | |
| background-size: 300% 100%; | |
| background-position: 0% 50%; | |
| background-clip: text; | |
| color: transparent; | |
| font-weight: 700; | |
| animation: ai-outline-label-sweep 3s linear infinite; | |
| } | |
| .AiIconBtn--outline:hover { | |
| background: var(--ai-soft-bg); | |
| } | |
| @keyframes ai-outline-sweep { | |
| 0% { | |
| background-position: | |
| 0 0, | |
| 0% 50%; | |
| } | |
| 100% { | |
| background-position: | |
| 0 0, | |
| 300% 50%; | |
| } | |
| } | |
| @keyframes ai-outline-label-sweep { | |
| 0% { | |
| background-position: 0% 50%; | |
| } | |
| 100% { | |
| background-position: 300% 50%; | |
| } | |
| } | |
| /* 3. Tint */ | |
| .AiBtn--tint, | |
| .AiIconBtn--tint { | |
| background: var(--ai-soft-bg); | |
| } | |
| .AiBtn--tint .AiBtn__label { | |
| line-height: 1.4; | |
| padding: 2px 0; | |
| background: var(--ai-gradient); | |
| background-clip: text; | |
| color: transparent; | |
| font-weight: 700; | |
| } | |
| .AiBtn--tint:hover, | |
| .AiIconBtn--tint:hover { | |
| background: color-mix(in srgb, var(--ai-grad-mid) 14%, transparent); | |
| } | |
| /* 4. Shimmer */ | |
| .AiBtn--shimmer, | |
| .AiIconBtn--shimmer, | |
| .AiBtn--shimmerSoft, | |
| .AiIconBtn--shimmerSoft { | |
| overflow: hidden; | |
| color: #fff; | |
| background: var(--ai-gradient); | |
| } | |
| .AiBtn--shimmer::after, | |
| .AiIconBtn--shimmer::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient( | |
| 100deg, | |
| transparent 35%, | |
| rgb(255 255 255 / 55%) 50%, | |
| transparent 65% | |
| ); | |
| transform: translateX(-100%); | |
| animation: ai-shimmer 2.6s ease-in-out infinite; | |
| } | |
| /* 4.1 Softer shimmer — narrower stripe, lower opacity, slower sweep */ | |
| .AiBtn--shimmerSoft::after, | |
| .AiIconBtn--shimmerSoft::after { | |
| content: ''; | |
| position: absolute; | |
| inset: 0; | |
| background: linear-gradient( | |
| 100deg, | |
| transparent 42%, | |
| rgb(255 255 255 / 22%) 50%, | |
| transparent 58% | |
| ); | |
| transform: translateX(-100%); | |
| animation: ai-shimmer-soft 5.2s ease-in-out infinite; | |
| } | |
| @keyframes ai-shimmer-soft { | |
| 0% { | |
| transform: translateX(-100%); | |
| } | |
| 30%, | |
| 100% { | |
| transform: translateX(100%); | |
| } | |
| } | |
| @keyframes ai-shimmer { | |
| 0% { | |
| transform: translateX(-100%); | |
| } | |
| 60%, | |
| 100% { | |
| transform: translateX(100%); | |
| } | |
| } | |
| /* 5. Underline */ | |
| .AiBtn--underline { | |
| color: var(--main-font); | |
| background: var(--surface); | |
| border: 1px solid var(--divider); | |
| overflow: hidden; | |
| } | |
| .AiBtn--underline::after, | |
| .AiIconBtn--underline::after { | |
| content: ''; | |
| position: absolute; | |
| left: 0; | |
| right: 0; | |
| bottom: 0; | |
| height: 2px; | |
| background: var(--ai-gradient); | |
| background-size: 200% 100%; | |
| animation: ai-underline 2.8s ease-in-out infinite; | |
| } | |
| .AiIconBtn--underline { | |
| overflow: hidden; | |
| } | |
| .AiBtn--underline:hover, | |
| .AiIconBtn--underline:hover { | |
| background: var(--ai-soft-bg); | |
| border-color: var(--ai-soft-border); | |
| } | |
| @keyframes ai-underline { | |
| 0% { | |
| background-position: 0% 50%; | |
| } | |
| 100% { | |
| background-position: 200% 50%; | |
| } | |
| } | |
| /* Milestone form mock */ | |
| .MsForm { | |
| margin-top: 24px; | |
| padding: 20px; | |
| max-width: 520px; | |
| border: 1px solid var(--divider); | |
| border-radius: 8px; | |
| background: var(--surface); | |
| } | |
| .MsForm h2 { | |
| margin: 0 0 4px; | |
| font-size: 18px; | |
| font-weight: 700; | |
| } | |
| .MsForm__hint { | |
| margin: 0 0 20px; | |
| font-size: 12px; | |
| color: var(--secondary-font); | |
| } | |
| .MsForm__row { | |
| display: flex; | |
| align-items: flex-start; | |
| gap: 12px; | |
| margin-bottom: 16px; | |
| } | |
| .MsForm__icon { | |
| width: 20px; | |
| height: 20px; | |
| color: var(--secondary-font); | |
| flex-shrink: 0; | |
| margin-top: 26px; | |
| } | |
| .MsForm__field { | |
| flex: 1; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 6px; | |
| } | |
| .MsForm__label { | |
| font-size: 12px; | |
| font-weight: 600; | |
| color: var(--main-font); | |
| } | |
| .MsForm__input, | |
| .MsForm__textarea, | |
| .MsForm__select { | |
| width: 100%; | |
| padding: 6px 10px; | |
| border: 1px solid var(--frames-and-lines); | |
| border-radius: 4px; | |
| background: var(--surface); | |
| color: var(--main-font); | |
| font: inherit; | |
| } | |
| .MsForm__input.is-title { | |
| font-size: 18px; | |
| font-weight: 700; | |
| } | |
| .MsForm__textarea { | |
| min-height: 90px; | |
| resize: vertical; | |
| } | |
| .MsForm__aiRow { | |
| display: flex; | |
| gap: 4px; | |
| margin-top: 8px; | |
| } | |
| .MsForm__helper { | |
| width: 28px; | |
| height: 28px; | |
| border: none; | |
| border-radius: 6px; | |
| background: transparent; | |
| color: var(--action-blue); | |
| cursor: pointer; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .MsForm__helper:hover { | |
| background: color-mix(in srgb, var(--action-blue) 10%, transparent); | |
| } | |
| .MsForm__footer { | |
| display: flex; | |
| justify-content: flex-end; | |
| gap: 8px; | |
| margin-top: 16px; | |
| } | |
| .MsForm__btn { | |
| padding: 6px 14px; | |
| border-radius: 4px; | |
| border: 1px solid var(--frames-and-lines); | |
| background: var(--surface); | |
| color: var(--main-font); | |
| cursor: pointer; | |
| } | |
| .MsForm__btn--primary { | |
| background: var(--action-blue); | |
| border-color: var(--action-blue); | |
| color: #fff; | |
| } | |
| /* Shimmering sparkles icon — gradient fill animates across */ | |
| .ShimmerSparkles { | |
| width: 20px; | |
| height: 20px; | |
| overflow: hidden; | |
| flex-shrink: 0; | |
| filter: drop-shadow( | |
| 0 0 2px color-mix(in srgb, var(--status-future-purple) 45%, transparent) | |
| ); | |
| } | |
| /* Ghost AI button (icon only, shimmering fill) */ | |
| .AiGhostBtn { | |
| position: relative; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| width: 28px; | |
| height: 28px; | |
| border-radius: 6px; | |
| border: 1px solid transparent; | |
| background: transparent; | |
| cursor: pointer; | |
| padding: 0; | |
| transition: background 0.15s ease; | |
| } | |
| .AiGhostBtn:hover { | |
| background: var(--ai-soft-bg); | |
| } | |
| /* 6. Pulse */ | |
| .AiBtn--pulse { | |
| color: var(--ai-grad-mid); | |
| background: var(--surface); | |
| border: 1px dashed var(--ai-soft-border); | |
| animation: ai-pulse 2.4s ease-in-out infinite; | |
| } | |
| .AiIconBtn--pulse { | |
| animation: ai-pulse 2.4s ease-in-out infinite; | |
| } | |
| .AiBtn--pulse:hover, | |
| .AiIconBtn--pulse:hover { | |
| animation-play-state: paused; | |
| background: var(--ai-soft-bg); | |
| } | |
| .AiBtn--pulse:hover { | |
| border-color: var(--ai-grad-mid); | |
| } | |
| @keyframes ai-pulse { | |
| 0%, | |
| 100% { | |
| box-shadow: 0 0 0 0 | |
| color-mix(in srgb, var(--ai-grad-mid) 30%, transparent); | |
| } | |
| 50% { | |
| box-shadow: 0 0 0 6px | |
| color-mix(in srgb, var(--ai-grad-mid) 0%, transparent); | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- shared shimmer gradient defs (one per pane so each picks up its own tokens) --> | |
| <svg | |
| width="0" | |
| height="0" | |
| style="position: absolute" | |
| aria-hidden="true" | |
| ></svg> | |
| <div class="page"> | |
| <section class="pane pane--light"> | |
| <h1>Light mode</h1> | |
| <p class="intro"> | |
| Six exploratory designs for AI feature buttons. Gradient uses | |
| existing Howwe tokens (<code>--action-blue</code> → | |
| <code>--status-future-purple</code>). Icon strokes shimmer with an | |
| animated SVG gradient. | |
| </p> | |
| <div class="AiButtonLab" id="lab-light"></div> | |
| <div class="AiButtonLab" id="form-light"></div> | |
| </section> | |
| <section class="pane pane--dark"> | |
| <h1>Dark mode</h1> | |
| <p class="intro"> | |
| Same six variants, dark surface tokens. The gradient automatically | |
| rebalances because both endpoints are theme tokens. | |
| </p> | |
| <div class="AiButtonLab" id="lab-dark"></div> | |
| <div class="AiButtonLab" id="form-dark"></div> | |
| </section> | |
| </div> | |
| <script> | |
| const variants = [ | |
| { | |
| id: 'fill', | |
| title: '1. Gradient fill', | |
| desc: 'Solid statement — strongest call-out.', | |
| white: true, | |
| }, | |
| { | |
| id: 'outline', | |
| title: '2. Gradient outline', | |
| desc: 'Animated gradient border + shimmering label.', | |
| }, | |
| { | |
| id: 'tint', | |
| title: '3. Soft tint', | |
| desc: 'Tinted background with gradient label/icon.', | |
| }, | |
| { | |
| id: 'shimmer', | |
| title: '4. Shimmer', | |
| desc: 'Gradient fill with continuous highlight sweep.', | |
| white: true, | |
| }, | |
| { | |
| id: 'shimmerSoft', | |
| title: '4.1 Shimmer (soft)', | |
| desc: 'Same idea as #4 but narrower stripe and lower opacity — reads as a gentle shine instead of a spotlight pass.', | |
| white: true, | |
| }, | |
| { | |
| id: 'underline', | |
| title: '5. Gradient underline', | |
| desc: 'Neutral pill with gradient bar at the bottom.', | |
| }, | |
| { | |
| id: 'pulse', | |
| title: '6. Breathing pulse', | |
| desc: 'Neutral body with a gentle expanding glow.', | |
| }, | |
| ]; | |
| const paths = { | |
| thunder: '<path d="M13 2 L3 14 h9 l-1 8 10-12 h-9 l1-8 z"/>', | |
| bulb: '<path d="M9 18h6"/><path d="M10 22h4"/><path d="M12 2a7 7 0 0 0-4 12.5V18h8v-3.5A7 7 0 0 0 12 2z"/>', | |
| }; | |
| function shimmerSvg(pathHtml, white, gradId) { | |
| const stroke = white ? '#fff' : `url(#${gradId})`; | |
| return `<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="${stroke}" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="overflow:hidden;flex-shrink:0">${pathHtml}</svg>`; | |
| } | |
| function defs(gradId) { | |
| return `<svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs><linearGradient id="${gradId}" gradientUnits="userSpaceOnUse" x1="-12" y1="0" x2="0" y2="0"><stop class="AiShimmerIcon__stopA" offset="0%"/><stop class="AiShimmerIcon__stopB" offset="50%"/><stop class="AiShimmerIcon__stopA" offset="100%"/><animate attributeName="x1" values="-24;24" dur="2.4s" repeatCount="indefinite"/><animate attributeName="x2" values="0;48" dur="2.4s" repeatCount="indefinite"/></linearGradient></defs></svg>`; | |
| } | |
| function renderLab(targetId, gradId) { | |
| const lab = document.getElementById(targetId); | |
| const html = | |
| defs(gradId) + | |
| '<div class="AiButtonLab__variantGrid">' + | |
| variants | |
| .map( | |
| (v) => ` | |
| <div class="AiButtonLab__variant"> | |
| <h4 class="AiButtonLab__variantTitle">${v.title}</h4> | |
| <p class="AiButtonLab__variantDesc">${v.desc}</p> | |
| <div class="AiButtonLab__row"> | |
| <button class="AiBtn AiBtn--${v.id}"> | |
| ${shimmerSvg(paths.thunder, v.white, gradId).replace('width="18" height="18"', 'width="16" height="16"')} | |
| <span class="AiBtn__label">Suggest with AI</span> | |
| </button> | |
| <button class="AiIconBtn AiIconBtn--${v.id}" aria-label="Suggest"> | |
| ${shimmerSvg(paths.thunder, v.white, gradId)} | |
| </button> | |
| <button class="AiIconBtn AiIconBtn--${v.id}" aria-label="Suggest"> | |
| ${shimmerSvg(paths.bulb, v.white, gradId)} | |
| </button> | |
| </div> | |
| </div>`, | |
| ) | |
| .join('') + | |
| '</div>'; | |
| lab.innerHTML = html; | |
| } | |
| renderLab('lab-light', 'ai-shimmer-grad-light'); | |
| renderLab('lab-dark', 'ai-shimmer-grad-dark'); | |
| function shimmerSparkles(gradId) { | |
| return ` | |
| <svg viewBox="0 0 24 24" class="ShimmerSparkles" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"> | |
| <defs> | |
| <linearGradient id="${gradId}" gradientUnits="userSpaceOnUse" x1="-12" y1="0" x2="0" y2="0"> | |
| <stop offset="0%" stop-color="var(--action-blue)"/> | |
| <stop offset="50%" stop-color="var(--status-future-purple)"/> | |
| <stop offset="100%" stop-color="var(--action-blue)"/> | |
| <animate attributeName="x1" values="-24;24" dur="2.4s" repeatCount="indefinite"/> | |
| <animate attributeName="x2" values="0;48" dur="2.4s" repeatCount="indefinite"/> | |
| </linearGradient> | |
| </defs> | |
| <path fill="url(#${gradId})" d="M12 1.5 L14.5 9.5 L22.5 12 L14.5 14.5 L12 22.5 L9.5 14.5 L1.5 12 L9.5 9.5 Z M19.5 0 L20.5 3.5 L24 4.5 L20.5 5.5 L19.5 9 L18.5 5.5 L15 4.5 L18.5 3.5 Z"/> | |
| </svg> | |
| `; | |
| } | |
| function renderForm(targetId, gradId) { | |
| const el = document.getElementById(targetId); | |
| el.innerHTML = ` | |
| <div class="MsForm"> | |
| <h2>New milestone</h2> | |
| <p class="MsForm__hint">In-context preview of the shimmering AI suggest button inside the milestone form.</p> | |
| <div class="MsForm__row"> | |
| <svg class="MsForm__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16"/><path d="M4 12h16"/><path d="M4 18h10"/></svg> | |
| <div class="MsForm__field"> | |
| <label class="MsForm__label">Title</label> | |
| <input class="MsForm__input is-title" value="Ship onboarding revamp"/> | |
| </div> | |
| </div> | |
| <div class="MsForm__row"> | |
| <svg class="MsForm__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="4" width="18" height="16" rx="2"/><path d="M7 9h10"/><path d="M7 13h10"/><path d="M7 17h6"/></svg> | |
| <div class="MsForm__field"> | |
| <label class="MsForm__label">Definition of done</label> | |
| <textarea class="MsForm__textarea" placeholder="Describe what needs to be true…"></textarea> | |
| <div class="MsForm__aiRow"> | |
| <button class="AiGhostBtn" title="Suggest with AI"> | |
| ${shimmerSparkles(gradId)} | |
| </button> | |
| <button class="MsForm__helper" title="Polish text"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 20 L14 10"/><path d="M14 4l6 6-4 4-6-6z"/></svg> | |
| </button> | |
| <button class="MsForm__helper" title="Undo"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 14L4 9l5-5"/><path d="M4 9h10a6 6 0 0 1 0 12h-3"/></svg> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="MsForm__row"> | |
| <svg class="MsForm__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="4"/><path d="M4 20a7 7 0 0 1 14 0"/></svg> | |
| <div class="MsForm__field"> | |
| <label class="MsForm__label">Owner</label> | |
| <select class="MsForm__select"> | |
| <option>Alice Johnson</option> | |
| <option>Bob Smith</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="MsForm__row"> | |
| <svg class="MsForm__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4"/><path d="M16 3v4"/><path d="M3 10h18"/></svg> | |
| <div class="MsForm__field"> | |
| <label class="MsForm__label">Deadline</label> | |
| <input class="MsForm__input" value="2026-05-15"/> | |
| </div> | |
| </div> | |
| <div class="MsForm__footer"> | |
| <button class="MsForm__btn">Cancel</button> | |
| <button class="MsForm__btn MsForm__btn--primary">Create milestone</button> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| renderForm('form-light', 'form-sparkles-light'); | |
| renderForm('form-dark', 'form-sparkles-dark'); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment