Files
deepagents/libs/code/deepagents_code/app.tcss
Mason Daugherty 0c7e58c508 refactor(code): share inline prompt infrastructure (#4724)
`ask_user` and goal review independently implemented the same inline
prompt mechanics, which made their shared lifecycle and input behavior
harder to maintain consistently.

This refactor introduces small neutral primitives for prompt text entry,
option rendering, one-shot future resolution, prompt chrome, and
application-level mounting, scrolling, cleanup, and focus restoration.
Each flow continues to own its domain state machine: `ask_user` retains
arbitrary text and multiple-choice LangGraph interrupt handling, while
goal review retains its accepted, edited, rejected, and cancelled
outcomes and shortcuts.

The existing appearance, key controls, result payloads, interruption
behavior, replacement policies, and cancellation semantics remain
unchanged. Coverage exercises both consumers independently, including
navigation, text submission, cancellation, focus, cleanup races, and
future resolution.
2026-07-14 14:52:53 -04:00

409 lines
7.9 KiB
Plaintext

/* Deep Agents Code Textual Stylesheet */
/* Define layers for z-ordering */
Screen {
layout: vertical;
layers: base autocomplete;
}
/* Thin scrollbars app-wide */
* {
scrollbar-size-vertical: 1;
}
/* Hide the Header's clickable ⭘ icon. It opens the command palette by default,
but ENABLE_COMMAND_PALETTE = False on the app, so it's already inert. We use
`visibility: hidden` (not `display: none`) so the 8-cell gutter is preserved
and balances the clock-space gutter on the right, keeping the title centered. */
#app-header HeaderIcon {
visibility: hidden;
}
/* Main content goes on base layer by default */
.message-timestamp-footer {
display: none;
height: auto;
color: $text-muted;
text-style: dim;
margin: -1 0 1 0;
padding: 0;
}
/*
* Visibility is toggled per-footer (not via a class on #messages) so a
* `/timestamps` toggle restyles only the footer leaves instead of forcing a
* re-cascade across every message subtree.
*/
.message-timestamp-footer.message-timestamp-footer-visible {
display: block;
}
/* Chat area - main scrollable messages area.
No horizontal padding so message blocks span the same full width as the
input box below (whose border is flush to both edges). The scrollbar is
toggled at runtime via the /scrollbar command (off by default). */
#chat {
height: 1fr;
padding: 1 0 0 0;
background: $background;
}
/* Welcome banner */
#welcome-banner {
height: auto;
margin-bottom: 1;
}
/* Messages area — uses undocumented "stream" layout (Textual ≥5.2.0) for
O(1) append performance via incremental placement caching. */
#messages {
layout: stream;
height: auto;
}
/* Bottom app container - holds ChatInput (now inside scroll) */
#bottom-app-container {
height: auto;
margin-top: 0;
}
/* Input area */
#input-area {
height: auto;
min-height: 3;
max-height: 25;
}
/* Approval Menu - inline in messages area */
.approval-menu {
height: auto;
margin: 1 0;
padding: 0 1;
background: $surface;
border: solid $warning;
}
/* Placeholder shown while the user is actively typing (approval deferred) */
.approval-placeholder {
height: auto;
margin: 1 0;
padding: 0 1;
border: solid $panel;
color: $text-muted;
text-style: italic;
}
.approval-menu .approval-title {
text-style: bold;
color: $warning;
margin-bottom: 0;
}
.approval-menu .approval-info {
height: auto;
color: $text-muted;
margin-bottom: 1;
}
.approval-menu .approval-option {
height: 1;
padding: 0 1;
}
.approval-menu .approval-option-selected {
background: $primary;
text-style: bold;
}
.approval-menu .approval-help {
color: $text-muted;
text-style: italic;
margin-top: 0;
margin-bottom: 0;
}
/* Status bar */
#status-bar {
height: 1;
dock: bottom;
}
/* Tool approval widgets */
.tool-approval-widget {
height: auto;
}
.approval-description {
color: $text-muted;
}
/* Diff styling — used by EditFileApprovalWidget (fg + bg + padding) */
.diff-removed {
height: auto;
color: $text-error;
background: $error-muted;
padding: 0 1;
}
.diff-added {
height: auto;
color: $text-success;
background: $success-muted;
padding: 0 1;
}
.diff-context {
height: auto;
color: $text-muted;
padding: 0 1;
}
/* Diff line backgrounds — used by compose_diff_lines (bg only, fg via Content) */
.diff-line-removed {
background: $error-muted;
}
.diff-line-added {
background: $success-muted;
}
/* Mode-specific borders for UserMessage */
UserMessage.-mode-shell {
border-left: wide $mode-bash;
}
UserMessage.-mode-shell-incognito {
border-left: wide $mode-incognito;
}
UserMessage.-mode-command {
border-left: wide $mode-command;
}
/* ASCII border overrides */
UserMessage.-ascii {
border-left: ascii $primary;
}
UserMessage.-ascii.-mode-shell {
border-left: ascii $mode-bash;
}
UserMessage.-ascii.-mode-shell-incognito {
border-left: ascii $mode-incognito;
}
UserMessage.-ascii.-mode-command {
border-left: ascii $mode-command;
}
QueuedUserMessage.-ascii {
border-left: ascii $panel;
}
ToolCallMessage.-ascii {
border-left: ascii $panel;
}
ToolCallMessage.-ascii:hover {
border-left: ascii $secondary;
}
/* Approval command — warning color for shell commands */
.approval-menu .approval-command {
height: auto;
margin: 0 0 1 0;
padding: 0 1;
color: $warning;
}
/* Separator line between tool details and options */
.approval-menu .approval-separator {
height: 1;
color: $warning;
margin: 0;
}
/* Scrollable tool info area in approval menu */
.approval-menu .tool-info-scroll {
height: auto;
max-height: 10;
margin-top: 0;
}
/* Inner container for tool info - allows content to expand for scrolling */
.approval-menu .tool-info-container {
height: auto;
}
/* Options container with background */
.approval-menu .approval-options-container {
height: auto;
background: $surface-darken-1;
padding: 0 1;
margin-top: 0;
}
/* Free-text reject reason input (Tab on Reject) */
.approval-menu .approval-reason-input {
margin: 1 0 0 0;
border: solid $warning;
background: $surface;
}
/* Persistent goal status */
.goal-status-panel {
height: auto;
max-height: 5;
margin: 0 1;
padding: 0 1;
color: $text;
background: $surface-darken-1;
border-left: thick $primary;
}
/* Shared inline prompt shell */
.inline-prompt {
height: auto;
margin: 1 0;
padding: 0 1;
background: $surface;
border: solid $success;
}
.inline-prompt .inline-prompt-title {
text-style: bold;
color: $success;
margin-bottom: 0;
}
.inline-prompt .inline-prompt-help {
color: $text-muted;
text-style: italic;
margin-top: 0;
margin-bottom: 0;
}
.inline-prompt .inline-prompt-input {
& .text-area--cursor-line {
background: transparent;
}
& .text-area--cursor-gutter {
background: transparent;
}
}
/* Goal review widget */
.goal-review-menu .goal-review-content {
height: auto;
max-height: 12;
padding: 0 1;
}
.goal-review-menu .goal-review-body {
height: auto;
}
.goal-review-menu .goal-review-markdown {
margin: 0 0 1 0;
padding: 0;
}
.goal-review-menu .goal-review-options-container {
height: auto;
background: $surface-darken-1;
padding: 0 1;
margin-top: 0;
}
.goal-review-menu .goal-review-option {
height: 1;
padding: 0 1;
}
.goal-review-menu .goal-review-option-selected {
background: $primary;
text-style: bold;
}
.goal-review-menu .goal-review-edit-input {
margin: 1 1 0 1;
height: auto;
min-height: 4;
max-height: 12;
background: transparent;
}
/* Ask user widget */
.ask-user-menu .ask-user-questions {
height: auto;
padding: 0 1;
}
.ask-user-menu .ask-user-question {
height: auto;
margin-bottom: 1;
}
.ask-user-menu .ask-user-question-active {
border-left: thick $success;
padding-left: 1;
}
.ask-user-menu .ask-user-question-inactive {
opacity: 0.5;
padding-left: 2;
}
.ask-user-menu .ask-user-question-text {
margin: 0 0 0 2;
padding: 0;
}
.ask-user-menu .ask-user-choice {
height: auto;
padding: 0 1;
}
.ask-user-menu .ask-user-text-input {
margin: 1 1 0 1;
height: auto;
min-height: 3;
max-height: 10;
background: transparent;
}
.ask-user-menu .ask-user-other-input {
margin: 1 1 0 1;
height: auto;
min-height: 3;
max-height: 10;
background: transparent;
}
/* ChatTextArea: override TextArea's built-in $surface background */
ChatTextArea {
background: transparent;
& .text-area--cursor-line {
background: transparent;
}
& .text-area--cursor-gutter {
background: transparent;
}
}
/* Completion popup styling (used by ChatInput) - appears BELOW input */
#completion-popup {
height: auto;
max-height: 12;
width: 100%;
margin-left: 3;
margin-top: 0;
padding: 0;
color: $text;
}