Index: uspace/app/nav/nav.c
===================================================================
--- uspace/app/nav/nav.c	(revision 9bed56559e0a699a63e60a3467b219c7f3617f2d)
+++ uspace/app/nav/nav.c	(revision 0e125698b867231c01d97e75fa522ce8e1321f8b)
@@ -263,10 +263,16 @@
 void navigator_switch_panel(navigator_t *navigator)
 {
+	errno_t rc;
+
 	if (panel_is_active(navigator->panel[0])) {
+		rc = panel_activate(navigator->panel[1]);
+		if (rc != EOK)
+			return;
 		panel_deactivate(navigator->panel[0]);
-		panel_activate(navigator->panel[1]);
 	} else {
+		rc = panel_activate(navigator->panel[0]);
+		if (rc != EOK)
+			return;
 		panel_deactivate(navigator->panel[1]);
-		panel_activate(navigator->panel[0]);
 	}
 }
Index: uspace/app/nav/panel.c
===================================================================
--- uspace/app/nav/panel.c	(revision 9bed56559e0a699a63e60a3467b219c7f3617f2d)
+++ uspace/app/nav/panel.c	(revision 0e125698b867231c01d97e75fa522ce8e1321f8b)
@@ -281,4 +281,7 @@
 				panel_page_down(panel);
 				break;
+			case KC_ENTER:
+				panel_open(panel, panel->cursor);
+				break;
 			default:
 				break;
@@ -344,9 +347,20 @@
  *
  * @param panel Panel
- */
-void panel_activate(panel_t *panel)
-{
+ *
+ * @return EOK on success or an error code
+ */
+errno_t panel_activate(panel_t *panel)
+{
+	errno_t rc;
+
+	if (panel->dir != NULL) {
+		rc = vfs_cwd_set(panel->dir);
+		if (rc != EOK)
+			return rc;
+	}
+
 	panel->active = true;
 	(void) panel_paint(panel);
+	return EOK;
 }
 
@@ -485,17 +499,43 @@
 	struct dirent *dirent;
 	vfs_stat_t finfo;
+	char newdir[256];
+	char *ndir = NULL;
 	errno_t rc;
 
-	dir = opendir(dirname);
-	if (dir == NULL)
-		return errno;
+	rc = vfs_cwd_set(dirname);
+	if (rc != EOK)
+		return rc;
+
+	rc = vfs_cwd_get(newdir, sizeof(newdir));
+	if (rc != EOK)
+		return rc;
+
+	ndir = str_dup(newdir);
+	if (ndir == NULL)
+		return ENOMEM;
+
+	dir = opendir(".");
+	if (dir == NULL) {
+		rc = errno;
+		goto error;
+	}
+
+	if (str_cmp(ndir, "/") != 0) {
+		/* Need to add a synthetic up-dir entry */
+		rc = panel_entry_append(panel, "..", 0, true);
+		if (rc != EOK)
+			goto error;
+	}
 
 	dirent = readdir(dir);
 	while (dirent != NULL) {
 		rc = vfs_stat_path(dirent->d_name, &finfo);
-		if (rc != EOK)
-			goto error;
-
-		rc = panel_entry_append(panel, dirent->d_name, 1,
+		if (rc != EOK) {
+			/* Possibly a stale entry */
+			dirent = readdir(dir);
+			continue;
+		}
+
+		rc = panel_entry_append(panel, dirent->d_name, finfo.size,
 		    finfo.is_directory);
 		if (rc != EOK)
@@ -515,7 +555,13 @@
 	panel->page = panel_first(panel);
 	panel->page_idx = 0;
+	free(panel->dir);
+	panel->dir = ndir;
 	return EOK;
 error:
-	closedir(dir);
+	(void) vfs_cwd_set(panel->dir);
+	if (ndir != NULL)
+		free(ndir);
+	if (dir != NULL)
+		closedir(dir);
 	return rc;
 }
@@ -870,4 +916,41 @@
 }
 
+/** Open panel entry.
+ *
+ * Perform Open action on a panel entry (e.g. switch to a subdirectory).
+ *
+ * @param panel Panel
+ * @param entry Panel entry
+ *
+ * @return EOK on success or an error code
+ */
+errno_t panel_open(panel_t *panel, panel_entry_t *entry)
+{
+	gfx_context_t *gc = ui_window_get_gc(panel->window);
+	char *dirname;
+	errno_t rc;
+
+	if (!entry->isdir)
+		return EOK;
+
+	dirname = str_dup(entry->name);
+	panel_clear_entries(panel);
+
+	rc = panel_read_dir(panel, dirname);
+	if (rc != EOK) {
+		free(dirname);
+		return rc;
+	}
+
+	rc = panel_paint(panel);
+	if (rc != EOK) {
+		free(dirname);
+		return rc;
+	}
+
+	free(dirname);
+	return gfx_update(gc);
+}
+
 /** @}
  */
Index: uspace/app/nav/panel.h
===================================================================
--- uspace/app/nav/panel.h	(revision 9bed56559e0a699a63e60a3467b219c7f3617f2d)
+++ uspace/app/nav/panel.h	(revision 0e125698b867231c01d97e75fa522ce8e1321f8b)
@@ -56,5 +56,5 @@
 extern unsigned panel_page_size(panel_t *);
 extern bool panel_is_active(panel_t *);
-extern void panel_activate(panel_t *);
+extern errno_t panel_activate(panel_t *);
 extern void panel_deactivate(panel_t *);
 extern errno_t panel_entry_append(panel_t *, const char *, uint64_t, bool);
@@ -75,4 +75,5 @@
 extern void panel_page_up(panel_t *);
 extern void panel_page_down(panel_t *);
+extern errno_t panel_open(panel_t *, panel_entry_t *);
 
 #endif
Index: uspace/app/nav/test/panel.c
===================================================================
--- uspace/app/nav/test/panel.c	(revision 9bed56559e0a699a63e60a3467b219c7f3617f2d)
+++ uspace/app/nav/test/panel.c	(revision 0e125698b867231c01d97e75fa522ce8e1321f8b)
@@ -143,5 +143,5 @@
 
 	event.type = KEY_PRESS;
-	event.key = KC_ENTER;
+	event.key = KC_ESCAPE;
 	event.mods = 0;
 	event.c = '\0';
@@ -158,5 +158,5 @@
 
 	event.type = KEY_PRESS;
-	event.key = KC_ENTER;
+	event.key = KC_ESCAPE;
 	event.mods = 0;
 	event.c = '\0';
@@ -277,5 +277,6 @@
 
 	PCUT_ASSERT_FALSE(panel_is_active(panel));
-	panel_activate(panel);
+	rc = panel_activate(panel);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 	PCUT_ASSERT_TRUE(panel_is_active(panel));
 
@@ -429,10 +430,14 @@
 	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
 
-	PCUT_ASSERT_INT_EQUALS(1, list_count(&panel->entries));
+	PCUT_ASSERT_INT_EQUALS(2, list_count(&panel->entries));
 
 	entry = panel_first(panel);
 	PCUT_ASSERT_NOT_NULL(entry);
+	PCUT_ASSERT_STR_EQUALS("..", entry->name);
+
+	entry = panel_next(entry);
+	PCUT_ASSERT_NOT_NULL(entry);
 	PCUT_ASSERT_STR_EQUALS("a", entry->name);
-	// PCUT_ASSERT_INT_EQUALS(1, entry->size);
+	PCUT_ASSERT_INT_EQUALS(1, entry->size);
 
 	panel_destroy(panel);
@@ -1136,3 +1141,77 @@
 }
 
