Saturday 13 February 2021

Vuetify and MDB

Both Vuetify and MDB implement the Material Design Design Language. Whereas Vuetify implements Material Design using the Vue JavaScript framework, MDB implements it atop the Bootstrap CSS framework. We're looking at a few specific terms there aren't we? We have JavaScript and CSS frameworks and Design Language - but what do we mean by those terms.

I covered the primary three JavaScript frameworks in my previous book, and there is no shortage of articles comparing and contrasting Angular, React and Vue (the three most popular JavaScript frameworks at the time of writing). A JavaScript framework provides a developer with a blueprint, and often concrete artefacts, to use when building an application. Rather than coding everything from the ground up - perhaps utilising functions from a JavaScript library - a JavaScript framework offers structure (the degree and rigidity of this structure depend upon how opinionated the framework is) that will then be decorated with the application's business logic.

JavaScript frameworks are a vast area of contention so I should note that I use VueJS the most because it's the one I use professionally. I prefer it because of familiarity and because it has the lowest adoption barrier - seemingly being the closest to VanillaJS. Again, their primary benefit is that they allow developers to hit the ground running in terms of how an application will be structured, especially those frameworks that are more opinionated. We've used the word "opinionated" a few times now - it is a term which is closely related to the friction developers find when developing applications. If the developer follows the framework designers' accepted application design, they feel less friction while developing the application. Should they attempt something outside those guidelines, and the framework be very opinionated, then they can find the going harder; they will feel more friction. The constraints of an opinionated framework can be comforting; depending upon the confidence of the developer. JavaScript frameworks do involve some measure of learning as well as obedience to the design dictates of their designers; the less opinionated the framework, the less deference is required to others' decisions, and the developer needs to have more confidence in their abilities. That is not to suggest that skilled developers don't use frameworks - just that they might have chosen their framework because it conforms with their preferred approach.

Similarly, CSS frameworks make the developer's life convenient, and they do that by removing an awful lot of the fear, uncertainty and dread at the start of a project. Initiating a project can be terrifying and might be analogous to an artist creating new work, being confronted with - and subsequently terrified of - the blank canvas. If you've been provided with a ready-made tranche of CSS, then a significant number of visual design and development decisions have already been made for you. While comforting, it is like being swaddled in a vast blanket and can be somewhat constricting. I can't be alone when I noted that many sites started to look like facsimiles of the Bootstrap site just after the framework's release.

This tendency to homogenisation is, to a degree, ameliorated by Bootstrap theming. MDB takes this theming to the next level by adding custom elements and components not ordinarily available within Bootstrap, excluding multiple external libraries.

Criticism of both CSS and JavaScript frameworks is rife and, to an extent, understandable. The constraints they provide, while offering countless boons to the developer, might explain their proliferation. Developers can be opinionated - how else might you interpret the continuing arguments over the relative benefits of Vim over Emacs. Personally, if I have to log into a Linux server, I generally use Nano, much to the disdain of friends who have spent the time to learn the minutiae of Vim or Vi. The criticism means that developers sometimes seek to break out of those confines while, in turn, constraining others within similar bonds of conformity by developing competing CSS or JavaScript frameworks. One has to appreciate such dedication. Developing a framework is a challenging and often thankless task - especially as, once birthed, they are likely to be exposed to a vast ecosystem of other frameworks, all competing for developer adoption.

Developers will be exposed to multiple CSS and JavaScript frameworks throughout their career - either by choice or imposed by their employer. As such, a new developer is left in a quandary about what to learn. The web fundamentals (HTML, CSS and JS) can sometimes be left behind in the scramble to learn the latest framework with the most-posted jobs - concentrating on learning the fundamentals provides a foundation where the developer can learn to appreciate the relative merits of a CSS or JavaScript framework. I once was asked to implement a CSS framework, which I will not name, which was very concrete and opinionated in its naming convention for the classes used. Those classes were the be-all and end-all of the framework and wholly dictated the appearance of elements in the UI. The developer could add class attributes to HTML elements to make them act in ways contrary to how they should by default, which left me feeling very uncomfortable.

That's not to say that developers should ignore innovations within the field, but discernment is required before jumping on to the latest bandwagon. Indeed, the new developer's primary focus should be the fundamentals of HTML, CSS and JS - in that order. Your first professional role, or independent study, will likely provide more than enough exposure to CSS and JavaScript frameworks.

Now that we're more aware of the frameworks lets look at Design Languages. Nate Baldwin suggests that if you have spent any time developing anything on the internet; you have either already created a Design Language of your own, or implemented someone else's. That includes creating an eBay listing or implementing a custom frame on your Facebook Profile. Baldwin's article goes into Design Languages' details. He notes that they are made up of many disparate elements in the same way that our written or spoken languages are. He also points out that, despite their ubiquity, the visual interfaces that Design Languages influence are remarkably complex mechanisms to glean and impart information. As such, we need to be conscious of their impact on our users and aware of their importance.

