| name | rdos-ui-components |
| description | UI components and rendering for R-DOS. Use when rendering modals, dialogs, lists, or any UI. CRITICAL - explains ModalFrame vs FullScreenView to prevent panics. |
R-DOS UI Components
CRITICAL: ModalFrame vs FullScreenView
This is the #1 source of bugs. ModalFrame PANICS on full-screen areas!
| Component | Use For | Max Size |
|---|
FullScreenView | Full-screen plugin views | Unlimited |
ModalFrame | Small centered dialogs | 79x23 max |
FullScreenView (Full-screen views)
use crate::ui::components::FullScreenView;
fn draw_modal(&self, frame: &mut Frame, area: Rect, colors: &ThemeColors) {
let view = FullScreenView::new(area, " TITLE ", colors);
view.render_frame(frame);
let content = view.content_area();
view.render_help(frame, vec![("Esc", "close")]);
}
ModalFrame (Small dialogs only)
use crate::ui::components::ModalFrame;
fn draw_dialog(&self, frame: &mut Frame, area: Rect, colors: &ThemeColors) {
let width = area.width.min(55);
let height = area.height.min(14);
let x = area.x + (area.width.saturating_sub(width)) / 2;
let y = area.y + (area.height.saturating_sub(height)) / 2;
let modal_area = Rect::new(x, y, width, height);
let modal = ModalFrame::themed(modal_area, " CONFIRM ", colors);
modal.render_frame(frame);
modal.render_help(frame, vec![("Y", "yes"), ("N", "no")]);
}
Available Components
use crate::ui::components::{
ModalFrame,
FullScreenView,
MessageModal,
ProgressBar,
ScrollableList,
Table,
InputField,
ConfirmDialog,
TabBar,
TabState,
LogViewer,
LogViewerState,
LogStatus,
};
TabBar Component
For plugins with multiple views (Containers/Images/Volumes/Networks):
use crate::ui::components::TabBar;
let tabs = vec!["Containers", "Images", "Volumes", "Networks"];
let tab_bar = TabBar::new(&tabs, selected_index);
let spans = tab_bar.render(&colors);
view.render_row(frame, 0, spans);
let mut state = TabState::new(4);
state.next();
state.prev();
LogViewer Component
For streaming command output (builds, terraform plan/apply):
use crate::ui::components::{LogViewer, LogViewerState, LogStatus};
let mut state = LogViewerState::new().with_visible_height(18);
state.push_line("Step 1/5: Starting...");
state.push_line("Downloading dependencies...");
let viewer = LogViewer::new(&state)
.title("Build Output")
.status(LogStatus::Running);
viewer.render(frame, &view, &colors);
state.scroll_up();
state.scroll_down();
state.page_up(18);
state.page_down(18);
state.scroll_to_top();
state.scroll_to_bottom();
let help = viewer.help_items();
view.render_help(frame, help);
LogStatus Values
LogStatus::Idle - Ready, not running
LogStatus::Running - In progress (yellow)
LogStatus::Success - Completed successfully (green)
LogStatus::Failed - Command failed (red)
Theme Colors
NEVER hardcode colors. Use ThemeColors:
fn draw(&self, frame: &mut Frame, area: Rect, colors: &ThemeColors) {
colors.fg()
colors.bg()
colors.blue()
colors.green()
colors.red()
colors.yellow()
colors.grey()
colors.cyan()
}
Selection Highlighting
let style = if is_selected {
Style::default().fg(colors.yellow()).bg(colors.red())
} else {
Style::default().fg(colors.fg())
};
Q-DOS II Screen Layout
Row 0: Title bar
Row 1: ═══════════════════════════ (separator)
Row 2: Context info
Row 3-N: Content area (scrollable)
Row N-1: ═══════════════════════════ (separator)
Row N: Help row (keybindings)
Border Characters
Double-line borders: ╔═╗║╚╝╠╣╦╩╬
Minimum Size
All layouts must work at 80x25 terminal size.