- Added Textual TUI framework with modern terminal UI - Created main TUI app with navigation, message view, event log, state inspector - Added comprehensive CSS styling for Discord-like appearance - Implemented navigation pane, message area, event log, state tree, command bar - Added keyboard shortcuts (Ctrl+Q quit, Ctrl+C command, Ctrl+N/P nav, etc.) - Integrated TUI with existing REST/Gateway servers and state management - Added CLI flag --tui/--no-tui to launch TUI mode - Added Textual and textual-dev to optional dependencies All 19 tests passing.
474 lines
6.7 KiB
Plaintext
474 lines
6.7 KiB
Plaintext
/* APIcord TUI Styles */
|
|
|
|
Screen {
|
|
background: $surface;
|
|
color: $text;
|
|
}
|
|
|
|
#navigation-pane {
|
|
width: 22;
|
|
background: $panel;
|
|
border-right: solid $primary;
|
|
padding: 1;
|
|
}
|
|
|
|
#navigation-pane .nav-title {
|
|
text-style: bold;
|
|
color: $accent;
|
|
margin-bottom: 1;
|
|
}
|
|
|
|
#navigation-pane .nav-item {
|
|
height: 3;
|
|
margin: 0 1;
|
|
padding: 0 1;
|
|
background: $surface;
|
|
border: solid $background;
|
|
}
|
|
|
|
#navigation-pane .nav-item:hover {
|
|
background: $primary 20%;
|
|
border: solid $primary;
|
|
}
|
|
|
|
#navigation-pane .nav-item:focus {
|
|
background: $primary 30%;
|
|
border: solid $accent;
|
|
}
|
|
|
|
#navigation-pane .nav-item .nav-icon {
|
|
width: 3;
|
|
text-align: center;
|
|
color: $text-muted;
|
|
}
|
|
|
|
#navigation-pane .nav-item .nav-label {
|
|
width: 1fr;
|
|
}
|
|
|
|
#navigation-pane .nav-item .nav-badge {
|
|
width: 5;
|
|
text-align: right;
|
|
color: $accent;
|
|
text-style: bold;
|
|
}
|
|
|
|
#main-content {
|
|
width: 1fr;
|
|
background: $surface;
|
|
layout: vertical;
|
|
}
|
|
|
|
#message-area {
|
|
height: 1fr;
|
|
border: solid $primary;
|
|
margin: 1;
|
|
padding: 1;
|
|
}
|
|
|
|
#message-list {
|
|
height: 1fr;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.message-entry {
|
|
height: auto;
|
|
min-height: 3;
|
|
margin: 0 0 1 0;
|
|
padding: 1;
|
|
background: $panel;
|
|
border: solid $background;
|
|
}
|
|
|
|
.message-entry:hover {
|
|
border: solid $primary;
|
|
}
|
|
|
|
.message-header {
|
|
height: 1;
|
|
layout: horizontal;
|
|
}
|
|
|
|
.message-author {
|
|
color: $accent;
|
|
text-style: bold;
|
|
}
|
|
|
|
.message-timestamp {
|
|
color: $text-muted;
|
|
text-align: right;
|
|
width: 20;
|
|
}
|
|
|
|
.message-content {
|
|
margin-top: 1;
|
|
color: $text;
|
|
}
|
|
|
|
.message-embed {
|
|
margin-top: 1;
|
|
padding: 1;
|
|
background: $surface;
|
|
border: solid $primary;
|
|
}
|
|
|
|
.embed-title {
|
|
color: $accent;
|
|
text-style: bold;
|
|
}
|
|
|
|
.embed-description {
|
|
margin: 1 0;
|
|
color: $text;
|
|
}
|
|
|
|
.embed-fields {
|
|
layout: horizontal;
|
|
}
|
|
|
|
.embed-field {
|
|
width: 1fr;
|
|
margin: 0 1;
|
|
padding: 1;
|
|
background: $surface;
|
|
border: solid $background;
|
|
}
|
|
|
|
.embed-field.inline {
|
|
width: auto;
|
|
min-width: 20;
|
|
}
|
|
|
|
.embed-field-name {
|
|
color: $text-muted;
|
|
text-style: bold;
|
|
text-transform: uppercase;
|
|
font-size: 80%;
|
|
}
|
|
|
|
.embed-field-value {
|
|
color: $text;
|
|
margin-top: 1;
|
|
}
|
|
|
|
.embed-footer {
|
|
margin-top: 1;
|
|
color: $text-muted;
|
|
font-size: 80%;
|
|
text-align: right;
|
|
}
|
|
|
|
.message-components {
|
|
margin-top: 1;
|
|
layout: horizontal;
|
|
}
|
|
|
|
.component-button {
|
|
min-width: 16;
|
|
height: 3;
|
|
margin: 0 1;
|
|
border: solid $primary;
|
|
}
|
|
|
|
.component-button.primary {
|
|
background: $primary;
|
|
color: $surface;
|
|
}
|
|
|
|
.component-button.secondary {
|
|
background: $secondary;
|
|
color: $surface;
|
|
}
|
|
|
|
.component-button.success {
|
|
background: $success;
|
|
color: $surface;
|
|
}
|
|
|
|
.component-button.danger {
|
|
background: $error;
|
|
color: $surface;
|
|
}
|
|
|
|
.component-button.link {
|
|
background: transparent;
|
|
color: $primary;
|
|
text-style: underline;
|
|
}
|
|
|
|
.component-select {
|
|
min-width: 30;
|
|
height: 3;
|
|
margin: 0 1;
|
|
border: solid $primary;
|
|
background: $surface;
|
|
}
|
|
|
|
#inspector-pane {
|
|
width: 36;
|
|
background: $panel;
|
|
border-left: solid $primary;
|
|
padding: 1;
|
|
}
|
|
|
|
#inspector-pane .section-title {
|
|
text-style: bold underline;
|
|
color: $accent;
|
|
margin: 1 0;
|
|
}
|
|
|
|
#inspector-pane .state-tree {
|
|
height: 1fr;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.tree-node {
|
|
height: 1;
|
|
padding: 0 1;
|
|
}
|
|
|
|
.tree-node.expanded > .node-label {
|
|
text-style: bold;
|
|
}
|
|
|
|
.tree-node .node-icon {
|
|
width: 2;
|
|
}
|
|
|
|
.tree-node .node-label {
|
|
width: 1fr;
|
|
}
|
|
|
|
.tree-node .node-value {
|
|
width: 12;
|
|
text-align: right;
|
|
color: $text-muted;
|
|
}
|
|
|
|
#event-log {
|
|
height: 1fr;
|
|
border: solid $primary;
|
|
margin: 1;
|
|
padding: 1;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.event-entry {
|
|
height: 1;
|
|
padding: 0 1;
|
|
border-bottom: solid $background 50%;
|
|
}
|
|
|
|
.event-entry:hover {
|
|
background: $primary 10%;
|
|
}
|
|
|
|
.event-time {
|
|
width: 10;
|
|
color: $text-muted;
|
|
text-style: bold;
|
|
}
|
|
|
|
.event-type {
|
|
width: 20;
|
|
color: $accent;
|
|
text-style: bold;
|
|
}
|
|
|
|
.event-detail {
|
|
width: 1fr;
|
|
color: $text;
|
|
}
|
|
|
|
#command-bar {
|
|
height: 3;
|
|
background: $panel;
|
|
border-top: solid $primary;
|
|
padding: 0 1;
|
|
layout: horizontal;
|
|
}
|
|
|
|
#command-bar .prompt {
|
|
width: 3;
|
|
color: $accent;
|
|
text-style: bold;
|
|
content-align: center middle;
|
|
}
|
|
|
|
#command-input {
|
|
width: 1fr;
|
|
height: 3;
|
|
background: $surface;
|
|
border: solid $primary;
|
|
padding: 0 1;
|
|
}
|
|
|
|
#command-input:focus {
|
|
border: solid $accent;
|
|
}
|
|
|
|
#status-bar {
|
|
height: 1;
|
|
background: $primary;
|
|
color: $surface;
|
|
padding: 0 1;
|
|
layout: horizontal;
|
|
}
|
|
|
|
.status-item {
|
|
width: auto;
|
|
margin-right: 2;
|
|
}
|
|
|
|
#footer-hints {
|
|
height: 1;
|
|
background: $surface;
|
|
color: $text-muted;
|
|
padding: 0 1;
|
|
text-align: center;
|
|
}
|
|
|
|
.tabbed-content {
|
|
height: 1fr;
|
|
}
|
|
|
|
.tab-header {
|
|
height: 1;
|
|
layout: horizontal;
|
|
background: $panel;
|
|
border-bottom: solid $primary;
|
|
}
|
|
|
|
.tab-button {
|
|
min-width: 12;
|
|
height: 1;
|
|
padding: 0 1;
|
|
background: transparent;
|
|
border: none;
|
|
color: $text-muted;
|
|
}
|
|
|
|
.tab-button.active {
|
|
color: $accent;
|
|
text-style: bold;
|
|
border-bottom: solid $accent;
|
|
}
|
|
|
|
.tab-button:hover {
|
|
color: $text;
|
|
background: $surface;
|
|
}
|
|
|
|
.tab-panel {
|
|
height: 1fr;
|
|
display: none;
|
|
}
|
|
|
|
.tab-panel.active {
|
|
display: block;
|
|
}
|
|
|
|
/* Modal / Dialog */
|
|
.modal {
|
|
align: center middle;
|
|
width: 60;
|
|
height: 30;
|
|
background: $panel;
|
|
border: thick $accent;
|
|
padding: 1;
|
|
}
|
|
|
|
.modal-title {
|
|
text-style: bold;
|
|
color: $accent;
|
|
margin-bottom: 1;
|
|
text-align: center;
|
|
}
|
|
|
|
.modal-content {
|
|
height: 1fr;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.modal-buttons {
|
|
height: 3;
|
|
layout: horizontal;
|
|
margin-top: 1;
|
|
}
|
|
|
|
.modal-button {
|
|
width: 1fr;
|
|
margin: 0 1;
|
|
}
|
|
|
|
/* Command Palette */
|
|
.command-palette {
|
|
align: center middle;
|
|
width: 80;
|
|
height: 40;
|
|
background: $panel;
|
|
border: thick $accent;
|
|
padding: 1;
|
|
}
|
|
|
|
.command-palette-input {
|
|
width: 1fr;
|
|
height: 3;
|
|
margin-bottom: 1;
|
|
}
|
|
|
|
.command-palette-results {
|
|
height: 1fr;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.command-palette-item {
|
|
height: 3;
|
|
padding: 0 1;
|
|
layout: horizontal;
|
|
}
|
|
|
|
.command-palette-item:hover {
|
|
background: $primary 20%;
|
|
}
|
|
|
|
.command-palette-item .cmd-name {
|
|
width: 24;
|
|
color: $accent;
|
|
text-style: bold;
|
|
}
|
|
|
|
.command-palette-item .cmd-desc {
|
|
width: 1fr;
|
|
color: $text-muted;
|
|
}
|
|
|
|
.command-palette-item .cmd-shortcut {
|
|
width: 20;
|
|
text-align: right;
|
|
color: $text-muted;
|
|
font-size: 80%;
|
|
}
|
|
|
|
/* Connection status indicators */
|
|
.status-connected {
|
|
color: $success;
|
|
}
|
|
|
|
.status-disconnected {
|
|
color: $error;
|
|
}
|
|
|
|
.status-connecting {
|
|
color: $warning;
|
|
}
|
|
|
|
/* Scrollbar styling */
|
|
ScrollBar {
|
|
background: $surface;
|
|
color: $primary;
|
|
}
|
|
|
|
ScrollBar:hover {
|
|
color: $accent;
|
|
} |