Being made up of many various elements, a Design Language is a tricky beast and worth studying. Even the name itself can be problematic, with designers calling them Design Languages or Design Systems - some front-end frameworks are even worthy of the name Design Language and cod;tas host a curated list of them. I've used three of the twenty-nine Design Languages listed during my career to date (at the time of writing). Still, of those three, I keep returning to Material Design - though I'm becoming more and more enamoured of IBM's Living Language. I should also note that I've also developed within the constraints of private, corporate, Design Languages for clients, some of which went so far as to have distinct and restricted corporate typefaces.

As an aside, I should also note that when I worked primarily on local government contracts, the predominant thematic colour was purple. After all, Purple was historically restricted to royalty and the elite due to the dye's original exorbitant costs. Thankfully I was no longer working in such a milieu when the UK Independence Party co-opted that particular colour. One can only imagine that the only solution to theming such sites today is to use the whole rainbow of colours represented on Wikipedia's list of United Kingdom political party meta attributes.

As a further aside, I spent some time thinking about political parties' colours in the UK. I wrote a blog post with, not my thoughts per se, but my findings, from the Wikipedia article linked above and display the political parties, sorted using their hue, saturation and lightness (HSL) values.

Working within a Design Language's strictures is similar, but not the same as working within a CSS or JavaScript framework's bindings. It is related in that working with a Design Language means that the overarching application has a consistent look (in the same way as working with a CSS framework) and feel (in the same way as working within a JavaScript framework). Further, introducing elements from other Design Languages is likely to present your users' to some discordance and lead to confusion in the same way as CSS and JavaScript frameworks don't often play well together.

That is not to say we should not seek to challenge our users by introducing innovation. But those challenges should be sprinkled sparingly through the application, rather than at every turn of the user. Using a Design Language, we help our users feel confident that their interaction will lead to expected results by allowing them to feel confident in the application's consistency. Further, a documented Design Language will allow other team members - should you enjoy work with others - feel as though they know how to progress with preliminary development before the input of a dedicated front-end developer. John Rhea discusses the introduction of dissonance to an application in his book Beginner Usability: A Novice's Guide to Zombie Proofing Your Website. He notes that users will be familiar with interacting with websites in specific ways, though interacting with previous websites. He also notes that to introduce dissonance, one must already be conscious of the rules implied by a Design Language.

But what is a Design Language? In the case of Material Design, Material is the metaphor which inspires the Design Language. Real-world objects act as the inspiration for user interface elements. Content is organised using cards, lists and sheets, navigations occurs when users interact with navigation draws and tabs; actions are initiated using buttons. Nearly all elements have a subtle rounding because, in nature, right angles are rare. I'm conscious that answering what a Design Language is is difficult to define; it is an aesthetic feeling towards an application and is made up of visual and conceptual standards. UXPin, the above quote's originator, says that a Design Language collects and standardises user interface components and patterns, a style guide, and some semantics documentation. Both UXPin and Gleb Kuznetsov note that a Design Language must relate to the brand's corporate identity. Should you be tasked with developing an application for a brand, you must examine their other assets - physical or internet-based. This examination will furnish you with a feeling about how your application should look, even if it's only related to any logos to be used or colour-schemes to implement.

We started this by examining what we mean by CSS frameworks, JavaScript frameworks and Design Languages; we'll now look at the relationship between MDB and Vuetify and Material Design. Both MDB and Vuetify implement the Material Design Language, using significantly different techniques. Up until the release of version 5, MDB also required the inclusion of the jQuery JavaScript library. The Bootstrap CSS framework itself required jQuery before version 5; now it only needs the Popper JavaScript library to enable proper positioning of tooltips and popover elements. MDB now has its own, dedicated, JavaScript library and no longer requires jQuery.

MDB adds Material Design concepts to the Bootstrap CSS framework along with a significant number of discrete, JavaScript-powered, user interface elements. Vuetify does pretty much the same but adds Material Design principles to the Vue JavaScript framework. Bootstrap and MDB's reliance on JavaScript means that both approaches aren't all that different, especially when considering the initial reliance Bootstrap had on jQuery. The primary differences are how Vuetify forces the developer to write the application. MDB decorates the HTML, whereas Vuetify replaces common HTML elements with its components. If building with HTML is analogous to building with Lego - which it can sometimes seem to be - then creating your first application with Vuetify is similar to building with a completely different construction toy such as Meccano.

