next: ai part 2

This commit is contained in:
nym21
2026-07-22 16:50:27 +02:00
parent 227a31f64e
commit 52e4db5ea6
18 changed files with 1318 additions and 1281 deletions
+86
View File
@@ -0,0 +1,86 @@
/**
* @typedef {Object} AskComposerOptions
* @property {(question: string) => void} onSubmit
* @property {() => void} onStop
*/
/** @param {AskComposerOptions} options */
export function createAskComposer(options) {
const form = document.createElement("form");
const fieldset = document.createElement("fieldset");
const label = document.createElement("label");
const labelText = document.createElement("span");
const input = document.createElement("textarea");
const actions = document.createElement("div");
const send = document.createElement("button");
const sendIcon = document.createElement("span");
const stop = document.createElement("button");
form.dataset.askComposer = "";
form.hidden = true;
fieldset.disabled = true;
labelText.append("Message assistant");
input.name = "question";
input.rows = 1;
input.maxLength = 4_000;
input.placeholder = "Ask anything";
input.required = true;
send.type = "submit";
send.ariaLabel = "Send message";
send.title = "Send message";
sendIcon.ariaHidden = "true";
sendIcon.append("↑");
send.append(sendIcon);
stop.type = "button";
stop.ariaLabel = "Stop generating";
stop.title = "Stop generating";
stop.hidden = true;
stop.addEventListener("click", options.onStop);
input.addEventListener("keydown", (event) => {
if (event.key !== "Enter" || event.shiftKey) return;
event.preventDefault();
form.requestSubmit();
});
form.addEventListener("submit", (event) => {
event.preventDefault();
const question = input.value.trim();
if (question) options.onSubmit(question);
});
label.append(labelText, input);
actions.append(send, stop);
fieldset.append(label, actions);
form.append(fieldset);
return {
element: form,
get value() {
return input.value;
},
set value(value) {
input.value = value;
},
focus() {
input.focus();
},
hide() {
form.hidden = true;
fieldset.disabled = true;
},
ready() {
form.hidden = false;
fieldset.disabled = false;
input.disabled = false;
send.hidden = false;
stop.hidden = true;
},
generating() {
form.hidden = false;
fieldset.disabled = false;
input.disabled = true;
send.hidden = true;
stop.hidden = false;
},
};
}
+76
View File
@@ -0,0 +1,76 @@
main[data-page="ask"] [data-ask-composer] {
position: relative;
display: block;
border: 1px solid var(--field-border-color);
border-radius: var(--control-radius);
padding: 0.25rem;
background: var(--ask-panel);
transition: border-color 120ms ease;
&:focus-within {
border-color: var(--orange);
}
> fieldset {
display: block;
margin: 0;
padding: 0;
border: 0;
> label {
display: block;
margin: 0;
padding: 0;
border: 0;
> span {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
> textarea {
display: block;
field-sizing: content;
width: 100%;
min-height: var(--ask-control-size);
max-height: 12rem;
border: 0;
padding: 0.5625rem
calc(var(--ask-icon-size) + 0.75rem) 0.5625rem 0.75rem;
background: transparent;
font-size: var(--font-size-sm);
line-height: var(--line-height-sm);
resize: none;
&:focus-visible {
outline: 0;
}
}
}
> div {
position: absolute;
top: 50%;
right: 0.25rem;
display: grid;
place-items: center;
width: var(--ask-icon-size);
height: var(--ask-icon-size);
translate: 0 -50%;
> button:last-child::before {
width: 0.55rem;
height: 0.55rem;
border-radius: 0.08rem;
background: currentColor;
content: "";
}
}
}
}