mirror of
https://github.com/murashit/codex-panel.git
synced 2026-07-22 06:57:10 +00:00
Refine rewrite selection popover styling and shortcuts
This commit is contained in:
parent
a1f550a5d7
commit
2496099850
2 changed files with 35 additions and 69 deletions
|
|
@ -1,7 +1,7 @@
|
|||
import { Notice, type Editor } from "obsidian";
|
||||
|
||||
import { syncComposerHeight } from "../ui/composer";
|
||||
import { createIconButton } from "../ui/components";
|
||||
import { syncTextareaHeight } from "../ui/textarea-autogrow";
|
||||
import { diffLineClass, displayDiffLineText, displayDiffLines } from "../ui/turn-diff";
|
||||
import { buildSelectionUnifiedDiff } from "./diff";
|
||||
import { isRewriteActionKey, isRewriteGenerateKey } from "./keys";
|
||||
|
|
@ -115,6 +115,7 @@ export class RewriteSelectionPopover {
|
|||
} finally {
|
||||
if (this.abortController === abortController) this.abortController = null;
|
||||
this.syncControls();
|
||||
if (this.options.session.status === "preview") this.focusApplyButton();
|
||||
this.position();
|
||||
}
|
||||
}
|
||||
|
|
@ -140,10 +141,9 @@ export class RewriteSelectionPopover {
|
|||
const root = activeDocument.body.createDiv({ cls: "codex-panel-rewrite-popover" });
|
||||
root.setAttr("role", "dialog");
|
||||
root.setAttr("aria-label", "Rewrite selection");
|
||||
root.onkeydown = (event) => this.handlePopoverKeydown(event);
|
||||
|
||||
const instruction = root.createEl("textarea", {
|
||||
cls: "codex-panel-rewrite-popover__instruction",
|
||||
cls: "codex-panel__input codex-panel-rewrite-popover__instruction",
|
||||
attr: { placeholder: "How should Codex rewrite the selected text?" },
|
||||
});
|
||||
instruction.value = this.options.session.instruction;
|
||||
|
|
@ -162,18 +162,38 @@ export class RewriteSelectionPopover {
|
|||
|
||||
const promptRow = root.createDiv({ cls: "codex-panel-rewrite-popover__prompt-row" });
|
||||
promptRow.append(instruction);
|
||||
const controls = promptRow.createDiv({ cls: "codex-panel-rewrite-popover__controls" });
|
||||
const generateButton = createIconButton(controls, "sparkles", "Generate rewrite", "codex-panel-rewrite-popover__icon-button");
|
||||
const controls = promptRow.createDiv({ cls: "codex-panel__composer-actions codex-panel-rewrite-popover__controls" });
|
||||
const generateButton = createIconButton(
|
||||
controls,
|
||||
"sparkles",
|
||||
"Generate rewrite",
|
||||
"codex-panel__composer-action codex-panel-rewrite-popover__icon-button",
|
||||
);
|
||||
generateButton.onclick = () => void this.generate();
|
||||
const cancelButton = createIconButton(controls, "x", "Cancel rewrite", "codex-panel-rewrite-popover__icon-button");
|
||||
const cancelButton = createIconButton(
|
||||
controls,
|
||||
"x",
|
||||
"Cancel rewrite",
|
||||
"codex-panel__composer-action codex-panel-rewrite-popover__icon-button",
|
||||
);
|
||||
cancelButton.onclick = () => this.cancel();
|
||||
|
||||
const status = root.createDiv({ cls: "codex-panel-rewrite-popover__status" });
|
||||
const streamPreview = root.createEl("pre", { cls: "codex-panel-rewrite-popover__stream-preview is-hidden" });
|
||||
const resultRow = root.createDiv({ cls: "codex-panel-rewrite-popover__result-row" });
|
||||
const diff = resultRow.createDiv({ cls: "codex-panel-rewrite-popover__diff" });
|
||||
const applyButton = createIconButton(resultRow, "check", "Apply rewrite", "codex-panel-rewrite-popover__icon-button mod-cta");
|
||||
const applyButton = createIconButton(
|
||||
resultRow,
|
||||
"check",
|
||||
"Apply rewrite",
|
||||
"codex-panel__composer-action codex-panel-rewrite-popover__icon-button mod-cta",
|
||||
);
|
||||
applyButton.onclick = () => this.apply();
|
||||
applyButton.onkeydown = (event) => {
|
||||
if (!isRewriteActionKey(event)) return;
|
||||
event.preventDefault();
|
||||
this.apply();
|
||||
};
|
||||
|
||||
return { root, instruction, generateButton, applyButton, resultRow, status, streamPreview, diff, debug: null };
|
||||
}
|
||||
|
|
@ -254,13 +274,9 @@ export class RewriteSelectionPopover {
|
|||
this.close();
|
||||
}
|
||||
|
||||
private handlePopoverKeydown(event: KeyboardEvent): void {
|
||||
if (!this.elements || event.target === this.elements.instruction) return;
|
||||
if (isInteractiveEventTarget(event.target)) return;
|
||||
if (this.options.session.replacementText === null || this.options.session.status === "generating") return;
|
||||
if (!isRewriteActionKey(event)) return;
|
||||
event.preventDefault();
|
||||
this.apply();
|
||||
private focusApplyButton(): void {
|
||||
if (!this.elements || this.elements.applyButton.disabled) return;
|
||||
this.elements.applyButton.focus({ preventScroll: true });
|
||||
}
|
||||
|
||||
private setStatus(text: string, options: { active?: boolean } = {}): void {
|
||||
|
|
@ -291,10 +307,7 @@ export class RewriteSelectionPopover {
|
|||
}
|
||||
|
||||
private syncInstructionHeight(): void {
|
||||
syncTextareaHeight(this.elements?.instruction ?? null, {
|
||||
minHeightFallback: 0,
|
||||
maxHeightFallback: Math.min(168, activeWindow.innerHeight * 0.28),
|
||||
});
|
||||
syncComposerHeight(this.elements?.instruction ?? null);
|
||||
}
|
||||
|
||||
private position(): void {
|
||||
|
|
@ -336,8 +349,3 @@ function renderRewriteDiff(parent: HTMLElement, diff: string): void {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isInteractiveEventTarget(target: EventTarget | null): boolean {
|
||||
if (!(target instanceof HTMLElement)) return false;
|
||||
return Boolean(target.closest("button, input, textarea, select, a, [role='button']"));
|
||||
}
|
||||
|
|
|
|||
50
styles.css
50
styles.css
|
|
@ -1,5 +1,6 @@
|
|||
.codex-panel,
|
||||
.codex-panel-settings {
|
||||
.codex-panel-settings,
|
||||
.codex-panel-rewrite-popover {
|
||||
--codex-panel-top-icon-size: var(--icon-s, 16px);
|
||||
--codex-panel-icon-button-inline-size: calc(var(--codex-panel-top-icon-size) + var(--size-2-3, 6px) * 2);
|
||||
--codex-panel-icon-button-block-size: calc(var(--codex-panel-top-icon-size) + var(--size-2-2, 4px) * 2);
|
||||
|
|
@ -1397,8 +1398,6 @@
|
|||
}
|
||||
|
||||
.codex-panel-rewrite-popover {
|
||||
--rewrite-icon-button-size: calc(var(--icon-s, 16px) + var(--size-2-3, 6px) * 2);
|
||||
--rewrite-control-stack-size: calc(var(--rewrite-icon-button-size) * 2 + var(--size-2-1, 2px));
|
||||
position: fixed;
|
||||
z-index: var(--layer-popover, 30);
|
||||
box-sizing: border-box;
|
||||
|
|
@ -1416,38 +1415,17 @@
|
|||
color: var(--text-normal);
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__instruction {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: var(--rewrite-control-stack-size);
|
||||
min-height: var(--rewrite-control-stack-size);
|
||||
max-height: min(168px, 28vh);
|
||||
padding: var(--size-2-3, 6px) var(--size-4-2, 8px);
|
||||
line-height: var(--line-height-normal);
|
||||
resize: none;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__prompt-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: var(--size-2-2, 4px);
|
||||
gap: var(--codex-panel-section-gap);
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
justify-content: flex-start;
|
||||
gap: var(--size-2-1, 2px);
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__result-row {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
gap: var(--size-2-2, 4px);
|
||||
gap: var(--codex-panel-control-gap);
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
|
|
@ -1456,30 +1434,10 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__icon-button {
|
||||
--icon-size: var(--icon-s, 16px);
|
||||
--icon-stroke: var(--icon-s-stroke-width, 2px);
|
||||
box-sizing: border-box;
|
||||
width: var(--rewrite-icon-button-size);
|
||||
height: var(--rewrite-icon-button-size);
|
||||
min-width: var(--rewrite-icon-button-size);
|
||||
min-height: var(--rewrite-icon-button-size);
|
||||
padding: var(--size-2-3, 6px);
|
||||
border: 0;
|
||||
border-radius: var(--clickable-icon-radius, var(--radius-s));
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__icon-button.is-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__icon-button svg {
|
||||
width: var(--icon-size);
|
||||
height: var(--icon-size);
|
||||
stroke-width: var(--icon-stroke);
|
||||
}
|
||||
|
||||
.codex-panel-rewrite-popover__status {
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-ui-small);
|
||||
|
|
|
|||
Loading…
Reference in a new issue