Business and Service Flows

Flower Shop Subscription Plan Selection

Complete subscription plan selection in a flower shop scenario: includes real content, actionable controls, clear status feedback, and responsive layouts across sizes.

Business and Service FlowsSubscription Plan SelectionHTMLCSSJavaScript
With JavaScript enabled, you can edit, run, and save this example. The fixed source is as follows:
<!doctype html>
<html lang="en" dir="ltr">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Flower Shop Subscription Plan Selection</title>
  <style>
    :root { --ink:#17241d; --paper:#f3f0e7; --accent:#af4f45; --secondary:#9eb49f; --line:color-mix(in srgb, var(--ink) 18%, transparent); --shadow:0 24px 60px color-mix(in srgb, var(--ink) 16%, transparent); color-scheme:light; }
    * { box-sizing:border-box; }
    html { min-width:320px; background:var(--paper); }
    body { min-height:100vh; margin:0; overflow-x:hidden; color:var(--ink); font-family:"Hiragino Maru Gothic ProN","PingFang SC",sans-serif; background:radial-gradient(circle at 15% 10%,color-mix(in srgb,var(--secondary) 35%,transparent) 0 9%,transparent 10%),radial-gradient(circle at 90% 75%,color-mix(in srgb,var(--accent) 18%,transparent) 0 12%,transparent 13%),var(--paper); }
    button,input,select,textarea { color:inherit; font:inherit; }
    button,[role="button"],input,select,textarea { accent-color:var(--accent); }
    button { cursor:pointer; }
    button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid var(--accent); outline-offset:3px; }
    [hidden] { display:none !important; }
    @media (max-width:700px) { .mast h1 { line-height:1.08 !important; letter-spacing:-.035em !important; overflow-wrap:anywhere; } }
    @media (prefers-reduced-motion:reduce) { *,*::before,*::after { scroll-behavior:auto !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; transition-duration:.01ms !important; } }
    .page{width:min(1140px,calc(100% - 28px));margin:auto;padding:54px 0}.mast{display:flex;justify-content:space-between;align-items:center;gap:24px;margin:0 12px 28px}.mast h1{font-family:"Hiragino Maru Gothic ProN","PingFang SC",sans-serif;font-weight:900;font-size:clamp(38px,8vw,82px);letter-spacing:-.035em;margin:0;line-height:.98}.eyebrow{display:inline-flex;padding:7px 12px;border-radius:999px;color:var(--paper);background:var(--accent);font-weight:900}.intro{max-width:620px;line-height:1.65}.scenario{padding:12px 18px;border-radius:999px;background:var(--secondary);box-shadow:0 7px 0 color-mix(in srgb,var(--ink) 18%,transparent);font-weight:900}.demo{border-radius:46px 18px 46px 18px;box-shadow:0 18px 0 color-mix(in srgb,var(--secondary) 45%,transparent);position:relative;min-height:390px;overflow:hidden;padding:clamp(22px,5vw,54px);background:color-mix(in srgb,var(--paper) 90%,#fff)}@media(max-width:700px){.mast{display:grid}.page{width:calc(100% - 16px);padding:18px 0}.demo{padding:17px}}
    .panel{padding:30px;border:0;border-radius:42px 12px;background:color-mix(in srgb,var(--secondary) 18%,var(--paper))}.row{display:flex;flex-wrap:wrap;gap:14px;align-items:center}.stack{display:flex;flex-direction:column;gap:20px}.action{min-height:48px;padding:12px 22px;border:0;border-radius:50% 50% 18px 18px;background:color-mix(in srgb,var(--secondary) 42%,transparent);font-weight:800}.action.primary,.action.is-active{color:var(--paper);background:var(--accent)}.muted{color:color-mix(in srgb,var(--ink) 64%,transparent);line-height:1.7}.status{min-height:25px;margin-top:16px;color:var(--accent)}.metric{font-size:clamp(32px,7vw,66px);font-weight:800}.meter{height:11px;border-radius:50%;background:color-mix(in srgb,var(--ink) 10%,transparent)}.meter>i{display:block;height:100%;border-radius:inherit;background:var(--accent)}.chip{padding:8px 12px;border-radius:50%;background:var(--paper)}
    .composition-gallery{margin:0;padding:clamp(8px,2vw,18px);border:1px solid var(--ink);background:color-mix(in srgb,var(--paper) 78%,transparent)}.gallery-caption{display:grid;grid-template-columns:auto 1fr auto;gap:16px;align-items:center;padding:15px 4px 2px;font-size:12px}.gallery-caption::before,.gallery-caption::after{content:"";height:1px;background:var(--line)}.gallery-caption strong{font:800 11px/1.2 ui-monospace,monospace;letter-spacing:.16em;text-transform:uppercase}.composition-gallery .demo{box-shadow:none}.composition-gallery .demo::before{content:"";position:absolute;inset:10px;border:1px dashed color-mix(in srgb,var(--accent) 36%,transparent);pointer-events:none}
    .subscription-studio{display:grid;gap:18px}.subscription-studio>header{display:flex;justify-content:space-between;gap:24px;align-items:end;padding-bottom:16px;border-bottom:1px solid var(--line)}.subscription-studio h2{margin:.25em 0;font-size:clamp(32px,6vw,64px)}.subscription-studio header p{max-width:58ch}.subscription-cycle{display:grid;grid-template-columns:auto 52px auto;gap:9px;align-items:center;font-weight:900}.subscription-cycle input{position:absolute;opacity:0}.subscription-cycle i{display:block;width:52px;height:28px;padding:4px;border-radius:999px;background:var(--line)}.subscription-cycle i::after{content:"";display:block;width:20px;height:20px;border-radius:50%;background:var(--paper);box-shadow:0 2px 6px #0004;transition:transform .18s}.subscription-cycle input:checked+i{background:var(--accent)}.subscription-cycle input:checked+i::after{transform:translateX(24px)}.subscription-cycle input:focus-visible+i{outline:3px solid var(--accent);outline-offset:3px}.subscription-plans{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}.subscription-plans>label>input{position:absolute;opacity:0}.subscription-plans>label>span{display:grid;gap:13px;min-height:300px;padding:20px;border:1px solid var(--line);border-radius:18px;background:var(--paper)}.subscription-plans>label>input:checked+span{border-color:var(--accent);box-shadow:inset 0 0 0 3px var(--accent)}.subscription-plans>label>input:focus-visible+span{outline:3px solid var(--accent);outline-offset:3px}.subscription-plans span>i{font:900 12px/1 ui-monospace,monospace;font-style:normal}.subscription-plans span>b{font-size:24px}.subscription-plans span>small{min-height:34px}.subscription-plans span>strong{display:flex;align-items:baseline;margin-top:auto;font-size:44px}.subscription-plans strong em{font-size:16px;font-style:normal}.subscription-plans strong small{font-size:12px}.subscription-plans span>u{text-decoration:none;color:var(--accent);font-weight:900}.subscription-receipt{display:grid;grid-template-columns:repeat(3,1fr) auto;gap:12px;align-items:center;padding:17px;border-left:7px solid var(--accent);background:var(--ink);color:var(--paper)}.subscription-receipt>div{display:grid;gap:5px}.subscription-receipt>div span{font-size:11px}.subscription-receipt output{grid-column:1/-1;color:var(--secondary)}@media(max-width:720px){.subscription-studio>header{align-items:start;flex-direction:column}.subscription-plans{grid-template-columns:1fr}.subscription-plans>label>span{min-height:220px}.subscription-receipt{grid-template-columns:1fr 1fr}.subscription-receipt .action{grid-column:1/-1}}.workflow-dispatch{display:grid;grid-template-columns:minmax(210px,.48fr) minmax(0,1.52fr);gap:18px}.dispatch-console{display:grid;align-content:start;gap:16px;padding:22px;border:1px solid var(--line);border-radius:18px;background:color-mix(in srgb,var(--secondary) 12%,var(--paper))}.dispatch-console h2{margin:.2em 0}.dispatch-console form,.dispatch-console label{display:grid;gap:7px}.dispatch-console input,.dispatch-console select{min-width:0;width:100%;padding:10px;border:1px solid var(--line);border-radius:8px;background:var(--paper)}.dispatch-console fieldset{display:flex;gap:12px;border:1px solid var(--line);border-radius:10px}.dispatch-console fieldset label{display:flex;align-items:center}.dispatch-workbench{--dispatch-load:.22;min-width:0;padding:14px;border-left:8px solid color-mix(in srgb,var(--accent) calc(var(--dispatch-load)*100%),var(--line));background:linear-gradient(90deg,color-mix(in srgb,var(--accent) 8%,transparent),transparent 28%)}.dispatch-workbench[data-dispatch-priority="urgent"]{box-shadow:inset 0 0 0 2px var(--accent)}@media(max-width:900px){.workflow-dispatch{grid-template-columns:1fr}.dispatch-console{order:2}}
  </style>
</head>
<body data-aesthetic="playful" data-composition="gallery-frame">
  <main class="page">
    <header class="mast"><div><span class="eyebrow">playful / Subscription plan selection / INTERMEDIATE</span><h1>Flower Shop Subscription Plan Selection</h1><p class="intro">Complete subscription plan selection in a flower shop scenario: includes real content, actionable controls, clear status feedback, and responsive layouts across sizes.</p></div><span class="scenario">Flower shop</span></header>
    <figure class="composition-gallery"><section class="demo" aria-label="Flower Shop Subscription Plan Selection Interaction Area"><div class="workflow-dispatch"><aside class="dispatch-console"><span class="eyebrow">Flower Shop DISPATCH</span><h2>Bouquet order dispatch console</h2><form id="workflowDispatchForm"><label>Task Type<select id="workflowDispatchKind"><option>Daily Bouquet</option><option>Seasonal bouquet</option><option>Custom Bouquet</option></select></label><label>Floral quantity<input id="workflowDispatchAmount" type="number" min="1" max="9999" value="33"><span>Branch</span></label><fieldset><legend>Processing priority</legend><label><input type="radio" name="workflowPriority" value="normal" checked>Regular</label><label><input type="radio" name="workflowPriority" value="urgent">Urgent</label></fieldset><button class="action primary" type="submit">Accept orders</button></form><label>Current task<select id="workflowDispatchActive" aria-label="Switch current task"><option value="1">Daily Bouquet</option><option value="2">Seasonal bouquet</option></select></label><output id="workflowDispatchSummary">Waiting for Dispatch</output></aside><section id="workflowCore" class="workflow-core dispatch-workbench" data-dispatch-priority="normal"><!-- 11DZ_CORE_START:commerce-service-flows-subscription-plans --><section class="subscription-studio"><header><div><span class="eyebrow">SUBSCRIPTION STUDIO</span><h2>Flower Shop Subscription Setup</h2><p>First switch the billing cycle, then choose the service allowance that matches the actual frequency.</p></div><label class="subscription-cycle"><span>Monthly</span><input id="subscriptionCycle" type="checkbox" role="switch" aria-label="Switch to annual billing" data-core-bridge="commerce-service-flows-subscription-plans"><i aria-hidden="true"></i><span>Per year</span></label></header><div class="subscription-plans"><label><input type="radio" name="subscriptionPlan" value="0"><span><i>01</i><b>Pay-as-you-go plan</b><small>Suitable for occasional use</small><strong><em>¥</em><output data-subscription-price="39">39</output><small>/ mo</small></strong><u>2 service credits</u></span></label><label><input type="radio" name="subscriptionPlan" value="1" checked><span><i>02</i><b>Common plans</b><small>Includes priority scheduling</small><strong><em>¥</em><output data-subscription-price="78">78</output><small>/ mo</small></strong><u>6 service quota</u></span></label><label><input type="radio" name="subscriptionPlan" value="2"><span><i>03</i><b>Team plan</b><small>Supports shared use</small><strong><em>¥</em><output data-subscription-price="136">136</output><small>/ mo</small></strong><u>12 service credits</u></span></label></div><aside class="subscription-receipt"><div><span>Current Plan</span><strong id="subscriptionSelected">Common plans</strong></div><div><span>Billing cycle</span><strong id="subscriptionPeriod">Monthly</strong></div><div><span>Cycle total</span><strong id="subscriptionTotal">¥78</strong></div><button id="subscriptionConfirm" class="action primary" type="button">Confirm Local Subscription</button><output id="subscriptionResult">Not confirmed, payment will not be initiated</output></aside></section><!-- 11DZ_CORE_END --></section></div><p id="status" class="status" role="status" aria-live="polite"></p></section><figcaption class="gallery-caption"><strong>Flower Shop / GALLERY 03</strong></figcaption></figure>
  </main>
  <script>
    'use strict';
    const statusOutput = document.querySelector('#status');
    const announce = message => { statusOutput.textContent = message; };
    /* 11DZ_CORE_SCRIPT_START:commerce-service-flows-subscription-plans */
const subscriptionPlans=[{"name":"Pay-as-you-go plan","monthly":39,"note":"Suitable for occasional use"},{"name":"Common plans","monthly":78,"note":"Includes priority scheduling"},{"name":"Team plan","monthly":136,"note":"Supports shared use"}];const subscriptionCycle=document.querySelector('#subscriptionCycle');const subscriptionChoices=[...document.querySelectorAll('[name="subscriptionPlan"]')];const subscriptionState={annual:false,selected:1,confirmed:false};function renderSubscription(){subscriptionState.annual=subscriptionCycle.checked;subscriptionState.selected=subscriptionChoices.findIndex(choice=>choice.checked);const plan=subscriptionPlans[subscriptionState.selected];document.querySelectorAll('[data-subscription-price]').forEach((output,index)=>{output.textContent=subscriptionState.annual?Math.round(subscriptionPlans[index].monthly*10):subscriptionPlans[index].monthly;output.nextElementSibling.textContent=subscriptionState.annual?'/ year':'/ mo';});document.querySelector('#subscriptionSelected').textContent=plan.name;document.querySelector('#subscriptionPeriod').textContent=subscriptionState.annual?'Annual · Save two months':'Monthly';document.querySelector('#subscriptionTotal').textContent='¥'+(subscriptionState.annual?Math.round(plan.monthly*10):plan.monthly);subscriptionCycle.setAttribute('aria-label',subscriptionState.annual?'Switch to monthly billing':'Switch to annual billing');document.querySelector('#subscriptionResult').textContent=subscriptionState.confirmed?'The configuration has changed. Please confirm again.':'Not confirmed, payment will not be initiated';subscriptionState.confirmed=false;announce('Selected '+plan.name+','+(subscriptionState.annual?'Per year':'Monthly')+'Billing');}subscriptionCycle.addEventListener('change',renderSubscription);subscriptionChoices.forEach(choice=>choice.addEventListener('change',renderSubscription));document.querySelector('#subscriptionConfirm').addEventListener('click',()=>{subscriptionState.confirmed=true;document.querySelector('#subscriptionResult').textContent='Confirmed on current page '+subscriptionPlans[subscriptionState.selected].name;announce(document.querySelector('#subscriptionResult').textContent);});renderSubscription();
/* 11DZ_CORE_SCRIPT_END */
const workflowBridgeSpec={"name":"commerce-service-flows-subscription-plans","selector":"[data-core-bridge=\"commerce-service-flows-subscription-plans\"]","mode":"toggle","key":" "};const workflowBridgeCore=document.querySelector('#workflowCore');const workflowBridgeControl=workflowBridgeCore.querySelector(workflowBridgeSpec.selector);if(!workflowBridgeControl)throw new Error('Missing core bridge: '+workflowBridgeSpec.name);const workflowBridgeControlledId=workflowBridgeControl.getAttribute('aria-controls');const workflowBridgeControlled=workflowBridgeControlledId?document.getElementById(workflowBridgeControlledId):null;workflowBridgeCore.dataset.workflowBridge=workflowBridgeSpec.name;workflowBridgeCore.dataset.workflowVersion='0';function workflowBridgeSerialize(){const visualNode=workflowBridgeCore.firstElementChild||workflowBridgeCore;const visual=getComputedStyle(visualNode);const outputs=[...workflowBridgeCore.querySelectorAll('output,[role="status"],[aria-live],meter,progress')].map(node=>node.textContent.trim()+'|'+node.getAttribute('aria-valuenow')+'|'+node.getAttribute('value'));const canvas=[...workflowBridgeCore.querySelectorAll('canvas')].map(node=>{try{return node.toDataURL().slice(-160);}catch{return 'canvas-unavailable';}});return JSON.stringify({html:workflowBridgeCore.innerHTML,status:statusOutput.textContent,outputs,canvas,visual:[visual.display,visual.visibility,visual.opacity,visual.transform,visual.filter,visual.backgroundColor,visual.width,visual.height],scroll:workflowBridgeSpec.mode==='scroll'?workflowBridgeControl.scrollTop:null});}let workflowBridgeLastEffect=workflowBridgeSerialize();function workflowBridgeSummary(){const label=(workflowBridgeControl.getAttribute('aria-label')||workflowBridgeControl.textContent||workflowBridgeControl.value||workflowBridgeSpec.name).trim().replace(/\s+/g,' ').slice(0,72);return label+' · Core Version '+workflowBridgeCore.dataset.workflowVersion;}function workflowBridgeCommit(){const effect=workflowBridgeSerialize();if(effect===workflowBridgeLastEffect)return {changed:false,summary:workflowBridgeSummary()};workflowBridgeLastEffect=effect;workflowBridgeCore.dataset.workflowVersion=String(Number(workflowBridgeCore.dataset.workflowVersion||0)+1);return {changed:true,summary:workflowBridgeSummary()};}function workflowBridgeScheduleCommit(){queueMicrotask(workflowBridgeCommit);setTimeout(workflowBridgeCommit,0);}workflowBridgeControl.setAttribute('aria-keyshortcuts',workflowBridgeSpec.key===' '?'Space':workflowBridgeSpec.key);const workflowBridgeToggleKeyMatches=event=>event.key===workflowBridgeSpec.key||event.key==='Spacebar'||event.code==='Space';workflowBridgeControl.addEventListener('keydown',event=>{if(!workflowBridgeToggleKeyMatches(event))return;event.preventDefault();});workflowBridgeControl.addEventListener('keyup',event=>{if(!workflowBridgeToggleKeyMatches(event))return;event.preventDefault();workflowBridgeControl.click();});workflowBridgeControl.addEventListener("change",workflowBridgeScheduleCommit);const workflowBridgeStateTargets=new Set(workflowBridgeCore.querySelectorAll('dialog'));if(workflowBridgeControlled&&workflowBridgeCore.contains(workflowBridgeControlled))workflowBridgeStateTargets.add(workflowBridgeControlled);workflowBridgeStateTargets.forEach(target=>['close','cancel','toggle'].forEach(eventName=>target.addEventListener(eventName,workflowBridgeScheduleCommit)));function workflowBridgeActivate(){workflowBridgeControl.focus();workflowBridgeControl.click();const result=workflowBridgeCommit();setTimeout(workflowBridgeCommit,0);return result;}function workflowBridgeReset(){workflowBridgeCore.dataset.workflowVersion='0';workflowBridgeLastEffect=workflowBridgeSerialize();}
const workflowDispatchCore=document.querySelector('#workflowCore');const workflowDispatchForm=document.querySelector('#workflowDispatchForm');const workflowDispatchSelect=document.querySelector('#workflowDispatchActive');const workflowDispatchJobs=new Map([["1",{"label":"Daily Bouquet","amount":12,"priority":"normal","touches":0}],["2",{"label":"Seasonal bouquet","amount":21,"priority":"urgent","touches":0}]]);let workflowDispatchSerial=workflowDispatchJobs.size;function workflowDispatchDrive(job,activate=false){workflowDispatchCore.dataset.dispatchPriority=job.priority;workflowDispatchCore.style.setProperty('--dispatch-load',Math.min(.95,.16+job.amount/120));const bridge=activate?workflowBridgeActivate():{changed:false,summary:workflowBridgeSummary()};document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' Branch · '+bridge.summary;announce('Current flower order task:'+job.label);}function workflowDispatchRender(activeId,activate=false){workflowDispatchSelect.replaceChildren(...[...workflowDispatchJobs].map(([id,job])=>{const option=document.createElement('option');option.value=id;option.textContent=job.label+(job.priority==='urgent'?' · Urgent':'');return option;}));workflowDispatchSelect.value=activeId;workflowDispatchDrive(workflowDispatchJobs.get(activeId),activate);}workflowDispatchForm.addEventListener('submit',event=>{event.preventDefault();const data=new FormData(workflowDispatchForm);const id=String(++workflowDispatchSerial);workflowDispatchJobs.set(id,{label:document.querySelector('#workflowDispatchKind').value,amount:Math.max(1,Number(document.querySelector('#workflowDispatchAmount').value)||1),priority:data.get('workflowPriority'),touches:0});workflowDispatchRender(id,true);});workflowDispatchSelect.addEventListener('change',()=>workflowDispatchDrive(workflowDispatchJobs.get(workflowDispatchSelect.value),true));workflowDispatchCore.addEventListener('focusin',()=>{const job=workflowDispatchJobs.get(workflowDispatchSelect.value);if(!job)return;job.touches+=1;document.querySelector('#workflowDispatchSummary').textContent=job.label+' · '+job.amount+' Branch · '+workflowBridgeSummary();});workflowDispatchRender('1',false);
workflowBridgeReset();
  </script>
</body>
</html>
Page feedbackFound an issue or have suggestions for improvement?
Feedback features need to be used in the online version

Please enable JavaScript in the online version before submitting; local features of the current tool or example are not affected.

Go to the online version for feedback