+++
date = "2021-04-30T08:28:01+00:00"
publishdate = "2023-12-29T07:08:55+00:00"
title = "Site Updates: Navigation"
slug = "site-updates-navigation"
author = "Thedro"
tags = ["webdev"]
type = "posts"
summary = "Time has granted a small reprieve to work on the greatest pain point of my personal website --- the navigation bar."
draft = ""
syntax = "1"
toc = ""
updated = ""
+++
{{< image source="/images/site-updates-navigation.png" title="Updated navigation bar" >}}
Updated navigation bar {{< /image >}}
Time has granted a small reprieve to work on the greatest pain point of my
personal website --- the navigation bar. Due to sheer laziness, the navigation
bar was initially implemented as three separate bars for each of the main views
(tablet, phone, and desktop devices). This created unnecessary friction when
adding new items. In the long term, the goal of integrating more programs into
the website will require a certain consistency and so the navigation bar must be
unified across all views.
## Improvements
My website is glued together with {{< sidenote mark="`PHP`" set="left" >}} Make of
that what you will. [`PHP`](https://www.php.net/) is probably _the_ most hated
programming language. {{< /sidenote >}} on the back--end. You'll often hear that
`PHP` has native {{< sidenote mark="templating" set="right" >}} Eventually the
navigation components may be moved into a [Go](https://golang.org/) `HTML`
template, and generated statically by [Hugo](https://gohugo.io/).
{{< /sidenote >}} abilities and that is true. To solve my problem of multiple
navigation bars, a templating system is used to create scoped components using
[null coalescing operators](https://en.wikipedia.org/wiki/Null_coalescing_operator)
to set the defaults. This bespoke component `navigator.link` describes a
navigation link. Three parts receive or pass data: the attributes, the content,
and optionally, a faux return clause.
```html {options="hl_lines=2-6 8-11 14"}
```
Since this component is described in a file, it is cascaded anywhere using
`require`.
```html {options="hl_lines=3-7"}
```
In frameworks like [Laravel,](https://github.com/laravel/laravel) this
templating method can take on a more
{{< sidenote mark="abstracted" set="right" >}} You know the saying: As clean as
a whistle. Corporate types would rather the code below than the code above.
{{< /sidenote >}} form where components may contain scoped `CSS` or `JavaScript`
that can be "extracted" into one final payload. Laravel uses
[Blade](https://laravel.com/docs/8.x/blade) syntax for templating.
```php {options="hl_lines=22-24"}
@component ('components.navigator')
@slot ('left')
@include ('navigator.partials.menu')
@include ('navigator.partials.logo')
@include ('navigator.partials.header')
@endslot
@slot ('middle')
@include ('navigator.partials.title')
@endslot
@slot ('right')
@include ('navigator.partials.search')
@include ('navigator.partials.list')
@include ('navigator.partials.user')
@include ('navigator.partials.options')
@endslot
@endcomponent
@component ('components.context-menu', ['extract' => 'style']) @endcomponent
@component ('components.context-overlay', ['extract' => 'style']) @endcomponent
```
Templates can also be nested indefinitely. Here's the unified context menu
component that contains nested `HTML` elements inside the `label` that is
stacked or cascaded in different places around the website.
```php {options="hl_lines=5-8"}
More
insert;
require views('components', 'context.menu');
?>
```
You'll notice that namespacing could become an issue, particularly for code
below the fold, and ideally data would be passed as
{{< sidenote mark="arguments" set="right" >}} In PHP version `8` one could
simplify and structure view code further with
[named arguments](https://stitcher.io/blog/php-8-named-arguments) and
[other niceties](https://stitcher.io/blog/php-in-2021#the-language).
{{< /sidenote >}} to the `views` function, but this somewhat `CSS` _like_
behavior is preferred for duplicating components of a similar type quickly.
{{< image source="/images/site-updates-navigation-context-menu.png" title="Basic context menu component" >}}
Basic context menu component {{< /image >}}
## Goals
More interesting tasks are on my to--do list and may be completed if the time
allows.
### Comprehensive Dark and Light Mode
The dark mode on the site isn't implemented all that well. One of my goals is to
implement comprehensive dark mode features. In reality `CSS` is the only
necessity, but adding some of the minor features may prove useful. One such
feature involves situations where light and dark mode changes apply to all open
tabs of the site. The most comprehensive guide on implementing dark mode that
I've come across is
[written in this blog post.](https://www.kooslooijesteijn.net/blog/add-dark-mode-to-website)
### Search Engine
The idea of a
[vertical search engine](https://en.wikipedia.org/wiki/Vertical_search) where
the search scope is limited to a specific set of curated sites looks promising.
Here's to hoping somebody makes a nice and
{{< sidenote mark="simple" set="left" >}} [Go](https://golang.org/) would be a
good language for writing a search engine. {{< /sidenote >}} vertical search
engine that is easy to integrate into a blog, or maybe I'll make my own. Lately,
I've been playing around with building a search engine from scratch for
something else that I'm interested in personally.
{{< video poster="/images/product-search-engine.png" source="/videos/product-search-engine.mp4" options="loop muted" width="1400" >}}
Searching through a small index in a personal work in progress application
{{< /video >}}
## Deployment
The deployment situation for the website is looking up. The `CI/CD` (Continuous
Integration and Deployment) situation, previously
[Drone,](https://github.com/drone/drone) was replaced with
[NixOS](https://github.com/NixOS) and now the website deploys instantly. The
deployment logic lives on the server itself. The development, staging, and
production environments are setup and activated with a simple `NixOS` module.
```nix
{
services.thedroneely.enable = true;
services.thedroneely.development.enable = true;
services.thedroneely.staging.enable = true;
services.thedroneely.production.enable = true;
}
```