git.lucas.co / cce-system-interface
system settings
git clone https://git.lucas.co/cce-system-interface.git

commit96d3f299d5f262d4d70951ef06e3aa66a668147a
parent56f92cfb86
authorLucas Galante <[email protected]>
date2026-08-12 15:36
feat: Packages page restyle — one well, page-filling frameless list

The Packages / Package Info / System Update wells merge into a single
label-less well: tabs carry live counts, the update action collapses to
a compact button with its status inline, selected-package details (and
a compact quiet-red Uninstall) appear between the header and the list,
and the list drops its plate and fills the remaining page height.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/pages/packages.rs | 403 ++++++++++++++++++++++++--------------------------
 1 file changed, 191 insertions(+), 212 deletions(-)

diff --git a/src/pages/packages.rs b/src/pages/packages.rs
index 9e39f90..8f55503 100644
--- a/src/pages/packages.rs
+++ b/src/pages/packages.rs
@@ -1,4 +1,4 @@
-use crate::app::{AppAction, PageContent, SectionContextExt};
+use crate::app::{AppAction, PageContent, SectionContextExt, section_divider};
 use crate::scroll_region::ScrollRegion;
 use cce_ui::layout::{render_widget, PageLayoutBuilder, LayoutStrategy, SectionContext, RenderTarget};
 use cce_ui::widget::{WidgetHost, TextBox, InteractiveListItem};