Perhaps I might be accused of being an HTML purist, but using a v-container element is little different to using a div and adding a class of container - but it does seem to be a case of replacing HTML elements for the sake of it. Vuetify does have a sensibly naming convention so that you can mostly guess what is required next while building your application. A v-container likely needs to have a v-row within it, and that v-row is crying out for at least one v-col. You know, seeing as both Bootstrap and Vuetify both share a twelve-point grid system, that the v-col will have a cols attribute with a number between 1 and 12 as its value. But why bother with separate elements when adding a hierarchy of div elements with the classes of container, row and col-* will work just as well? It all smacks of overkill and using custom elements for the sake of it.

I guess that there's not a great deal to differentiate the two approaches to implementing Material Design. Vuetify has the closest affinity to those developers already used to working with Vue. In contrast, MDB is likely to feel the most natural for those developers used to traditional application development using so-called monolithic application structures, which don't take advantage of Single Page Application (SPA) architecture. I am conscious that I don't use SPAs professionally. To a greater or lesser degree, I'm not upset about not working with a SPA though, and I feel an affinity with Chris Ferdinandi when he notes that:

"Browsers are an amazing piece of technology. They give you so much for free, just baked right in."

"Single page apps break all that, and force you to recreate it with JavaScript."

Along with Vuetify, another prominent Vue Component Library implements the Material Design Language, Vue Material. Vue Material is closely related to, and partners with Creative Tim who develop Vue Material Kit. This situation mirrors MDB, as they also offer a paid-for product with more components.

Whatever your chosen CSS or JS framework or Design Language, the important thing is not to confuse your users too much while keeping your clients happy.

Saturday 6 February 2021

Political Spectrum

I'm doing some writing on design languages at the minute and, in an aside, I talked about working for UK local governments in a previous job. At that time, we used to be tasked with making the primary thematic colour purple because no political party used it. This usage was in the days before the rise of UKIP you see. Anyway, a purple cloth used to be reserved solely for royalty because of the die's exorbitant cost. Finding a list of the colours of all UK political parties on Wikipedia got me thinking about the amount of scripting I'm doing in the context of the 1000 miles in 2021 challenge. So I copied the table from Wikipedia and threw it into a Google Sheet. I converted the colour names into their HEX values then converted them to HSL so that I could sort them properly. Sorted first by Lightness, then Saturation and finally by Hue - I finally output an HTML link which I could display. The following is the sheet script I used to generate the links, and the result is above.

const RGBToHSL = (r,g,b) => {
  // Make r, g, and b fractions of 1
  r /= 255;
  g /= 255;
  b /= 255;
  // Find greatest and smallest channel values
  let cmin = Math.min(r,g,b),
      cmax = Math.max(r,g,b),
      delta = cmax - cmin,
      h = 0,
      s = 0,
      l = 0;
  // Calculate hue
  // No difference
  if (delta == 0){
    h = 0;
  }
  // Red is max
  else if (cmax == r) {
    h = ((g - b) / delta) % 6;
  }
  // Green is max
  else if (cmax == g) {
    h = (b - r) / delta + 2;
  }
  // Blue is max
  else {
    h = (r - g) / delta + 4;
  }
  h = Math.round(h * 60);

  // Make negative hues positive behind 360°
  if (h < 0){
    h += 360;
  }
  // Calculate lightness
  l = (cmax + cmin) / 2;
  // Calculate saturation
  s = delta == 0 ? 0 : delta / (1 - Math.abs(2 * l - 1));
  // Multiply l and s by 100
  s = +(s * 100).toFixed(1);
  l = +(l * 100).toFixed(1);
  return ["hsl(" + h + "," + s + "%," + l + "%)", h, s, l];
}

const hexToRGB = hex => hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b).substring(1).match(/.{2}/g).map(x => parseInt(x, 16))

const myFunction = () => {
  const returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1')
  const rowCount = returnSheet.getLastRow()
  for (let i = rowCount; i > 1; i--) {
    const rawValue = returnSheet.getRange('C' + i).getValue()
    const c = hexToRGB(rawValue)
    const hsl = RGBToHSL(...c)
    const url = returnSheet.getRange('B' + i).getRichTextValue().getLinkUrl()
    returnSheet.getRange('D' + i).setValue(rawValue.toUpperCase())
    returnSheet.getRange('E' + i).setValue(c[0])
    returnSheet.getRange('F' + i).setValue(c[1])
    returnSheet.getRange('G' + i).setValue(c[2])
    returnSheet.getRange('H' + i).setValue(hsl[0])
    returnSheet.getRange('I' + i).setValue(hsl[1])
    returnSheet.getRange('J' + i).setValue(hsl[2])
    returnSheet.getRange('K' + i).setValue(hsl[3])
    if(url){
      returnSheet.getRange('L' + i).setValue(`<a href="${url.replace('/meta/shortname', '').replace('Template:', '')}" target="_blank" style="background-color:${rawValue.toUpperCase().trim()};width:1px;" title="${returnSheet.getRange('B' + i).getValue()}"></a>`)
    }
  }
}