Department of Approvals
Reviving Windows Phone's Metro UI for an Engineering Firm
Department of Approvals is an engineering firm specializing in MEP Engineering and Energy Benchmarking services. They are looking for a flexible website that allows them to showcase their numerous projects across New York City. They approached me with their original website, and a clear outline in website architecture and the specifics of how they wanted it redone - in the style of Windows Phone's Metro UI system.
Branding
Design Brief
The responsive website was to combine static, brochure type information, as well as a dynamic "projects" section that showcases a variety of projects. The projects should be easily manageable and editable, and include images. In continuation to the old website, there should be an announcement banner at the top of the page for announcements. Department of Approvals provided clear input as to how the design should look, from sketches to reference videos, and together we coordinated a path forward.
Metro Design System
The first stage of this project was extensive research, screenshoting, and observing YouTube videos for motion design, until I felt comfortable working with this design language. Drawing from a slideshow that captures the Metro UI principles, I chose three key criteria to focus on: clean, content-focused, and alive in motion. It was such a joy to be able to revive such a beautiful, sleek, and functionalist design language.
Typography
Since Segoe UI, the original Metro UI font family, was owned by Windows and does not seem to have licensing options, I had to look at close alternatives. After consulting many online forums and comparing the two myself, I decided on Myriad Pro as a close alternative.
As for typographical hierarchy, I found old documents from wayback machine to guide my choices.
Color
The only use case in the website for a non-grayscale color would be the announcement banner, which I wanted to pop. I muted down the Metro UI blue for this purpose so that the overlaying white text would pop more.
Web Design
Animation
To create an app-like experience, the page transitions should be seamless. Here's the "Flip" animation that happens between the home page (menu) and subpage routes.
One layer deep from the home page, all transitions appear to be on the same surface: as users select different headers and subheaders, page content enters and exits the screen via a smooth "pushing" animation.
UI Elements
Since I couldn't find relevant references, I chose a flipbook-like design for the image gallery component, as well as a mirror image shadow which adds depth to the page.
Other UI elements are mainly seen on the admin side, but I wanted to get those right as well, from buttons, text inputs, to multiselect inputs.
Development
Technology Stack
I developed this website using Nuxt 3 and Tailwind CSS. For the backend, I used Google Firebase's Firestore, Authentication, and Storage. Having the entire backend on the cloud, in the same application, allows me to easily transfer the entire project to the client upon handoff.
Highlighted Features
Page Animations
Using three nested Nuxt Layouts, I could easily isolate and coordinate animation elements.
The first is a default layout
that acts as a simple wrapper containing the Navigation Bar and the Announcement bar.
The second and third are the header
and subheader
layouts that update internally based on the current route. Each layout is responsible for the animation of its elements.
Here's an example of the nested layouts for the path /services/fire-protection/sprinkler
:
In the example above, calculations for how the header (fire protection) and subheader (sprinkler) should appear are handled within the layouts, while the page transition animation is determined and assigned via a middleware function. By comparing the to
and from
routes, the middleware would assign a corresponding CSS pageTransition animation. Here's a peek into the layout logic for the header
layout.
<script setup lang="ts">
//layouts/header.vue
import { routes } from "/assets/routes.ts";
import { useWindowSize } from "@vueuse/core";
import { useElementSize } from "@vueuse/core";
const headers = ref(null);
const { width: windowW } = useWindowSize();
const { width: headersW } = useElementSize(headers);
const route = useRoute();
const page = route.path.split("/")[1];
const thisHeader = computed(() => {
return qsDecode(route.path.split("/")[2]);
});
const thisIndex = computed(() => {
return Array.from(Object.keys(routes[page])).indexOf(thisHeader.value);
});
const hasSubheader = function (route: string) {
return routes[page][route][0] !== undefined;
};
const headerOffset = computed(() => {
// retrieve header offset that shows the header option before and after the current/selected one.
// using windowW (window width) and elementW (element width) for calculations
});
</script>
<template>
<div class="w-screen overflow-y-auto" style="height: calc(100vh - 7.5rem)">
<nav
id="headers"
v-if="header !== 'admin'"
class="header flex whitespace-nowrap gap-6 mb-3 h-12 w-full overflow-y-visible [@media(max-width:767px)]:scrollbar-hide page-padding-x transition-all duration-300 ease"
:style="`transform: translateX(${headerOffset});`"
>
<nuxt-link
v-for="header in Array.from(Object.keys(routes[page]))"
:key="header"
:class="header === thisHeader ? 'opacity-100' : 'opacity-40'"
:to="
hasSubheader(header)
? `/${qsEncode(page)}/${qsEncode(header)}/${qsEncode(
routes[page][header][0],
)}`
: `/${qsEncode(page)}/${qsEncode(header)}`
"
>{{ header }}
</nuxt-link>
</nav>
<div id="header-slot" class="w-screen overflow-x-visible">
<slot></slot>
</div>
</div>
</template>
<style>
.header-left-enter-active,
.header-right-enter-active,
.header-left-leave-active,
.header-right-leave-active {
/* pageTransition animations (assigned if detected by middleware) */
}
</style>
Custom Content Management System (CMS)
Content that needs editing and updating include the announcement banner and projects. Projects will appear in pages where they have corresponding values assigned (e.g. a Brooklyn project will appear under /projects/by-location/brooklyn
). Project editing includes the ability to upload images.