@@ -55,9 +55,9 @@ impl Default for PackagesState {
             updates: Vec::new(),
             active_tab: PackageTab::Installed,
             search_box: TextBox::new(String::new()).with_placeholder("Filter Packages..."),
-            installed_list: ScrollRegion::new(32.0, 4.0),
+            installed_list: ScrollRegion::new(32.0, 4.0).with_frame(false),
             installed_items: Vec::new(),
-            updates_list: ScrollRegion::new(32.0, 4.0),
+            updates_list: ScrollRegion::new(32.0, 4.0).with_frame(false),
             updates_items: Vec::new(),
             updating: false,
             last_update_res: None,
@@ -329,167 +329,113 @@ pub fn view(
 ) -> PageContent {
     let mut final_pc = PageContent::new();
     let sec_w = 260.0f32;
-    let mut builder = PageLayoutBuilder::new(layout, cx, cy, cw, ch, sec_w).with_section_count(3);
+    let mut builder = PageLayoutBuilder::new(layout, cx, cy, cw, ch, sec_w).with_section_count(1);
 
-    // Section 1: Packages List
-    builder.add_section(&mut final_pc, "Packages", sec_focused.first().copied().unwrap_or(false), |sec| {
+    builder.add_section_spanned(&mut final_pc, "", 1, sec_focused.first().copied().unwrap_or(false), |sec| {
         let sec_w = sec.cw;
         if !state.loaded {
             sec.text("Loading package lists...", 12.0, 0.0, 12.0, TEXT_DIM);
-        } else {
-            // Tab header: Installed, Updates
-            let mut stack = sec.vstack(8.0);
-            let tab_h = 28.0;
-            let active_bg = [0.20, 0.40, 0.65, 0.4];
-            let inactive_bg = [0.10, 0.10, 0.16, 0.3];
-            let hover_bg = [0.20, 0.20, 0.25, 0.15];
-
-            let label1 = "Installed";
-            let label2 = "Updates";
-
-            stack.add_row(2, 8.0, tab_h, |ctx, i, x, w| {
-                if i == 0 {
-                    ctx.button(
-                        label1,
-                        x,
-                        ctx.ay(),
-                        w,
-                        tab_h,
-                        if state.active_tab == PackageTab::Installed { active_bg } else { inactive_bg },
-                        hover_bg,
-                        [0.90, 0.90, 0.95, 1.0],
-                        AppAction::Packages(PackagesMessage::SetTab(PackageTab::Installed)),
-                    );
-                } else {
-                    ctx.button(
-                        label2,
-                        x,
-                        ctx.ay(),
-                        w,
-                        tab_h,
-                        if state.active_tab == PackageTab::Updates { active_bg } else { inactive_bg },
-                        hover_bg,
-                        [0.90, 0.90, 0.95, 1.0],
-                        AppAction::Packages(PackagesMessage::SetTab(PackageTab::Updates)),
-                    );
-                }
-            });
-
-            stack.context.spacing(4.0);
-
-            // Search box
-            let search_w = sec_w - 24.0;
-            let search_h = 46.0;
-
-            state.search_box.set_row_rect(stack.context.left + 12.0, search_w);
-            stack.add_widget(&mut state.search_box, search_w, search_h, ctx);
-            stack.context.spacing(8.0);
-
-            // List area
-            let list_box_x = sec.left + 12.0;
-            let list_box_y = sec.ay();
-            let list_box_w = sec_w - 24.0;
-            let list_box_h = 360.0;
+            return;
+        }
 
-            let query = if state.search_box.editing {
-                state.search_box.edit_buffer.to_lowercase()
+        // ── Tabs (with counts), filter, compact update row ──
+        let mut stack = sec.vstack(8.0);
+        let tab_h = 28.0;
+        let active_bg = [0.20, 0.40, 0.65, 0.4];
+        let inactive_bg = [0.10, 0.10, 0.16, 0.3];
+        let hover_bg = [0.20, 0.20, 0.25, 0.15];
+
+        let label1 = format!("Installed ({})", state.installed.len());
+        let label2 = format!("Updates ({})", state.updates.len());
+
+        stack.add_row(2, 8.0, tab_h, |ctx, i, x, w| {
+            if i == 0 {
+                ctx.button(
+                    &label1,
+                    x,
+                    ctx.ay(),
+                    w,
+                    tab_h,
+                    if state.active_tab == PackageTab::Installed { active_bg } else { inactive_bg },
+                    hover_bg,
+                    [0.90, 0.90, 0.95, 1.0],
+                    AppAction::Packages(PackagesMessage::SetTab(PackageTab::Installed)),
+                );
             } else {
-                state.search_box.text.to_lowercase()
-            };
-
-            match state.active_tab {
-                PackageTab::Installed => {
-                    let filtered: Vec<&PackageInfo> = state.installed.iter()
-                        .filter(|p| p.name.to_lowercase().contains(&query) || p.version.to_lowercase().contains(&query))
-                        .collect();
-
-                    // Dissolved List (Phase 6v): scroll state + frame prims are app-owned.
-                    state.installed_list.set_rect(list_box_x, list_box_y, list_box_w, list_box_h);
-                    state.installed_list.update_bounds(filtered.len(), list_box_y, list_box_h);
-                    state.installed_list.push_prims(sec.pc);
-                    let item_h = state.installed_list.item_height;
-
-                    if state.installed_items.len() != filtered.len() {
-                        state.installed_items.clear();
-                        for _ in 0..filtered.len() {
-                            state.installed_items.push(InteractiveListItem::new(""));
-                        }
-                    }
+                ctx.button(
+                    &label2,
+                    x,
+                    ctx.ay(),
+                    w,
+                    tab_h,
+                    if state.active_tab == PackageTab::Updates { active_bg } else { inactive_bg },
+                    hover_bg,
+                    [0.90, 0.90, 0.95, 1.0],
+                    AppAction::Packages(PackagesMessage::SetTab(PackageTab::Updates)),
+                );
+            }
+        });
 
-                    sec.pc.push_clip_rect(list_box_x, list_box_y, list_box_w, list_box_h);
-                    for (idx, pkg) in filtered.iter().enumerate() {
-                        if let Some(draw_y) = state.installed_list.get_item_draw_y(idx, 4.0) {
-                            // Rows dispatch as extra roots (the dissolved list is no parent).
-                            let item = &mut state.installed_items[idx];
-                            item.title = pkg.name.clone();
-                            item.subtitle = Some(format!("Version: {}", pkg.version));
-                            item.selected = Some(&pkg.name) == state.selected_package.as_ref();
-                            render_widget(sec.pc, item, list_box_x + 24.0, draw_y, list_box_w - 44.0, item_h, ctx);
-                        }
-                    }
-                    sec.pc.pop_clip_rect();
+        stack.context.spacing(4.0);
 
-                    if filtered.is_empty() {
-                        sec.pc.text("No packages match the query", list_box_x + 16.0, list_box_y + 16.0, 12.0, TEXT_DIM);
-                    }
-                }
-                PackageTab::Updates => {
-                    let filtered: Vec<&UpdateInfo> = state.updates.iter()
-                        .filter(|p| p.name.to_lowercase().contains(&query))
-                        .collect();
-
-                    // Dissolved List (Phase 6v): scroll state + frame prims are app-owned.
-                    state.updates_list.set_rect(list_box_x, list_box_y, list_box_w, list_box_h);
-                    state.updates_list.update_bounds(filtered.len(), list_box_y, list_box_h);
-                    state.updates_list.push_prims(sec.pc);
-                    let item_h = state.updates_list.item_height;
-
-                    if state.updates_items.len() != filtered.len() {
-                        state.updates_items.clear();
-                        for _ in 0..filtered.len() {
-                            state.updates_items.push(InteractiveListItem::new(""));
-                        }
-                    }
+        let search_w = sec_w - 24.0;
+        let search_h = 46.0;
+        state.search_box.set_row_rect(stack.context.left + 12.0, search_w);
+        stack.add_widget(&mut state.search_box, search_w, search_h, ctx);
+        stack.context.spacing(4.0);
 
-                    sec.pc.push_clip_rect(list_box_x, list_box_y, list_box_w, list_box_h);
-                    for (idx, pkg) in filtered.iter().enumerate() {
-                        if let Some(draw_y) = state.updates_list.get_item_draw_y(idx, 4.0) {
-                            // Rows dispatch as extra roots (the dissolved list is no parent).
-                            let item = &mut state.updates_items[idx];
-                            item.title = pkg.name.clone();
-                            item.subtitle = Some(format!("{}  ->  {}", pkg.old_version, pkg.new_version));
-                            item.selected = Some(&pkg.name) == state.selected_package.as_ref();
-                            render_widget(sec.pc, item, list_box_x + 24.0, draw_y, list_box_w - 44.0, item_h, ctx);
-                        }
-                    }
-                    sec.pc.pop_clip_rect();
+        // Update System: compact button + status text on one row.
+        let status_line = if state.updating {
+            "Updating system...".to_string()
+        } else if state.updates.is_empty() {
+            "System is up to date".to_string()
+        } else {
+            format!("{} updates available", state.updates.len())
+        };
+        let status_color = if state.updating || !state.updates.is_empty() { ACCENT } else { TEXT_DIM };
+        let (btn_lbl, bg, hover) = if state.updating {
+            ("Updating...", [0.15, 0.15, 0.20, 1.0], [0.15, 0.15, 0.20, 1.0])
+        } else {
+            ("Update System", [0.13, 0.18, 0.14, 1.0], [0.25, 0.30, 0.26, 1.0])
+        };
+        stack.add_row(3, 8.0, 26.0, |c, i, x, w| {
+            if i == 0 {
+                c.button(btn_lbl, x, c.ay(), w, 26.0, bg, hover, [0.90, 0.90, 0.95, 1.0],
+                    AppAction::Packages(PackagesMessage::StartUpdate));
+            } else if i == 1 {
+                let y = c.ay();
+                c.pc.text(&status_line, x, y + 6.0, 12.0, status_color);
+            }
+        });
 
-                    if filtered.is_empty() {
-                        sec.pc.text("No updates match the query", list_box_x + 16.0, list_box_y + 16.0, 12.0, TEXT_DIM);
-                    }
+        if let Some(ref res) = state.last_update_res {
+            match res {
+                Ok(_) => stack.context.text("Last update succeeded", 12.0, 0.0, 12.0, [0.56, 0.83, 0.56, 1.0]),
+                Err(err) => {
+                    stack.context.text("Last update failed:", 12.0, 0.0, 12.0, RED);
+                    stack.context.text(err, 12.0, 0.0, 11.0, RED);
                 }
             }
-
-            sec.content_y += list_box_h;
         }
-    });
 
-    // Section 2: Package Details Info
-    builder.add_section(&mut final_pc, "Package Info", sec_focused.get(1).copied().unwrap_or(false), |sec1| {
+        // ── Selected package details ──
+        if state.loading_info || state.selected_package.is_some() {
+            section_divider(stack.context);
+        }
         if state.loading_info {
-            sec1.text("Loading package details...", 12.0, 0.0, 12.0, TEXT_DIM);
-        } else if let Some(ref pkg_name) = state.selected_package {
-            if let Some(ref info_raw) = state.selected_package_info {
-                let mut parsed = parse_package_info(info_raw);
+            stack.context.text("Loading package details...", 12.0, 0.0, 12.0, TEXT_DIM);
+        } else if let Some(pkg_name) = state.selected_package.clone() {
+            if let Some(info_raw) = state.selected_package_info.clone() {
+                let mut parsed = parse_package_info(&info_raw);
                 if parsed.name.is_empty() {
                     parsed.name = pkg_name.clone();
                 }
 
-                sec1.text(&parsed.name, 12.0, 0.0, 13.0, WHITE);
+                stack.context.text(&parsed.name, 12.0, 0.0, 14.0, [0.35, 0.65, 0.90, 1.0]);
 
                 let render_detail = |sub: &mut SectionContext<'_, PageContent>, key: &str, val: &str| {
                     sub.text(key, 12.0, 0.0, 11.0, TEXT_DIM);
-                    let val_start_x = 90.0f32;
+                    let val_start_x = 130.0f32;
                     let usable_w = sub.cw - val_start_x - 12.0;
                     let char_w = 6.0f32;
                     let max_chars = (usable_w / char_w).max(15.0) as usize;
@@ -500,29 +446,27 @@ pub fn view(
                     }
                 };
 
-                render_detail(sec1, "Version:", &parsed.version);
+                render_detail(stack.context, "Version:", &parsed.version);
                 if !parsed.size.is_empty() {
-                    render_detail(sec1, "Size:", &parsed.size);
+                    render_detail(stack.context, "Size:", &parsed.size);
                 }
                 if !parsed.licenses.is_empty() {
-                    render_detail(sec1, "Licenses:", &parsed.licenses);
+                    render_detail(stack.context, "Licenses:", &parsed.licenses);
                 }
                 if !parsed.website.is_empty() {
-                    render_detail(sec1, "Website:", &parsed.website);
+                    render_detail(stack.context, "Website:", &parsed.website);
                 }
                 if !parsed.packager.is_empty() {
-                    render_detail(sec1, "Packager:", &parsed.packager);
+                    render_detail(stack.context, "Packager:", &parsed.packager);
                 }
                 if !parsed.build_date.is_empty() {
-                    render_detail(sec1, "Build Date:", &parsed.build_date);
+                    render_detail(stack.context, "Build Date:", &parsed.build_date);
                 }
                 if !parsed.description.is_empty() {
-                    sec1.separator();
-                    render_detail(sec1, "Description:", &parsed.description);
+                    render_detail(stack.context, "Description:", &parsed.description);
                 }
                 if !parsed.required_by.is_empty() && parsed.required_by != "None" {
-                    sec1.separator();
-                    sec1.text("Required By:", 12.0, 0.0, 11.0, TEXT_DIM);
+                    stack.context.text("Required By:", 12.0, 0.0, 11.0, TEXT_DIM);
 
                     let reqs: Vec<&str> = parsed.required_by.split_whitespace().collect();
                     let cols_count = 3;
@@ -530,89 +474,128 @@ pub fn view(
                     let btn_h = 24.0;
 
                     for chunk in reqs.chunks(cols_count) {
-                        let btn_y = sec1.ay();
-                        let cols = sec1.row_layout(cols_count, gap);
+                        let btn_y = stack.context.ay();
+                        let cols = stack.context.row_layout(cols_count, gap);
                         for (i, &pkg) in chunk.iter().enumerate() {
                             if let Some(&(x, w)) = cols.get(i) {
                                 let action = AppAction::Packages(PackagesMessage::SelectAndScrollPackage(pkg.to_string()));
-                                sec1.button(pkg, x, btn_y, w, btn_h, TOGGLE_OFF, BTN_HOVER, TEXT_FG, action);
+                                stack.context.button(pkg, x, btn_y, w, btn_h, TOGGLE_OFF, BTN_HOVER, TEXT_FG, action);
                             }
                         }
                     }
                 }
                 if !parsed.commands.is_empty() {
-                    sec1.separator();
-                    render_detail(sec1, "Commands:", &parsed.commands);
+                    render_detail(stack.context, "Commands:", &parsed.commands);
                 }
 
                 if state.active_tab == PackageTab::Installed {
-                    let mut stack = sec1.vstack(8.0);
-                    let btn_h = 32.0;
-                    let (btn_lbl, bg, hover, action) = if state.uninstalling {
-                        ("Uninstalling...", TOGGLE_OFF, TOGGLE_OFF, AppAction::Packages(PackagesMessage::StartUninstall(pkg_name.clone())))
+                    stack.context.spacing(4.0);
+                    let (btn_lbl, bg, hover, text_col) = if state.uninstalling {
+                        ("Uninstalling...", TOGGLE_OFF, TOGGLE_OFF, TEXT_DIM)
                     } else {
-                        ("Uninstall Package", RED, BTN_HOVER, AppAction::Packages(PackagesMessage::StartUninstall(pkg_name.clone())))
+                        ("Uninstall", [0.25, 0.14, 0.14, 1.0], [0.40, 0.20, 0.20, 1.0], [0.95, 0.55, 0.55, 1.0])
                     };
-                    stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
-                        ctx.button(btn_lbl, x, ctx.ay(), w, btn_h, bg, hover, WHITE, action.clone());
+                    stack.add_row(3, 8.0, 26.0, |c, i, x, w| {
+                        if i == 0 {
+                            c.button(btn_lbl, x, c.ay(), w, 26.0, bg, hover, text_col,
+                                AppAction::Packages(PackagesMessage::StartUninstall(pkg_name.clone())));
+                        }
                     });
                 }
             } else {
-                sec1.text("No details available.", 12.0, 0.0, 12.0, TEXT_DIM);
+                stack.context.text("No details available.", 12.0, 0.0, 12.0, TEXT_DIM);
             }
-        } else {
-            sec1.text("Select a package to view details.", 12.0, 0.0, 12.0, TEXT_DIM);
         }
-    });
 
-    // Section 3: Update Actions / Status
-    builder.add_section(&mut final_pc, "System Update", sec_focused.get(2).copied().unwrap_or(false), |sec2| {
-        if !state.loaded {
-            sec2.text("Loading update status...", 12.0, 0.0, 12.0, TEXT_DIM);
+        section_divider(stack.context);
+
+        // ── List fills the rest of the page ──
+        let list_box_x = sec.left + 12.0;
+        let list_box_y = sec.ay();
+        let list_box_w = sec_w - 24.0;
+        let list_box_h = ((cy + ch) - 12.0 - list_box_y).max(120.0);
+
+        let query = if state.search_box.editing {
+            state.search_box.edit_buffer.to_lowercase()
         } else {
-            // Display summaries
-            sec2.text("Installed Packages:", 12.0, 0.0, 12.0, TEXT_DIM);
-            sec2.text(&format!("{}", state.installed.len()), 150.0, 0.0, 12.0, TEXT_FG);
-
-            sec2.text("Available Updates:", 12.0, 0.0, 12.0, TEXT_DIM);
-            let updates_color = if state.updates.is_empty() { TEXT_FG } else { ACCENT };
-            sec2.text(&format!("{}", state.updates.len()), 150.0, 0.0, 12.0, updates_color);
-
-            let status_lbl = if state.updating {
-                "Updating..."
-            } else if state.updates.is_empty() {
-                "System is up to date"
-            } else {
-                "Updates available"
-            };
-            sec2.text("Status:", 12.0, 0.0, 12.0, TEXT_DIM);
-            sec2.text(status_lbl, 150.0, 0.0, 12.0, if state.updating { ACCENT } else { TEXT_FG });
+            state.search_box.text.to_lowercase()
+        };
 
-            if let Some(ref res) = state.last_update_res {
-                match res {
-                    Ok(_) => {
-                        sec2.text("Last update succeeded!", 12.0, 0.0, 12.0, ACCENT);
+        match state.active_tab {
+            PackageTab::Installed => {
+                let filtered: Vec<&PackageInfo> = state.installed.iter()
+                    .filter(|p| p.name.to_lowercase().contains(&query) || p.version.to_lowercase().contains(&query))
+                    .collect();
+
+                // Dissolved List (Phase 6v): scroll state + frame prims are app-owned.
+                state.installed_list.set_rect(list_box_x, list_box_y, list_box_w, list_box_h);
+                state.installed_list.update_bounds(filtered.len(), list_box_y, list_box_h);
+                state.installed_list.push_prims(sec.pc);
+                let item_h = state.installed_list.item_height;
+
+                if state.installed_items.len() != filtered.len() {
+                    state.installed_items.clear();
+                    for _ in 0..filtered.len() {
+                        state.installed_items.push(InteractiveListItem::new(""));
                     }
-                    Err(err) => {
-                        sec2.text("Last update failed:", 12.0, 0.0, 12.0, RED);
-                        sec2.text(err, 12.0, 0.0, 11.0, RED);
+                }
+
+                sec.pc.push_clip_rect(list_box_x, list_box_y, list_box_w, list_box_h);
+                for (idx, pkg) in filtered.iter().enumerate() {
+                    if let Some(draw_y) = state.installed_list.get_item_draw_y(idx, 4.0) {
+                        // Rows dispatch as extra roots (the dissolved list is no parent).
+                        let item = &mut state.installed_items[idx];
+                        item.title = pkg.name.clone();
+                        item.subtitle = Some(format!("Version: {}", pkg.version));
+                        item.selected = Some(&pkg.name) == state.selected_package.as_ref();
+                        render_widget(sec.pc, item, list_box_x + 24.0, draw_y, list_box_w - 44.0, item_h, ctx);
                     }
                 }
+                sec.pc.pop_clip_rect();
+
+                if filtered.is_empty() {
+                    sec.pc.text("No packages match the query", list_box_x + 16.0, list_box_y + 16.0, 12.0, TEXT_DIM);
+                }
             }
+            PackageTab::Updates => {
+                let filtered: Vec<&UpdateInfo> = state.updates.iter()
+                    .filter(|p| p.name.to_lowercase().contains(&query))
+                    .collect();
 
-            let mut stack = sec2.vstack(8.0);
-            let btn_h = 32.0;
+                // Dissolved List (Phase 6v): scroll state + frame prims are app-owned.
+                state.updates_list.set_rect(list_box_x, list_box_y, list_box_w, list_box_h);
+                state.updates_list.update_bounds(filtered.len(), list_box_y, list_box_h);
+                state.updates_list.push_prims(sec.pc);
+                let item_h = state.updates_list.item_height;
 
-            let (btn_lbl, bg, hover, action) = if state.updating {
-                ("Updating...", TOGGLE_OFF, TOGGLE_OFF, AppAction::Packages(PackagesMessage::StartUpdate))
-            } else {
-                ("Update System", TOGGLE_ON, BTN_HOVER, AppAction::Packages(PackagesMessage::StartUpdate))
-            };
+                if state.updates_items.len() != filtered.len() {
+                    state.updates_items.clear();
+                    for _ in 0..filtered.len() {
+                        state.updates_items.push(InteractiveListItem::new(""));
+                    }
+                }
+
+                sec.pc.push_clip_rect(list_box_x, list_box_y, list_box_w, list_box_h);
+                for (idx, pkg) in filtered.iter().enumerate() {
+                    if let Some(draw_y) = state.updates_list.get_item_draw_y(idx, 4.0) {
+                        // Rows dispatch as extra roots (the dissolved list is no parent).
+                        let item = &mut state.updates_items[idx];
+                        item.title = pkg.name.clone();
+                        item.subtitle = Some(format!("{}  ->  {}", pkg.old_version, pkg.new_version));
+                        item.selected = Some(&pkg.name) == state.selected_package.as_ref();
+                        render_widget(sec.pc, item, list_box_x + 24.0, draw_y, list_box_w - 44.0, item_h, ctx);
+                    }
+                }
+                sec.pc.pop_clip_rect();
 
-            stack.add_row(1, 0.0, btn_h, |ctx, _, x, w| {
-                ctx.button(btn_lbl, x, ctx.ay(), w, btn_h, bg, hover, WHITE, action.clone());
-            });
+                if filtered.is_empty() {
+                    sec.pc.text("No updates match the query", list_box_x + 16.0, list_box_y + 16.0, 12.0, TEXT_DIM);
+                }
+            }
         }
+
+        // End the section so the well's bottom wall sits 12px below the list.
+        sec.content_y = list_box_y + list_box_h + 12.0 - (sec.padding() + 12.0);
     });
 
     final_pc
@@ -718,13 +701,9 @@ impl PackagesState {
 }
 
 impl crate::pages::AppPage for PackagesState {
-    // Sections: [Packages, Package Info, System Update]
+    // Sections: [the one well]
     fn section_widgets(&mut self) -> Vec<Vec<cce_ui::widget::WidgetId>> {
-        vec![
-            vec![self.search_box.id()],
-            Vec::new(),
-            Vec::new(),
-        ]
+        vec![vec![self.search_box.id()]]
     }
 
     fn view(