+/** panel_open() opens a directory entry */
+PCUT_TEST(open)
+{
+	ui_t *ui;
+	ui_window_t *window;
+	ui_wnd_params_t params;
+	panel_t *panel;
+	panel_entry_t *entry;
+	char buf[L_tmpnam];
+	char *sdname;
+	char *p;
+	errno_t rc;
+	int rv;
+
+	rc = ui_create_disp(NULL, &ui);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	ui_wnd_params_init(&params);
+	params.caption = "Test";
+
+	rc = ui_window_create(ui, &params, &window);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	/* Create name for temporary directory */
+	p = tmpnam(buf);
+	PCUT_ASSERT_NOT_NULL(p);
+
+	/* Create temporary directory */
+	rc = vfs_link_path(p, KIND_DIRECTORY, NULL);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rv = asprintf(&sdname, "%s/%s", p, "a");
+	PCUT_ASSERT_TRUE(rv >= 0);
+
+	/* Create sub-directory */
+	rc = vfs_link_path(sdname, KIND_DIRECTORY, NULL);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = panel_create(window, true, &panel);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	rc = panel_read_dir(panel, p);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+	PCUT_ASSERT_STR_EQUALS(p, panel->dir);
+
+	PCUT_ASSERT_INT_EQUALS(2, list_count(&panel->entries));
+
+	entry = panel_first(panel);
+	PCUT_ASSERT_NOT_NULL(entry);
+	PCUT_ASSERT_STR_EQUALS("..", entry->name);
+
+	entry = panel_next(entry);
+	PCUT_ASSERT_NOT_NULL(entry);
+	PCUT_ASSERT_STR_EQUALS("a", entry->name);
+	PCUT_ASSERT_TRUE(entry->isdir);
+
+	rc = panel_open(panel, entry);
+	PCUT_ASSERT_ERRNO_VAL(EOK, rc);
+
+	PCUT_ASSERT_STR_EQUALS(sdname, panel->dir);
+
+	panel_destroy(panel);
+	ui_window_destroy(window);
+	ui_destroy(ui);
+
+	rv = remove(sdname);
+	PCUT_ASSERT_INT_EQUALS(0, rv);
+
+	rv = remove(p);
+	PCUT_ASSERT_INT_EQUALS(0, rv);
+
+	free(sdname);
+}
+
 PCUT_EXPORT(panel);
Index: uspace/app/nav/types/panel.h
===================================================================
--- uspace/app/nav/types/panel.h	(revision 9bed56559e0a699a63e60a3467b219c7f3617f2d)
+++ uspace/app/nav/types/panel.h	(revision 0e125698b867231c01d97e75fa522ce8e1321f8b)
@@ -103,4 +103,7 @@
 	/** @c true iff the panel is active */
 	bool active;
+
+	/** Directory */
+	char *dir;
 } panel_t;
 
