diff --git a/Cargo.lock b/Cargo.lock
index 30b7e14..975bbba 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -61,6 +61,17 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
+[[package]]
+name = "bstr"
+version = "1.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
+dependencies = [
+ "memchr",
+ "regex-automata",
+ "serde",
+]
+
 [[package]]
 name = "bumpalo"
 version = "3.14.0"
@@ -679,6 +690,15 @@ dependencies = [
  "getrandom",
 ]
 
+[[package]]
+name = "normpath"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec60c60a693226186f5d6edf073232bfb6464ed97eb22cf3b01c1e8198fd97f5"
+dependencies = [
+ "windows-sys",
+]
+
 [[package]]
 name = "num_cpus"
 version = "1.16.0"
@@ -704,6 +724,17 @@ version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
+[[package]]
+name = "opener"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788"
+dependencies = [
+ "bstr",
+ "normpath",
+ "winapi",
+]
+
 [[package]]
 name = "pango"
 version = "0.17.10"
@@ -830,6 +861,12 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "regex-automata"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+
 [[package]]
 name = "relm4"
 version = "0.6.2"
@@ -971,6 +1008,7 @@ dependencies = [
 name = "sheet-organizer"
 version = "0.1.0"
 dependencies = [
+ "opener",
  "relm4",
  "relm4-components",
  "relm4-icons",
@@ -1294,6 +1332,72 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
 [[package]]
 name = "winnow"
 version = "0.5.34"
diff --git a/Cargo.toml b/Cargo.toml
index 94074b7..7bca355 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,4 +14,5 @@ relm4-components = "0.6.2"
 # Optional: icons
 relm4-icons = { version = "0.6.0", features = ["plus"] }
 
-walkdir = "2"
+walkdir = "2" # For traversing directories recursively
+opener = "0.6.1" # For opening files with the systems default application
diff --git a/src/main.rs b/src/main.rs
index 90af93c..80a769e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,6 +17,7 @@ struct AppModel {
 #[derive(Debug)]
 enum AppInput {
     McduInput(char),
+    SheetPressed(PathBuf),
 }
 
 #[relm4::component]
@@ -71,9 +72,14 @@ impl SimpleComponent for AppModel {
                 mcdu::McduOutput::ButtonPress(c) => AppInput::McduInput(c),
             });
 
-        let sheet_listing = SheetListingModel::builder()
-            .launch(path)
-            .forward(sender.input_sender(), |_response| todo!());
+        let sheet_listing =
+            SheetListingModel::builder()
+                .launch(path)
+                .forward(sender.input_sender(), |response| match response {
+                    sheet_listing::SheetPressedMessage::SheetPressed(path) => {
+                        AppInput::SheetPressed(path)
+                    }
+                });
 
         let model = AppModel {
             text: String::from("Text: "),
@@ -89,6 +95,7 @@ impl SimpleComponent for AppModel {
     fn update(&mut self, message: Self::Input, _sender: ComponentSender<Self>) {
         match message {
             AppInput::McduInput(c) => self.text.push(c),
+            AppInput::SheetPressed(sheet) => opener::open(sheet).unwrap(),
         }
     }
 }
diff --git a/src/sheet_listing.rs b/src/sheet_listing.rs
index f7facfa..fb0d56d 100644
--- a/src/sheet_listing.rs
+++ b/src/sheet_listing.rs
@@ -11,20 +11,31 @@ pub struct SheetModel {
     path: PathBuf,
 }
 
+#[derive(Debug)]
+pub enum SheetModelInput {
+    OnClicked,
+}
+
+#[derive(Debug)]
+pub enum SheetPressedMessage {
+    SheetPressed(PathBuf),
+}
+
 #[relm4::component(pub)]
 impl SimpleComponent for SheetModel {
     type Init = PathBuf;
-    type Input = ();
-    type Output = ();
+    type Input = SheetModelInput;
+    type Output = SheetPressedMessage;
 
     view! {
         #[root]
         gtk::Box {
             set_orientation: gtk::Orientation::Vertical,
-            gtk::Label {
+            append = &gtk::Button {
                 set_label: &format!("{}", model.path.file_name().unwrap().to_string_lossy()),
                 set_halign: gtk::Align::Start,
                 set_margin_all: 10,
+                connect_clicked[sender] => move |_| sender.input(SheetModelInput::OnClicked),
             }
         }
     }
@@ -32,21 +43,31 @@ impl SimpleComponent for SheetModel {
     fn init(
         path: Self::Init,
         root: &Self::Root,
-        _sender: ComponentSender<Self>,
+        sender: ComponentSender<Self>,
     ) -> ComponentParts<Self> {
         let model = SheetModel { path };
         let widgets = view_output!();
         ComponentParts { model, widgets }
     }
+
+    fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
+        match message {
+            SheetModelInput::OnClicked => sender
+                .output(SheetPressedMessage::SheetPressed(self.path.clone()))
+                .unwrap(),
+        }
+    }
 }
 
-pub struct SheetListingModel;
+pub struct SheetListingModel {
+    _sheet_models: Vec<Controller<SheetModel>>,
+}
 
 #[relm4::component(pub)]
 impl SimpleComponent for SheetListingModel {
     type Init = PathBuf;
     type Input = ();
-    type Output = ();
+    type Output = SheetPressedMessage;
 
     view! {
         #[root]
@@ -58,8 +79,10 @@ impl SimpleComponent for SheetListingModel {
     fn init(
         dir: Self::Init,
         root: &Self::Root,
-        _sender: ComponentSender<Self>,
+        sender: ComponentSender<Self>,
     ) -> ComponentParts<Self> {
+        let mut sheet_models = Vec::new();
+
         for entry in WalkDir::new(dir)
             .into_iter()
             .filter_map(|e| e.ok())
@@ -71,11 +94,16 @@ impl SimpleComponent for SheetListingModel {
                     .unwrap_or(false)
             })
         {
-            let sheet_model = SheetModel::builder().launch(entry);
+            let sheet_model = SheetModel::builder()
+                .launch(entry)
+                .forward(sender.output_sender(), |m| m);
             root.append(sheet_model.widget());
+            sheet_models.push(sheet_model);
         }
 
-        let model = SheetListingModel;
+        let model = SheetListingModel {
+            _sheet_models: sheet_models,
+        };
         let widgets = view_output!();
         ComponentParts { model, widgets }
     }