Back to Blog

Build a Note Viewer with Side Panel in egui | Learn egui in Neovim Ep 9

Sandy LaneSandy Lane

Video: Build a Note Viewer with Side Panel in egui | Learn egui in Neovim Ep 9 by Taught by Celeste AI - AI Coding Coach

Watch full page →

Build a Note Viewer with Side Panel in egui

This tutorial demonstrates how to create a simple note viewer app using egui's layout system. By combining a fixed sidebar with a central content panel, users can select note titles on the left and view their content on the right, creating an intuitive two-panel interface.

Code

use eframe::egui::{CentralPanel, SidePanel, SelectableLabel, Ui};

struct Note {
  title: String,
  content: String,
}

struct MyApp {
  notes: Vec<Note>,
  selected: Option<usize>,
}

impl Default for MyApp {
  fn default() -> Self {
    Self {
      notes: vec![
        Note {
          title: "Shopping List".to_owned(),
          content: "Milk\nEggs\nBread".to_owned(),
        },
        Note {
          title: "Meeting Notes".to_owned(),
          content: "Discuss project timeline\nAssign tasks".to_owned(),
        },
        Note {
          title: "Ideas".to_owned(),
          content: "Build a note viewer\nLearn egui".to_owned(),
        },
      ],
      selected: Some(0),
    }
  }
}

impl eframe::App for MyApp {
  fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
    // Left sidebar with fixed minimum width
    SidePanel::left("side_panel")
      .min_width(150.0)
      .show(ctx, |ui| {
        ui.heading("Notes");
        for (i, note) in self.notes.iter().enumerate() {
          // selectable_label highlights the selected note and makes it clickable
          if ui.selectable_label(self.selected == Some(i), ¬e.title).clicked() {
            self.selected = Some(i);
          }
        }
      });

    // Central panel fills remaining space, showing selected note content
    CentralPanel::default().show(ctx, |ui| {
      if let Some(selected) = self.selected {
        ui.heading(&self.notes[selected].title);
        ui.separator();
        ui.label(&self.notes[selected].content);
      } else {
        ui.label("Select a note from the sidebar");
      }
    });
  }
}

Key Points

  • Use SidePanel::left() with min_width() to create a fixed sidebar area.
  • CentralPanel::default() automatically fills the remaining window space for main content.
  • ui.selectable_label(selected, text) creates clickable, highlightable list items for navigation.
  • Store notes in a Vec of structs to manage data-driven UI content efficiently.
  • The two-panel layout pattern improves usability by separating navigation from content display.