in src/p5js_playground/playground.tsx [347:538]
render() {
return html`<div class="playground">
<div class="sidebar">
<div class="selector">
<button
id="geminiTab"
class=${classMap({
'selected-tab': this.selectedChatTab === ChatTab.GEMINI,
})}
@click=${() => {
this.selectedChatTab = ChatTab.GEMINI;
}}>
Gemini
</button>
<button
id="codeTab"
class=${classMap({
'selected-tab': this.selectedChatTab === ChatTab.CODE,
})}
@click=${() => {
this.selectedChatTab = ChatTab.CODE;
}}>
Code ${this.codeHasChanged ? ICON_EDIT : html``}
</button>
</div>
<div
id="chat"
class=${classMap({
'tabcontent': true,
'showtab': this.selectedChatTab === ChatTab.GEMINI,
})}>
<div class="chat-messages">
${this.messages}
<div id="anchor"></div>
</div>
<div class="footer">
<div
id="chatStatus"
class=${classMap({'hidden': this.chatState === ChatState.IDLE})}>
${this.chatState === ChatState.GENERATING
? html`${ICON_BUSY} Generating...`
: html``}
${this.chatState === ChatState.THINKING
? html`${ICON_BUSY} Thinking...`
: html``}
${this.chatState === ChatState.CODING
? html`${ICON_BUSY} Coding...`
: html``}
</div>
<div id="inputArea">
<input
type="text"
id="messageInput"
.value=${this.inputMessage}
@input=${(e: InputEvent) => {
this.inputMessage = (e.target as HTMLInputElement).value;
}}
@keydown=${(e: KeyboardEvent) => {
this.inputKeyDownAction(e);
}}
placeholder="Type your message..."
autocomplete="off" />
<button
id="sendButton"
class=${classMap({
'disabled': this.chatState !== ChatState.IDLE,
})}
@click=${() => {
this.sendMessageAction();
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="currentColor">
<path d="M120-160v-240l320-80-320-80v-240l760 320-760 320Z" />
</svg>
</button>
</div>
</div>
</div>
<div
id="editor"
class=${classMap({
'tabcontent': true,
'showtab': this.selectedChatTab === ChatTab.CODE,
})}>
<div class="code-container">
${this.codeSyntax}
<textarea
class="code-editor"
contenteditable=""
.value=${this.code}
.readonly=${this.chatState !== ChatState.IDLE}
@keyup=${(e: KeyboardEvent) => {
const val = (e.target as HTMLTextAreaElement).value;
if (this.code !== val) {
this.codeEditedAction(val);
this.requestUpdate();
}
}}
@change=${(e: InputEvent) => {
this.codeEditedAction((e.target as HTMLTextAreaElement).value);
}}></textarea>
</div>
</div>
</div>
<div class="main-container">
${this.previewFrame}
<div class="toolbar">
<button
id="reloadCode"
@click=${() => {
this.reloadCodeAction();
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="currentColor">
<path
d="M480-160q-134 0-227-93t-93-227q0-134 93-227t227-93q69 0 132 28.5T720-690v-110h80v280H520v-80h168q-32-56-87.5-88T480-720q-100 0-170 70t-70 170q0 100 70 170t170 70q77 0 139-44t87-116h84q-28 106-114 173t-196 67Z" />
</svg>
<div class="button-label">
<p>Reload</p>
<div
id="reloadTooltip"
class="button-tooltip ${classMap({
'show-tooltip': this.codeNeedsReload,
})}">
<p>Reload code changes</p>
</div>
</div>
</button>
<button
id="runCode"
class=${classMap({'disabled': this.isRunning})}
@click=${() => {
this.playAction();
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="55px"
viewBox="0 -960 960 960"
width="55px"
fill="currentColor">
<path
d="m380-300 280-180-280-180v360ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z" />
</svg>
</button>
<button
id="stop"
class=${classMap({'disabled': !this.isRunning})}
@click=${() => {
this.stopAction();
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="55px"
viewBox="0 -960 960 960"
width="55px"
fill="currentColor">
<path
d="M320-320h320v-320H320v320ZM480-80q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Z" />
</svg>
</button>
<button
id="clear"
@click=${() => {
this.clearAction();
}}>
<svg
xmlns="http://www.w3.org/2000/svg"
height="30px"
viewBox="0 -960 960 960"
width="30px"
fill="currentColor">
<path
d="m376-300 104-104 104 104 56-56-104-104 104-104-56-56-104 104-104-104-56 56 104 104-104 104 56 56Zm-96 180q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Z" />
</svg>
<div class="button-label">
<p>Reset</p>
</div>
</button>
</div>
</div>
</div>`;
}