DEV Community

Tomasz Wegrzanowski
Tomasz Wegrzanowski

Posted on • Updated on

Electron Adventures: Episode 25: Orthodox File Manager Styling

We want to build something along the lines of an "Orthodox File Manager".

Browsers default to mouse interfaces, while file managers need to work with just keyboard, and have a lot of UI patterns that don't match what typical websites or webapps.

So we' need to implement this functionality yourselves.

Orthodox File Manager UI

Let's do a simple interface with the following features, implementing highly simplified "Orthodox File Manager" interface:

  • two panels, switching between them with TAB
  • each panel is a list of files, UP and DOWN arrow move between them
  • any number of files can be selected with SPACE
  • various Fn keys popup various modals to perform common actions (on either selected files, or currently focused file if none are selected on given panel)
  • each panel remembers which file was focused, but focused file in inactive file is not indicated

But before we even get there, let do just styling with completely static data, similar to how we created the terminal app!

Data

I took static data from Cat Ipsum.

Header and footer are both placeholders.

Here's index.html:

<!DOCTYPE html>
<html>
  <head>
    <link href="app.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <div class="ui">
      <header>
        File Manager
      </header>
      <div class="panel panel-left active">
        <div class="file selected">Cat.js</div>
        <div class="file selected">ipsum.js</div>
        <div class="file">dolor.js</div>
        <div class="file selected">sit.js</div>
        <div class="file selected">amet.js</div>
        <div class="file focused">walk.js</div>
        <div class="file">on.js</div>
        <div class="file">keyboard.js</div>
        <div class="file">hide.js</div>
        <div class="file">when.js</div>
        <div class="file">guests.js</div>
        <div class="file">come.js</div>
        <div class="file">over.js</div>
        <div class="file">play.js</div>
        <div class="file">with.js</div>
        <div class="file">twist.js</div>
        <div class="file">ties.js</div>
      </div>
      <div class="panel panel-right">
        <div class="file">Ask.png</div>
        <div class="file">to.png</div>
        <div class="file focused">be.png</div>
        <div class="file">pet.png</div>
        <div class="file selected">then.png</div>
        <div class="file selected">attack.png</div>
        <div class="file selected">owners.png</div>
        <div class="file selected">hand.png</div>
        <div class="file">need.png</div>
        <div class="file">to.png</div>
        <div class="file">chase.png</div>
        <div class="file">tail.png</div>
      </div>
      <footer>
        <button>F1 Help</button>
        <button>F2 Menu</button>
        <button>F3 View</button>
        <button>F4 Edit</button>
        <button>F5 Copy</button>
        <button>F6 Move</button>
        <button>F7 Mkdir</button>
        <button>F8 Delete</button>
        <button>F10 Quit</button>
      </footer>
    </div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

It should be fairly self explanatory:

  • we have 4 areas: header, panel-left, panel-right, footer
  • each panel contains a lot of file items
  • some file items can selected or focused or both
  • only one of the panels will be active at a time

Setting up basic styling

Terminals are traditionally white-on-black. File managers are traditionally white-on-blue. I did not make the rules.

body {
  background-color: #226;
  color: #fff;
  font-family: monospace;
  margin: 0;
  font-size: 16px;
}
Enter fullscreen mode Exit fullscreen mode

Setting up grid

It's very easy to do this with display: grid:

.ui {
  width: 100vw;
  height: 100vh;
  display: grid;
  grid-template-areas:
    "header header"
    "panel-left panel-right"
    "footer footer";
  grid-template-columns: 1fr 1fr;
  grid-template-rows: auto 1fr auto;
}
.ui header {
  grid-area: header;
}
.ui .panel-left {
  grid-area: panel-left;
}
.ui .panel-right {
  grid-area: panel-right;
}
.ui footer {
  grid-area: footer;
}
Enter fullscreen mode Exit fullscreen mode

Setting up item styling

These are some reasonable colors to indicate selected and focused states. Additionally selected files are bolded, something terminal-based file managers don't normally do.

.ui .panel {
  background: #338;
  margin: 4px;
}
.panel .file.selected {
  color: #ff2;
  font-weight: bold;
}
.panel.active .file.focused {
  background-color: #66b;
}
Enter fullscreen mode Exit fullscreen mode

Styling header and footer

So far in this series I haven't used any CSS resets, so button needs a bunch of inherit rules. Most of the time I just nuke the whole CSS before starting, so then we wouldn't need any such rules:

header {
  font-size: 24px;
  margin: 4px;
}
.ui footer {
  text-align: center;
}
button {
  font-family: inherit;
  font-size: inherit;
  background-color: #66b;
  color: inherit;
}
Enter fullscreen mode Exit fullscreen mode

How much should we follow tradition?

Orthodox File Managers come from terminal era. I think the basic concept of keyboard-controlled two-panel UI is still great, but some of their design decisions are based on limitations of terminal UIs.

The most obvious question to ask is if we want to use monospace font or not. Pretty much no non-terminal programs do that, and nobody minds. Even text editors like VSCode use regular sans font for their file management.

There's a long list of such questions we could have.

We might explore some of them in the future.

Results

Here's the results:

Episode 25 Screenshot

As usual, all the code for the episode is here.

Discussion (0)