<main class="page">
<section class="composer" aria-label="AI prompt composer">
<div class="composer-top">
<div class="picker" id="picker">
<button type="button" class="picker-btn" id="picker-btn" aria-haspopup="listbox" aria-expanded="true" aria-controls="model-list">
<span class="picker-dot" id="picker-dot" aria-hidden="true"></span>
<span class="picker-name" id="picker-name">Nova 4 Balanced</span>
<span class="picker-tag" id="picker-tag">200k</span>
<svg class="picker-chevron" viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"></path></svg>
</button>
<ul class="model-list" id="model-list" role="listbox" aria-label="Select AI model"></ul>
</div>
<span class="model-note" id="model-note">Everyday coding and writing</span>
</div>
<label class="sr-only" for="prompt">Prompt</label>
<textarea id="prompt" rows="3">Compare B-tree and LSM-tree indexes for a write-heavy event log.</textarea>
<div class="composer-foot">
<button type="button" class="think-switch" id="think-switch" role="switch" aria-checked="false">
<span class="switch-track" aria-hidden="true"></span>
<span class="switch-label">Extended thinking</span>
<span class="switch-note" id="think-note">+4k budget</span>
</button>
<div class="foot-right">
<span class="tokens" id="tokens">18 / 200,000 tokens</span>
<button type="button" class="send-btn" id="send">
<span>Send</span>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14M13 6l6 6-6 6"></path></svg>
</button>
</div>
</div>
<p class="reply" id="reply" hidden></p>
<p class="sr-only" id="status" role="status"></p>
</section>
</main>*, *::before, *::after {
box-sizing: border-box;
}
:root {
--page: #f1f5f9;
--card: #ffffff;
--text: #0f172a;
--muted: #64748b;
--soft: #f1f5f9;
--hover: #e2e8f0;
--accent: #2563eb;
--accent-soft: #eff6ff;
--accent-text: #1d4ed8;
--ring: rgba(15, 23, 42, 0.06);
--shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 18px 40px -14px rgba(15, 23, 42, 0.14);
--menu-shadow: 0 4px 12px rgba(15, 23, 42, 0.06), 0 22px 44px -12px rgba(15, 23, 42, 0.18);
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
margin: 0;
background: var(--page);
color: var(--text);
}
.page {
display: grid;
grid-template-columns: minmax(0, 580px);
justify-content: center;
align-content: start;
min-height: 100vh;
padding: max(20px, calc(50vh - 177px)) 16px 20px;
}
.composer {
position: relative;
padding: 16px;
border-radius: 22px;
background: var(--card);
box-shadow: 0 0 0 1px var(--ring), var(--shadow);
}
.composer-top {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding-bottom: 10px;
}
.picker {
position: static;
}
.picker-btn {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 36px;
padding: 6px 12px;
border: 0;
border-radius: 999px;
background: var(--soft);
color: var(--text);
font: inherit;
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
transition: background 0.15s ease;
}
.picker-btn:hover {
background: var(--hover);
}
.picker-btn[aria-expanded="true"] {
background: var(--accent-soft);
color: var(--accent-text);
}
.picker-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--accent);
}
.picker-tag {
padding: 2px 7px;
border-radius: 999px;
background: var(--card);
color: var(--muted);
font-family: ui-monospace, Consolas, monospace;
font-size: 0.6875rem;
font-weight: 700;
}
.picker-btn[aria-expanded="true"] .picker-tag {
color: var(--accent-text);
}
.picker-chevron {
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
transition: transform 0.2s ease;
}
.picker-btn[aria-expanded="true"] .picker-chevron {
transform: rotate(180deg);
}
.model-note {
overflow: hidden;
font-size: 0.8125rem;
color: var(--muted);
text-overflow: ellipsis;
white-space: nowrap;
}
.model-list {
position: absolute;
top: calc(100% + 2px);
right: 0;
left: 0;
z-index: 20;
display: grid;
gap: 2px;
margin: 0;
padding: 5px;
border-radius: 16px;
background: var(--card);
box-shadow: 0 0 0 1px var(--ring), var(--menu-shadow);
list-style: none;
}
.model-list[hidden] {
display: none;
}
.model-opt {
display: grid;
grid-template-columns: 32px minmax(0, 1fr) auto;
align-items: center;
gap: 10px;
padding: 5px 10px;
border-radius: 12px;
cursor: pointer;
}
.model-opt:hover {
background: var(--soft);
}
.model-opt[aria-selected="true"] {
background: var(--accent-soft);
}
.model-opt:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.opt-ico {
display: grid;
place-items: center;
width: 32px;
height: 32px;
border-radius: 9px;
color: #ffffff;
}
.opt-ico svg {
width: 17px;
height: 17px;
fill: none;
stroke: currentColor;
stroke-width: 1.9;
stroke-linecap: round;
stroke-linejoin: round;
}
.opt-head {
display: flex;
align-items: center;
gap: 7px;
}
.opt-name {
font-size: 0.875rem;
font-weight: 600;
}
.opt-badge {
padding: 2px 7px;
border-radius: 999px;
background: var(--soft);
color: var(--muted);
font-size: 0.6875rem;
font-weight: 600;
}
.model-opt[aria-selected="true"] .opt-badge {
background: var(--card);
color: var(--accent-text);
}
.opt-desc {
margin: 1px 0 0;
font-size: 0.75rem;
color: var(--muted);
}
.opt-meta {
font-family: ui-monospace, Consolas, monospace;
font-size: 0.75rem;
font-weight: 600;
color: var(--muted);
white-space: nowrap;
}
.model-opt[aria-selected="true"] .opt-meta {
color: var(--accent-text);
}
textarea {
display: block;
width: 100%;
min-height: 228px;
padding: 10px 4px;
border: 0;
outline: 0;
resize: none;
background: transparent;
color: var(--text);
font: inherit;
font-size: 0.9375rem;
line-height: 1.55;
}
.composer-foot {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
gap: 10px;
padding-top: 12px;
border-top: 1px solid var(--soft);
}
.think-switch {
display: inline-flex;
align-items: center;
gap: 8px;
min-height: 34px;
padding: 4px 11px 4px 7px;
border: 0;
border-radius: 999px;
background: var(--soft);
color: var(--text);
font: inherit;
font-size: 0.8125rem;
font-weight: 600;
cursor: pointer;
}
.think-switch:disabled {
opacity: 0.6;
cursor: default;
}
.switch-track {
position: relative;
width: 30px;
height: 18px;
border-radius: 999px;
background: #cbd5e1;
transition: background 0.15s ease;
}
.switch-track::after {
content: "";
position: absolute;
top: 2px;
left: 2px;
width: 14px;
height: 14px;
border-radius: 50%;
background: #ffffff;
box-shadow: 0 1px 2px rgba(15, 23, 42, 0.2);
transition: transform 0.15s ease;
}
.think-switch[aria-checked="true"] .switch-track {
background: var(--accent);
}
.think-switch[aria-checked="true"] .switch-track::after {
transform: translateX(12px);
}
.switch-note {
font-size: 0.75rem;
font-weight: 500;
color: var(--muted);
}
.foot-right {
display: flex;
align-items: center;
gap: 10px;
margin-left: auto;
}
.tokens {
font-family: ui-monospace, Consolas, monospace;
font-size: 0.75rem;
font-variant-numeric: tabular-nums;
color: var(--muted);
}
.send-btn {
display: inline-flex;
align-items: center;
gap: 6px;
min-height: 34px;
padding: 6px 14px;
border: 0;
border-radius: 999px;
background: var(--text);
color: var(--card);
font: inherit;
font-size: 0.8125rem;
font-weight: 600;
cursor: pointer;
transition: transform 0.15s ease, opacity 0.15s ease;
}
.send-btn:hover {
transform: translateY(-1px);
}
.send-btn svg {
width: 15px;
height: 15px;
fill: none;
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
}
.picker-btn:focus-visible,
.think-switch:focus-visible,
.send-btn:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
.reply {
margin: 10px 0 0;
padding: 9px 12px;
border-radius: 12px;
background: var(--accent-soft);
color: var(--accent-text);
font-size: 0.8125rem;
font-weight: 500;
line-height: 1.45;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
overflow: hidden;
clip-path: inset(50%);
white-space: nowrap;
}
@media (max-width: 520px) {
.page {
padding-top: 20px;
}
.model-note {
display: none;
}
}
@media (pointer: coarse) {
.picker-btn,
.think-switch,
.send-btn,
.model-opt,
textarea {
min-height: 44px;
}
}
@media (prefers-color-scheme: dark) {
:root {
--page: #0b1120;
--card: #151e30;
--text: #f1f5f9;
--muted: #94a3b8;
--soft: #1e293b;
--hover: #293548;
--accent: #3b82f6;
--accent-soft: #172554;
--accent-text: #93c5fd;
--ring: rgba(255, 255, 255, 0.08);
--shadow: 0 18px 40px -14px rgba(0, 0, 0, 0.6);
--menu-shadow: 0 24px 48px -12px rgba(0, 0, 0, 0.75);
}
.switch-track {
background: #334155;
}
}
@media (forced-colors: active) {
.composer,
.model-list {
border: 1px solid CanvasText;
}
.model-opt[aria-selected="true"] {
outline: 2px solid Highlight;
}
.switch-track {
border: 1px solid ButtonText;
}
}
@media (prefers-reduced-motion: reduce) {
.picker-btn,
.picker-chevron,
.switch-track,
.switch-track::after,
.send-btn {
transition: none;
}
}const MODELS = [
{ id: "balanced", name: "Nova 4 Balanced", badge: "Default", color: "#2563eb", context: 200000, tag: "200k", cost: "$$", desc: "Everyday coding and writing", thinking: "optional", icon: "M12 2L2 7l10 5 10-5-10-5ZM2 17l10 5 10-5M2 12l10 5 10-5" },
{ id: "pro", name: "Nova 4 Pro", badge: "Deep work", color: "#7c3aed", context: 200000, tag: "200k", cost: "$$$", desc: "Hard refactors and long documents", thinking: "optional", icon: "M6 3h12l4 6-10 12L2 9l4-6ZM2 9h20" },
{ id: "flash", name: "Nova 4 Flash", badge: "Fastest", color: "#059669", context: 128000, tag: "128k", cost: "$", desc: "Quick answers and low latency", thinking: "off", icon: "M13 2L3 14h9l-1 8 10-12h-9l1-8Z" },
{ id: "reasoner", name: "Nova R1 Reasoner", badge: "Reasoning", color: "#ea580c", context: 128000, tag: "128k", cost: "$$$", desc: "Step-by-step math and architecture", thinking: "locked", icon: "M9 3h6v6H9V3ZM4 15h6v6H4v-6ZM14 15h6v6h-6v-6ZM12 9v3m0 0H7v3m5-3h5v3" }
];
const picker = document.getElementById("picker");
const pickerBtn = document.getElementById("picker-btn");
const pickerDot = document.getElementById("picker-dot");
const pickerName = document.getElementById("picker-name");
const pickerTag = document.getElementById("picker-tag");
const list = document.getElementById("model-list");
const modelNote = document.getElementById("model-note");
const prompt = document.getElementById("prompt");
const thinkSwitch = document.getElementById("think-switch");
const thinkNote = document.getElementById("think-note");
const tokensEl = document.getElementById("tokens");
const sendBtn = document.getElementById("send");
const reply = document.getElementById("reply");
const status = document.getElementById("status");
let selectedIndex = 0;
let userThinking = false;
function el(tag, className, text) {
const node = document.createElement(tag);
if (className) node.className = className;
if (text) node.textContent = text;
return node;
}
function makeIcon(pathData) {
const ns = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(ns, "svg");
const path = document.createElementNS(ns, "path");
svg.setAttribute("viewBox", "0 0 24 24");
svg.setAttribute("aria-hidden", "true");
path.setAttribute("d", pathData);
svg.append(path);
return svg;
}
function isThinkingOn(model) {
if (model.thinking === "locked") return true;
if (model.thinking === "off") return false;
return userThinking;
}
// Estimate ~4 chars per token plus the 4k reasoning budget
function updateTokens() {
const model = MODELS[selectedIndex];
const chars = prompt.value.trim().length;
const promptTokens = chars ? Math.max(1, Math.ceil(chars / 4)) : 0;
const budget = isThinkingOn(model) ? 4000 : 0;
const total = promptTokens + budget;
tokensEl.textContent = total.toLocaleString("en-US") + " / " + model.context.toLocaleString("en-US") + " tokens";
}
function applyModel(index, announce) {
selectedIndex = index;
const model = MODELS[index];
pickerDot.style.background = model.color;
pickerName.textContent = model.name;
pickerTag.textContent = model.tag;
modelNote.textContent = model.desc;
const on = isThinkingOn(model);
thinkSwitch.setAttribute("aria-checked", String(on));
thinkSwitch.disabled = model.thinking !== "optional";
if (model.thinking === "locked") {
thinkNote.textContent = "Always on";
} else if (model.thinking === "off") {
thinkNote.textContent = "Not used";
} else {
thinkNote.textContent = on ? "+4k active" : "+4k budget";
}
const options = list.querySelectorAll(".model-opt");
options.forEach(function(node, i) {
node.setAttribute("aria-selected", String(i === index));
});
updateTokens();
if (announce) status.textContent = "Selected " + model.name + ", " + model.tag + " context";
}
function openMenu(focusSelected) {
list.hidden = false;
pickerBtn.setAttribute("aria-expanded", "true");
if (focusSelected) {
const active = list.children[selectedIndex];
if (active) active.focus();
}
}
function closeMenu(returnFocus) {
if (list.hidden) return;
list.hidden = true;
pickerBtn.setAttribute("aria-expanded", "false");
if (returnFocus) pickerBtn.focus();
}
MODELS.forEach(function(model, i) {
const li = el("li", "model-opt");
const ico = el("span", "opt-ico");
const left = el("div", "");
const head = el("div", "opt-head");
const name = el("span", "opt-name", model.name);
const badge = el("span", "opt-badge", model.badge);
const desc = el("p", "opt-desc", model.desc);
const meta = el("div", "opt-meta", model.tag + " \u00b7 " + model.cost);
ico.style.background = model.color;
ico.append(makeIcon(model.icon));
li.setAttribute("role", "option");
li.tabIndex = -1;
head.append(name, badge);
left.append(head, desc);
li.append(ico, left, meta);
li.addEventListener("click", function() {
applyModel(i, true);
closeMenu(true);
});
list.append(li);
});
pickerBtn.addEventListener("click", function() {
if (list.hidden) openMenu(true);
else closeMenu(true);
});
pickerBtn.addEventListener("keydown", function(e) {
if (e.key === "ArrowDown" || e.key === "ArrowUp") {
e.preventDefault();
openMenu(true);
}
});
list.addEventListener("keydown", function(e) {
const options = Array.from(list.children);
const current = options.indexOf(document.activeElement);
if (e.key === "ArrowDown") {
e.preventDefault();
options[(current + 1) % options.length].focus();
} else if (e.key === "ArrowUp") {
e.preventDefault();
options[(current - 1 + options.length) % options.length].focus();
} else if (e.key === "Home") {
e.preventDefault();
options[0].focus();
} else if (e.key === "End") {
e.preventDefault();
options[options.length - 1].focus();
} else if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
if (current >= 0) {
applyModel(current, true);
closeMenu(true);
}
} else if (e.key === "Escape") {
e.preventDefault();
closeMenu(true);
} else if (e.key === "Tab") {
closeMenu(false);
}
});
thinkSwitch.addEventListener("click", function() {
const model = MODELS[selectedIndex];
if (model.thinking !== "optional") return;
userThinking = !userThinking;
applyModel(selectedIndex, false);
status.textContent = "Extended thinking " + (userThinking ? "on" : "off");
});
prompt.addEventListener("input", updateTokens);
sendBtn.addEventListener("click", function() {
const model = MODELS[selectedIndex];
const thinking = isThinkingOn(model) ? "with extended thinking" : "with standard response";
closeMenu(false);
reply.hidden = false;
reply.textContent = "Sent to " + model.name + " (" + model.tag + " context) " + thinking + ".";
status.textContent = reply.textContent;
});
document.addEventListener("pointerdown", function(e) {
if (!picker.contains(e.target)) closeMenu(false);
});
applyModel(0, false);
// Open the menu for the demo, remove this line to start closed
openMenu(false);Click any element to find its code Esc
Check this code before you run it
It came from a shared link. It runs with fewer permissions, so it cannot open pop-ups, submit forms or start downloads.
element.animate() call shows up here as it plays.