Radish alpha
h
Radicle Heartwood Protocol & Stack
Radicle
Git (anonymous pull)
Log in to clone via SSH
tui: Update navigation design
Erik Kundt committed 3 years ago
commit 362f26a0c8bfe08ca3711a2f85603c6d279bf78a
parent 4a99e18562763d3138cf03e7ddf260c50915ca4e
7 files changed +64 -38
modified radicle-tui/src/app/page.rs
@@ -81,8 +81,7 @@ impl ViewPage for Home {

    fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame) {
        let area = frame.size();
-
        let navigation_h = 1u16;
-
        let layout = layout::default_page(area, navigation_h);
+
        let layout = layout::default_page(area);

        app.view(&Cid::Home(HomeCid::Navigation), frame, layout[0]);
        app.view(&self.active_component, frame, layout[1]);
@@ -145,9 +144,7 @@ impl ViewPage for PatchView {

    fn view(&mut self, app: &mut Application<Cid, Message, NoUserEvent>, frame: &mut Frame) {
        let area = frame.size();
-
        let navigation_h = 2u16;
-

-
        let layout = layout::default_page(area, navigation_h);
+
        let layout = layout::default_page(area);

        app.view(&Cid::Patch(PatchCid::Navigation), frame, layout[0]);
        app.view(&self.active_component, frame, layout[1]);
modified radicle-tui/src/ui/components/common/container.rs
@@ -1,14 +1,15 @@
use tuirealm::command::{Cmd, CmdResult};
use tuirealm::props::{
    AttrValue, Attribute, BorderSides, BorderType, Color, PropPayload, PropValue, Props, Style,
+
    TextModifiers,
};
use tuirealm::tui::layout::{Constraint, Direction, Layout, Rect};
-
use tuirealm::tui::text::{Span, Spans};
use tuirealm::tui::widgets::{Block, Cell, Row};
use tuirealm::{Frame, MockComponent, State, StateValue};

use crate::ui::components::common::label::Label;
use crate::ui::ext::HeaderBlock;
+
use crate::ui::layout;
use crate::ui::state::TabState;
use crate::ui::widget::{Widget, WidgetComponent};

@@ -35,16 +36,16 @@ impl WidgetComponent for GlobalListener {
#[derive(Clone)]
pub struct Tabs {
    tabs: Vec<Widget<Label>>,
-
    divider: Widget<Label>,
+
    line: Widget<Label>,
    state: TabState,
}

impl Tabs {
-
    pub fn new(tabs: Vec<Widget<Label>>, divider: Widget<Label>) -> Self {
+
    pub fn new(tabs: Vec<Widget<Label>>, line: Widget<Label>) -> Self {
        let count = &tabs.len();
        Self {
            tabs,
-
            divider,
+
            line,
            state: TabState {
                selected: 0,
                len: *count as u16,
@@ -59,27 +60,46 @@ impl WidgetComponent for Tabs {
        let display = properties
            .get_or(Attribute::Display, AttrValue::Flag(true))
            .unwrap_flag();
-
        let foreground = properties
-
            .get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
-
            .unwrap_color();
-
        let highlight = properties
-
            .get_or(Attribute::HighlightedColor, AttrValue::Color(Color::Reset))
-
            .unwrap_color();

        if display {
-
            let spans = self
-
                .tabs
-
                .iter()
-
                .map(|tab| Spans::from(vec![Span::from(tab)]))
-
                .collect::<Vec<_>>();
+
            let layout = Layout::default()
+
                .direction(Direction::Vertical)
+
                .constraints(vec![
+
                    Constraint::Length(1),
+
                    Constraint::Length(1),
+
                    Constraint::Length(1),
+
                ])
+
                .split(area);
+

+
            // Render tabs on first row, highlighting the selected tab.
+
            let mut tabs = vec![];
+
            for (index, tab) in self.tabs.iter().enumerate() {
+
                let mut tab = tab.clone().to_boxed();
+
                if index == selected as usize {
+
                    tab.attr(
+
                        Attribute::TextProps,
+
                        AttrValue::TextModifiers(TextModifiers::REVERSED),
+
                    );
+
                }
+
                tabs.push(tab.clone().to_boxed() as Box<dyn MockComponent>);
+
            }
+
            tabs.push(Widget::new(Label::default()).to_boxed());

-
            let tabs = tuirealm::tui::widgets::Tabs::new(spans)
-
                .style(Style::default().fg(foreground))
-
                .highlight_style(Style::default().fg(highlight))
-
                .divider(Span::from(&self.divider))
-
                .select(selected as usize);
+
            let tab_layout = layout::h_stack(tabs, layout[1]);
+
            for (mut tab, area) in tab_layout {
+
                tab.view(frame, area);
+
            }

-
            frame.render_widget(tabs, area);
+
            // Repeat and render line on second row.
+
            let overlines = vec![self.line.clone(); area.width as usize];
+
            let overlines = overlines
+
                .iter()
+
                .map(|l| l.clone().to_boxed() as Box<dyn MockComponent>)
+
                .collect();
+
            let line_layout = layout::h_stack(overlines, layout[2]);
+
            for (mut line, area) in line_layout {
+
                line.view(frame, area);
+
            }
        }
    }

modified radicle-tui/src/ui/layout.rs
@@ -46,7 +46,8 @@ pub fn h_stack(
    widgets.into_iter().zip(layout.into_iter()).collect()
}

-
pub fn default_page(area: Rect, nav_h: u16) -> Vec<Rect> {
+
pub fn default_page(area: Rect) -> Vec<Rect> {
+
    let nav_h = 3u16;
    let margin_h = 1u16;
    let content_h = area.height.saturating_sub(nav_h.saturating_add(margin_h));

modified radicle-tui/src/ui/theme.rs
@@ -25,6 +25,7 @@ pub struct Icons {
    pub property_divider: char,
    pub shortcutbar_divider: char,
    pub tab_divider: char,
+
    pub tab_overline: char,
    pub whitespace: char,
}

@@ -55,7 +56,7 @@ pub fn default_dark() -> Theme {
        colors: Colors {
            default_fg: Color::Rgb(200, 200, 200),
            tabs_fg: Color::Rgb(100, 100, 100),
-
            tabs_highlighted_fg: Color::Rgb(38, 162, 105),
+
            tabs_highlighted_fg: Color::Rgb(85, 85, 255),
            workspaces_info_fg: Color::Rgb(220, 140, 40),
            labeled_container_bg: Color::Rgb(20, 20, 20),
            item_list_highlighted_bg: Color::Rgb(40, 40, 40),
@@ -74,6 +75,7 @@ pub fn default_dark() -> Theme {
            property_divider: '∙',
            shortcutbar_divider: '∙',
            tab_divider: '|',
+
            tab_overline: '▔',
            whitespace: ' ',
        },
    }
modified radicle-tui/src/ui/widget/common.rs
@@ -27,6 +27,11 @@ pub fn label(content: &str) -> Widget<Label> {
        .width(width)
}

+
pub fn reversable_label(content: &str) -> Widget<Label> {
+
    let content = &format!(" {content} ");
+
    label(content)
+
}
+

pub fn container_header(theme: &Theme, label: &str) -> Widget<Header> {
    let content = AttrValue::Payload(PropPayload::Vec(vec![PropValue::TextSpan(
        TextSpan::from(&format!(" {label} ")).fg(theme.colors.default_fg),
@@ -112,13 +117,11 @@ pub fn property_list(_theme: &Theme, properties: Vec<Widget<Property>>) -> Widge
}

pub fn tabs(theme: &Theme, tabs: Vec<Widget<Label>>) -> Widget<Tabs> {
-
    let divider = label(&theme.icons.tab_divider.to_string());
-
    let tabs = Tabs::new(tabs, divider);
+
    let line =
+
        label(&theme.icons.tab_overline.to_string()).foreground(theme.colors.tabs_highlighted_fg);
+
    let tabs = Tabs::new(tabs, line);

-
    Widget::new(tabs)
-
        .height(1)
-
        .foreground(theme.colors.tabs_fg)
-
        .highlight(theme.colors.tabs_highlighted_fg)
+
    Widget::new(tabs).height(2)
}

pub fn table(
modified radicle-tui/src/ui/widget/home.rs
@@ -13,9 +13,9 @@ pub fn navigation(theme: &Theme) -> Widget<Tabs> {
    common::tabs(
        theme,
        vec![
-
            common::label("dashboard"),
-
            common::label("issues"),
-
            common::label("patches"),
+
            common::reversable_label("dashboard").foreground(theme.colors.tabs_highlighted_fg),
+
            common::reversable_label("issues").foreground(theme.colors.tabs_highlighted_fg),
+
            common::reversable_label("patches").foreground(theme.colors.tabs_highlighted_fg),
        ],
    )
}
modified radicle-tui/src/ui/widget/patch.rs
@@ -15,7 +15,10 @@ use crate::ui::theme::Theme;
pub fn navigation(theme: &Theme) -> Widget<Tabs> {
    common::tabs(
        theme,
-
        vec![common::label("activity"), common::label("files")],
+
        vec![
+
            common::reversable_label("activity").foreground(theme.colors.tabs_highlighted_fg),
+
            common::reversable_label("files").foreground(theme.colors.tabs_highlighted_fg),
+
        ],
    )
}