Tag: System

Using Your Own Design System with KendoReact Components

Maybe you’ve already heard of (or even worked with!) KendoReact. It’s popped up in some of my day-to-day conversations, especially those about working with design systems and React. You could think of it as a component library like Bootstrap or Material Design, except the components in KendoReact are far more robust. These are interactive, state-driven components ready to start building full-blown UI’s right out of the gate (not to mention, if you want to use Bootstrap as the theme, you absolutely can).

Whenever you’re thinking about using a UI library, you need to think about the styling capabilities. Are you able to really express your brand with these? Were they meant to be styled? What is the styling experience going to be like?

Fortunately, KendoReact really makes styling a citizen of the entire UI library.

KendoReact is a collection of UI components for building sites. It’s a pretty massive one. Over 80 by my count, and that doesn’t include the child components of heavy lifters like the <Grid /> family.

Here’s one, the <DropDownList />, and just using the default theme (even that is optional):

If I want to style this, I don’t need any special proprietary skills, I can just use CSS. Here’s me forcing a whole new look onto it with different colors and fonts, with just some simple CSS:

But hey, maybe you want to do something a bit more systematized than cowboying some random override CSS. I don’t blame you. Good news: KendoReact themes are Sass-powered. So you can control a lot of the colorization and styling just by changing a few Sass variables.

They have a whole theme builder you can use right on their site that spits out exactly what you need. Say you want to start from their base theme and go from there, select the Default theme:

Then you can play with all the colors in the UI to your liking. Here’s me poking at a theme with some CSS-Tricks colors.

I can download that from the site which will give me the variables as a SCSS file that I can apply before the default theme in my build (there is a great tutorial covering how to do that over on the Telerik blog). Plus, it gives me the whole dang CSS file of the theme if I want to use it that way, which is simple and quick. Here’s me using their conversational chat widget with that theme:

Again, I can start with Bootstrap, I can start with Material, I can start with their default theme, or I can start from scratch. Styling is totally up to me. Each theme has its perks and, as you might expect, are super flexible as far as configuring colors, fonts, and other design elements.

If you really get into this, of course you’ll be consulting their docs and finding your way around there (it’s nice to know they have really comprehensive docs). It’s all pretty straightforward though, you’ll do great! If you need to get going building out a state-driven interactive interface quickly without sacrificing any customizability or power, you’ll find KendoReact is your friend.


The post Using Your Own Design System with KendoReact Components appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , ,

Setting up and Customizing the Ant Design System in a Nuxt App

I don’t typically work with UI libraries because they can be cumbersome and hard to override, which can contribute to a bloated. However, Ant Design has recently gained some some of my affection because it’s easy to use, has extensible defaults, and features a delicate design.

Nuxt and Ant Design work well together, in part because of Nuxt’s code-splitting and tree-shaking abilities, not to mention Nuxt’s new static target deployment option. I can serve an app using Ant Design with great performance scores.

Combining the two was a little tricky and there isn’t a lot in the way of documentation for how to do it, so what follows are the steps you need to set it up. Let’s get started!

Install Ant.design 

The first step is installing the ant-design-vue package, along with Less.js and less-loader, which we will need to create our Less variables:

yarn add ant-design-vue less less-loader # or npm i ant-design-vue less less-loader

Now lets tell Nuxt to use it globally via a plugin. We’ll create a file called antd-ui.js:

import Vue from 'vue' import Antd from 'ant-design-vue/lib'  Vue.use(Antd)

You may notice that unlike the process outlined in the Ant Design getting started guide, we are not importing the global CSS file they mention. That’s because we’re going to manually import the base variable Less file instead so that we can override it. 

We have a few things to do in our nuxt.config.js file. First, let’s register the plugin we just made:

plugins: ["@/plugins/antd-ui"],

Next, we’re going to let webpack know we’d like to build Less:

build: {    loaders: {      less: {        lessOptions: {          javascriptEnabled: true,        },     },   }, }

Finally, we need to create a global stylesheet for our variables that imports Ant Design’s defaults as well as our overrides:

css: [   "~/assets/variables.less" ],

We can see that this file exists in a /assets folder, so let’s make it. We’ll create a file in there called variables.less, and import Ant Design’s Less variables:

@import '~ant-design-vue/dist/antd.less';

Below this line, there are myriad variables you can override. This is just a sampling. The rest of the variables are here, and you’ll need to include them by their @ and can change it to whatever you wish:

@primary-color: #1890ff; // primary color for all components @link-color: #1890ff; // link color @success-color: #52c41a; // success state color @warning-color: #faad14; // warning state color @error-color: #f5222d; // error state color @font-size-base: 14px; // major text font size @heading-color: rgba(0, 0, 0, 0.85); // heading text color @text-color: rgba(0, 0, 0, 0.65); // major text color @text-color-secondary: rgba(0, 0, 0, 0.45); // secondary text color @disabled-color: rgba(0, 0, 0, 0.25); // disable state color @border-radius-base: 4px; // major border radius @border-color-base: #d9d9d9; // major border color @box-shadow-base: 0 2px 8px rgba(0, 0, 0, 0.15); // major shadow for layers

We’re good to go! There’s no need to import what we need into every component because Nuxt will now take care of that. If you’d like to override very specific styles not included in the variables, you can find the associative classes and override them in your layouts/default.vue file as well.

Ant.design and Nuxt allow you a great framework for building apps very quickly and with ease. Enjoy!


The post Setting up and Customizing the Ant Design System in a Nuxt App appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , , ,
[Top]

Designing a JavaScript Plugin System

WordPress has plugins. jQuery has plugins. Gatsby, Eleventy, and Vue do, too.

Plugins are a common feature of libraries and frameworks, and for a good reason: they allow developers to add functionality, in a safe, scalable way. This makes the core project more valuable, and it builds a community — all without creating an additional maintenance burden. What a great deal!

So how do you go about building a plugin system? Let’s answer that question by building one of our own, in JavaScript.

I’m using the word “plugin” but these things are sometimes called other names, like “extensions,” “add-ons,” or “modules.” Whatever you call them, the concept (and benefit) is the same.

Let’s build a plugin system

Let’s start with an example project called BetaCalc. The goal for BetaCalc is to be a minimalist JavaScript calculator that other developers can add “buttons” to. Here’s some basic code to get us started:

// The Calculator const betaCalc = {   currentValue: 0,      setValue(newValue) {     this.currentValue = newValue;     console.log(this.currentValue);   },      plus(addend) {     this.setValue(this.currentValue + addend);   },      minus(subtrahend) {     this.setValue(this.currentValue - subtrahend);   } }; 
 // Using the calculator betaCalc.setValue(3); // => 3 betaCalc.plus(3);     // => 6 betaCalc.minus(2);    // => 4

We’re defining our calculator as an object-literal to keep things simple. The calculator works by printing its result via console.log.

Functionality is really limited right now. We have a setValue method, which takes a number and displays it on the “screen.” We also have plus and minus methods, which will perform an operation on the currently displayed value.

It’s time to add more functionality. Let’s start by creating a plugin system.

The world’s smallest plugin system

We’ll start by creating a register method that other developers can use to register a plugin with BetaCalc. The job of this method is simple: take the external plugin, grab its exec function, and attach it to our calculator as a new method:

// The Calculator const betaCalc = {   // ...other calculator code up here 
   register(plugin) {     const { name, exec } = plugin;     this[name] = exec;   } };

And here’s an example plugin, which gives our calculator a “squared” button:

// Define the plugin const squaredPlugin = {   name: 'squared',   exec: function() {     this.setValue(this.currentValue * this.currentValue)   } }; 
 // Register the plugin betaCalc.register(squaredPlugin);

In many plugin systems, it’s common for plugins to have two parts:

  1. Code to be executed
  2. Metadata (like a name, description, version number, dependencies, etc.)

In our plugin, the exec function contains our code, and the name is our metadata. When the plugin is registered, the exec function is attached directly to our betaCalc object as a method, giving it access to BetaCalc’s this.

So now, BetaCalc has a new “squared” button, which can be called directly:

betaCalc.setValue(3); // => 3 betaCalc.plus(2);     // => 5 betaCalc.squared();   // => 25 betaCalc.squared();   // => 625

There’s a lot to like about this system. The plugin is a simple object-literal that can be passed into our function. This means that plugins can be downloaded via npm and imported as ES6 modules. Easy distribution is super important!

But our system has a few flaws.

By giving plugins access to BetaCalc’s this, they get read/write access to all of BetaCalc’s code. While this is useful for getting and setting the currentValue, it’s also dangerous. If a plugin was to redefine an internal function (like setValue), it could produce unexpected results for BetaCalc and other plugins. This violates the open-closed principle, which states that a software entity should be open for extension but closed for modification.

Also, the “squared” function works by producing side effects. That’s not uncommon in JavaScript, but it doesn’t feel great — especially when other plugins could be in there messing with the same internal state. A more functional approach would go a long way toward making our system safer and more predictable.

A better plugin architecture

Let’s take another pass at a better plugin architecture. This next example changes both the calculator and its plugin API:

// The Calculator const betaCalc = {   currentValue: 0,      setValue(value) {     this.currentValue = value;     console.log(this.currentValue);   },     core: {     'plus': (currentVal, addend) => currentVal + addend,     'minus': (currentVal, subtrahend) => currentVal - subtrahend   }, 
   plugins: {},     
   press(buttonName, newVal) {     const func = this.core[buttonName] || this.plugins[buttonName];     this.setValue(func(this.currentValue, newVal));   }, 
   register(plugin) {     const { name, exec } = plugin;     this.plugins[name] = exec;   } };    // Our Plugin const squaredPlugin = {    name: 'squared',   exec: function(currentValue) {     return currentValue * currentValue;   } }; 
 betaCalc.register(squaredPlugin); 
 // Using the calculator betaCalc.setValue(3);      // => 3 betaCalc.press('plus', 2); // => 5 betaCalc.press('squared'); // => 25 betaCalc.press('squared'); // => 625

We’ve got a few notable changes here.

First, we’ve separated the plugins from “core” calculator methods (like plus and minus), by putting them in their own plugins object. Storing our plugins in a plugin object makes our system safer. Now plugins accessing this can’t see the BetaCalc properties — they can only see properties of betaCalc.plugins.

Second, we’ve implemented a press method, which looks up the button’s function by name and then calls it. Now when we call a plugin’s exec function, we pass it the current calculator value (currentValue), and we expect it to return the new calculator value.

Essentially, this new press method converts all of our calculator buttons into pure functions. They take a value, perform an operation, and return the result. This has a lot of benefits:

  • It simplifies the API.
  • It makes testing easier (for both BetaCalc and the plugins themselves).
  • It reduces the dependencies of our system, making it more loosely coupled.

This new architecture is more limited than the first example, but in a good way. We’ve essentially put up guardrails for plugin authors, restricting them to only the kind of changes that we want them to make.

In fact, it might be too restrictive! Now our calculator plugins can only do operations on the currentValue. If a plugin author wanted to add advanced functionality like a “memory” button or a way to track history, they wouldn’t be able to.

Maybe that’s ok. The amount of power you give plugin authors is a delicate balance. Giving them too much power could impact the stability of your project. But giving them too little power makes it hard for them to solve their problems — in that case you might as well not have plugins.

What more could we do?

There’s a lot more we could do to improve our system.

We could add error handling to notify plugin authors if they forget to define a name or return a value. It’s good to think like a QA dev and imagine how our system could break so we can proactively handle those cases.

We could expand the scope of what a plugin can do. Currently, a BetaCalc plugin can add a button. But what if it could also register callbacks for certain lifecycle events — like when the calculator is about to display a value? Or what if there was a dedicated place for it to store a piece of state across multiple interactions? Would that open up some new use cases?

We could also expand plugin registration. What if a plugin could be registered with some initial settings? Could that make the plugins more flexible? What if a plugin author wanted to register a whole suite of buttons instead of a single one — like a “BetaCalc Statistics Pack”? What changes would be needed to support that?

Your plugin system

Both BetaCalc and its plugin system are deliberately simple. If your project is larger, then you’ll want to explore some other plugin architectures.

One good place to start is to look at existing projects for examples of successful plugin systems. For JavaScript, that could mean jQuery, Gatsby, D3, CKEditor, or others.

You may also want to be familiar with various JavaScript design patterns. (Addy Osmani has a book on the subject.)  Each pattern provides a different interface and degree of coupling, which gives you a lot of good plugin architecture options to choose from. Being aware of these options helps you better balance the needs of everyone who uses your project.

Besides the patterns themselves, there’s a lot of good software development principles you can draw on to make these kinds of decisions. I’ve mentioned a few along the way (like the open-closed principle and loose coupling), but some other relevant ones include the Law of Demeter and dependency injection.

I know it sounds like a lot, but you’ve gotta do your research. Nothing is more painful than making everyone rewrite their plugins because you needed to change the plugin architecture. It’s a quick way to lose trust and discourage people from contributing in the future.

Conclusion

Writing a good plugin architecture from scratch is difficult! You have to balance a lot of considerations to build a system that meets everyone’s needs. Is it simple enough? Powerful enough? Will it work long term?

It’s worth the effort though. Having a good plugin system helps everyone. Developers get the freedom to solve their problems. End users get a large number of opt-in features to choose from. And you get to grow an ecosystem and community around your project. It’s a win-win-win situation.


The post Designing a JavaScript Plugin System appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, , ,
[Top]

System UIcons

This is a great collection of icons by Corey Ginnivan that’s both free and with no attribution required when you use them. The style is super simple. Each icon looks like older versions of the icons from macOS to me because they’re cute but not too cute.

Also? The icon picker UI is slick and looks something like this today:

Oh and also, as I was looking around Corey’s personal site I noticed this lovely UI effect when you scroll —each card stacks on top of each other:

Direct Link to ArticlePermalink


The post System UIcons appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

,
[Top]

A Font-Like SVG Icon System for Vue

Managing a custom collection of icons in a Vue app can be challenging at times. An icon font is easy to use, but for customization, you have to rely on third-party font generators, and merge conflicts can be painful to resolve since fonts are binary files.

Using SVG files instead can eliminate those pain points, but how can we ensure they’re just as easy to use while also making it easy to add or remove icons?

Here is what my ideal icon system looks like:

  • To add icons, you just drop them into a designated icons folder. If you no longer need an icon, you simply delete it.
  • To use the rocket.svg icon in a template, the syntax is as simple as <svg-icon icon="rocket" />.
  • The icons can be scaled and colored using the CSS font-size and color properties (just like an icon font).
  • If multiple instances of the same icon appear on the page, the SVG code is not duplicated each time.
  • No webpack config editing is required.

This is what we will build by writing two small, single-file components. There are a few specific requirements for this implementation, though I’m sure many of you wizards out there could rework this system for other frameworks and build tools:

  • webpack: If you used the Vue CLI to scaffold your app, then you’re already using webpack.
  • svg-inline-loader: This allows us to load all of our SVG code and clean up portions we do not want. Go ahead and run npm install svg-inline-loader --save-dev from the terminal to get started.

The SVG sprite component

To meet our requirement of not repeating SVG code for each instance of an icon on the page, we need to build an SVG “sprite.” If you haven’t heard of an SVG sprite before, think of it as a hidden SVG that houses other SVGs. Anywhere we need to display an icon, we can copy it out of the sprite by referencing the id of the icon inside a <use> tag like this:

<svg><use xlink:href="#rocket" /></svg>

That little bit of code is essentially how our <SvgIcon> component will work, but let’s go ahead create the <SvgSprite> component first. Here is the entire SvgSprite.vue file; some of it may seem daunting at first, but I will break it all down.

<!-- SvgSprite.vue -->  <template>   <svg width="0" height="0" style="display: none;" v-html="$ options.svgSprite" /> </template>  <script> const svgContext = require.context(   '!svg-inline-loader?' +    'removeTags=true' + // remove title tags, etc.   '&removeSVGTagAttrs=true' + // enable removing attributes   '&removingTagAttrs=fill' + // remove fill attributes   '!@/assets/icons', // search this directory   true, // search subdirectories   /w+.svg$ /i // only include SVG files ) const symbols = svgContext.keys().map(path => {   // get SVG file content   const content = svgContext(path)    // extract icon id from filename   const id = path.replace(/^./(.*).w+$ /, '$ 1')   // replace svg tags with symbol tags and id attribute   return content.replace('<svg', `<symbol id="$ {id}"`).replace('svg>', 'symbol>') }) export default {   name: 'SvgSprite',   svgSprite: symbols.join('n'), // concatenate all symbols into $ options.svgSprite } </script>

In the template, our lone <svg> element has its content bound to $ options.svgSprite. In case you’re unfamiliar with $ options it contains properties that are directly attached to our Vue component. We could have attached svgSprite to our component’s data, but we don’t really need Vue to set up reactivity for this since our SVG loader is only going to run when our app builds.

In our script, we use require.context to retrieve all of our SVG files and clean them up while we’re at it. We invoke svg-inline-loader and pass it several parameters using syntax that is very similar to query string parameters. I’ve broken these up into multiple lines to make them easier to understand.

const svgContext = require.context(   '!svg-inline-loader?' +    'removeTags=true' + // remove title tags, etc.   '&removeSVGTagAttrs=true' + // enable removing attributes   '&removingTagAttrs=fill' + // remove fill attributes   '!@/assets/icons', // search this directory   true, // search subdirectories   /w+.svg$ /i // only include SVG files )

What we’re basically doing here is cleaning up the SVG files that live in a specific directory (/assets/icons) so that they’re in good shape to use anywhere we need them.

The removeTags parameter strips out tags that we do not need for our icons, such as title and style. We especially want to remove title tags since those can cause unwanted tooltips. If you would like to preserve any hard-coded styling in your icons, then add removingTags=title as an additional parameter so that only title tags are removed.

We also tell our loader to remove fill attributes, so that we can set our own fill colors with CSS later. It’s possible you will want to retain your fill colors. If that’s the case, then simply remove the removeSVGTagAttrs and removingTagAttrs parameters.

The last loader parameter is the path to our SVG icon folder. We then provide require.context with two more parameters so that it searches subdirectories and only loads SVG files.

In order to nest all of our SVG elements inside our SVG sprite, we have to convert them from <svg> elements into SVG <symbol> elements. This is as simple as changing the tag and giving each one a unique id, which we extract from the filename.

const symbols = svgContext.keys().map(path => {   // extract icon id from filename   const id = path.replace(/^./(.*).w+$ /, '$ 1')   // get SVG file content   const content = svgContext(path)   // replace svg tags with symbol tags and id attribute   return content.replace('<svg', `<symbol id="$ {id}"`).replace('svg>', 'symbol>') })

What do we do with this <SvgSprite> component? We place it on our page before any icons that depend on it. I recommend adding it to the top of the App.vue file.

<!-- App.vue --> <template>   <div id="app">     <svg-sprite /> <!-- ... -->

The icon component

Now let’s build the SvgIcon.vue component.

<!-- SvgIcon.vue -->  <template>   <svg class="icon" :class="{ 'icon-spin': spin }">     <use :xlink:href="`#$ {icon}`" />   </svg> </template>  <script> export default {   name: 'SvgIcon',   props: {     icon: {       type: String,       required: true,     },     spin: {       type: Boolean,       default: false,     },   }, } </script>  <style> svg.icon {   fill: currentColor;   height: 1em;   margin-bottom: 0.125em;   vertical-align: middle;   width: 1em; } svg.icon-spin {   animation: icon-spin 2s infinite linear; } @keyframes icon-spin {   from {     transform: rotate(0deg);   }   to {     transform: rotate(359deg);   } } </style>

This component is much simpler. As previously mentioned, we leverage the <use> tag to reference an id inside our sprite. That id comes from our component’s icon prop.

I’ve added a spin prop in there that toggles an .icon-spin class as an optional bit of animation, should we ever need. This could, for example, be useful for a loading spinner icon.

<svg-icon v-if="isLoading" icon="spinner" spin />

Depending on your needs, you may want to add additional props, such as rotate or flip. You could simply add the classes directly to the component without using props if you’d like.

Most of our component’s content is CSS. Other than the spinning animation, most of this is used to make our SVG icon act more like an icon font¹. To align the icons to the text baseline, I’ve found that applying vertical-align: middle, along with a bottom margin of 0.125em, works for most cases. We also set the fill attribute value to currentColor, which allows us to color the icon just like text.

<p style="font-size: 2em; color: red;">   <svg-icon icon="exclamation-circle" /><!-- This icon will be 2em and red. -->   Error! </p>

That’s it!  If you want to use the icon component anywhere in your app without having to import it into every component that needs it, be sure to register the component in your main.js file:

// main.js import Vue from 'vue' import SvgIcon from '@/components/SvgIcon.vue' Vue.component('svg-icon', SvgIcon) // ...

Final thoughts

Here are a few ideas for improvements, which I intentionally left out to keep this solution approachable:

  • Scale icons that have non-square dimensions to maintain their proportions
  • Inject the SVG sprite into the page without needing an additional component.
  • Make it work with vite, which is a new, fast (and webpack-free) build tool from Vue creator Evan You.
  • Leverage the Vue 3 Composition API.

If you want to quickly take these components for a spin, I’ve created a demo app based on the default vue-cli template. I hope this helps you develop an implementation that fits your app’s needs!


¹ If you’re wondering why we’re using SVG when we want it to behave like an icon font, then check out the classic post that pits the two against one another.


The post A Font-Like SVG Icon System for Vue appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

CSS-Tricks

, ,
[Top]

The Best Design System Tool is Slack

There’s a series questions I have struggled with for as long as I can remember. The questions have to do with how design systems work: Where should we document things? Do we make a separate app? Do we use a third-party tool to document our components? How should that tie into Figma or Sketch? What about written documentation? Should we invest a lot of time into making a giant Polaris-like wiki of how to build things?

The issue with all these tools and links and repositories is that it can become increasingly difficult to remember where to go for what kind of information. Designers should go here and engineers should go there — unless, of course, you’re an iOS engineer, then you need this special resource instead. It can be overwhelming and confusing for everyone that doesn’t live within the orbit of design systems drama and is just trying to ship a feature on time.

After years of struggling with these questions, I think my current advice to my past (and current) self is this: meet the people where they are. And where are most people asking questions about design systems, whether that’s a color variable or a component or a design pattern?

In Slack!

The other day I thought it would be neat to set up some Slackbot custom responses to do a rather simple thing. When someone types color me into a channel, I all the color variables and their hex values are pasted. That way, no one needs to learn a new tool or bookmark yet another link.

Here’s how it works.

We first have to open up the settings of the organization you’re in and click the “Customize” item in this dropdown:

That pops open a new tab with the “Customize your Workspace” settings. If you select “Slackbot” from the options, then you can then see all of the custom responses that have been set up already. From there, we can create a new response like this:

That n is what breaks things onto a new line so that I can now test it out in a chat with myself once I’ve saved this:

Because this takes up so much darn space, I also made separate answers for each color, like blue and purple. But all of this has me wondering: how else can we use Slack — or whatever chat app or communication tool — to extend the cause of good design systems work?

I bet there’s a ton of other things we can do to improve our lives within tools like this and make design systems work even easier.

The post The Best Design System Tool is Slack appeared first on CSS-Tricks.

CSS-Tricks

, , , ,
[Top]

Chrome + System Fonts Snafu

There was just a bug late last year where system fonts (at least on Mac, I don’t know what the story was on other platforms) in Chrome appeared too thin and tracked-in at small sizes and too thick and tracked-out at larger sizes. That one was fixed, thankfully. But while it was a problem, it was the reason I gave up on system fonts for now and switched something else. A performance loss but aesthetic gain.

Now there is a new much worse bug, where the system font can’t be bolded. It’s not great, as a ton of sites roll with the system font stack as it has two major benefits: 1) it can help your site look like the operating system 2) it has great performance as the site doesn’t need to download/display and custom fonts.

Jon Henshaw wrote it up:

… the bug caught the attention of Adam Argyle, maker of VisBug and Chrome CSS Developer Advocate at Google. Argyle created a Chromium bug report, but the Chromium development team ultimately decided it wasn’t a blocker for releasing version 81. That resulted in sites like Coywolf not being able to use bold text for fonts that are larger than 16px (e.g., every heading).

The bug won’t be fixed in version 82 because the Chromium team announced that they’re skipping it, and will be releasing version 83 in mid-May instead. Argyle assured everyone on the original GitHub bug report that it would be fixed in version 83.

Above is Jon’s site. Andy Bell’s site got hit by it too.

So we’re looking at 4 weeks or so. Adam proposed a temporary fix of going Helvetica for now:

body {   font-family: -apple-system, Helvetica; }

I guess with -apple-system in there, older versions of Chrome/macOS still might be able to benefit from system fonts? Not sure.

That brings up a source of confusion for me. When I first heard of using system font stacks, there was -apple-system and BlinkMacSystemFont and you were supposed to use them in that order in the font stack. Then came along -system-ui, and that seemed to work well all by itself and that was nice as it was obviously less Mac-specific. But there is also system-ui (no starting dash), and that seems to do the same thing and I’m not sure which is correct. Now it looks like the plan is ui-sans-serif and friends (like ui-serif and ui-monospace). I like the idea, but I’d love to hear clarity from browser vendors on what the recommended use is. Are we in a spot like this?

/* Just a guess... */ body {   font-family:      ui-sans-serif,      system-ui,      -system-ui,      -apple-system,     BlinkMacSystemFont,     Roboto, Helvetica, Arial,      sans-serif,      "Apple Color Emoji"; }

Another observation from me… as I was trying to replicate this on Chrome 81, at first I was like “weird, works for me”, because I was trying out the bolding on default 16px text. I noticed that it was when the font was 20px or bigger the problem kicked in:

Bramus has an alternative fix idea: use Inter.

The post Chrome + System Fonts Snafu appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]

How to build a bad design system

I didn’t realize this until it was far too late, but one of the biggest mistakes that’s made on a design systems team is a common mismanagement issue: there are too many people in a meeting and they have too many dang opinions.

Is there a conversation about the color of your buttons that’s taking place? Great! Everyone needs a consistent set of colors so that users know what to click and so that designers don’t have to choose from a smorgasbord of options. But the tough question at the beginning isn’t what colors we should choose and when to pick them, but rather this: how many people are in that dang room?

How many people are making decisions about your design system?

Are three people talking about the buttons in your design system? Wonderful. Are there 20? Woof! That’s a serious problem because it shows that far too much energy is being spent on the wrong things; it’s nothing short of mismanagement, in fact.

(This is why I reckon design systems aren’t about design or even about systems. It’s actually about managing people and their time, attention, and focus. But that’s a rant for another day.)

Anyway, the hard call that someone on a large design team will have to make at some point or another is deciding which people need to leave the room. And that sounds really mean, I get it, but it’s the kind thing to do. If everyone has opinions then, first, nothing will get done and, second, you’ll end up causing rifts when some opinions are shunned and others are heard.

It was thoroughly shocking to me when I started my first big design systems project that the more people that joined any given meeting, the less effective we were. It was like the IQ of the room dropped by ten thousand points. And I was also shocked that the hardest problem wasn’t about building the system; learning about TypeScript, making sure components were accessible, doing audits, etc. Instead it was this: the whole too-many-people-in-a-meeting thing.

Everyone cannot possibly be allowed to voice their opinions about every tiny detail of the UI and at some point someone needs to come in and draw a line as to who is allowed to care about what things. That’s not to say that people aren’t allowed to have feedback — feedback should always be welcome! — but one of the main advantages of having a design systems team is to offset all those decisions onto someone else.

I was listening to this livestream of Jason Fried and DHH the other day and they mention that:

If you want to be even less sure about something, all you have to do is ask one more person what their take is.

That’s definitely the feeling I had when too many people were talking about buttons or borders or anything, really. This sort of hopeless feeling that change just isn’t possible. And that you can’t make a decision about something because you need to massage the egos of everyone in the room.

This also reminds me of this great post by Paul Ford about what the web is:

“Why wasn’t I consulted,” which I abbreviate as WWIC, is the fundamental question of the web. It is the rule from which other rules are derived. Humans have a fundamental need to be consulted, engaged, to exercise their knowledge (and thus power), and no other medium that came before has been able to tap into that as effectively.

Working in a big organization is shocking to newcomers because of this, as suddenly everyone has to be consulted to make the smallest decision. And the more people you have to consult to get something done, the more bureaucracy exists within that company. In short: design systems cannot be effective in bureaucratic organizations. Trust me, I’ve tried.


Anyway, the way to fight that is by drawing that line, by kicking people out of meetings that don’t need to be there. It’s really the kindest thing to do because it will make your design system much faster to build, and less stressful for you.

The post How to build a bad design system appeared first on CSS-Tricks.

CSS-Tricks

, ,
[Top]

Weekly Platform News: Contrast Ratio Range, replaceAll Method, Native File System API

In this week’s roundup: Firefox’s new contrast checker, a simpler way to lasso substrings in a string, and a new experimental API that will let apps fiddle with a user’s local files.

Firefox shows the contrast ratio range for text on a multicolored background

According to Success Criterion 1.4.3 of the Web Content Accessibility Guidelines (WCAG), text should have a contrast ratio of at least 4.5. (A lower contrast ratio is acceptable only if the text is 24px or larger.)

If the background of the text is not a solid color but a color gradient or photograph, you can use the special element picker in Firefox’s Accessibility panel to get a range of contrast ratios based on the element’s actual background.

(via Šime Vidas)

Replacing all instances of a substring in a string

The new JavaScript replaceAll method makes it easier to replace all instances of a substring in a string without having to convert the substring to a regex first, which is “hard to get right since JavaScript doesn’t offer a built-in mechanism to escape regular expression patterns.”

// BEFORE str = str.replace(/foo/g, "bar");  // AFTER str = str.replaceAll("foo", "bar");

This new string method has not yet shipped in browsers, but you can start using it today via Babel (since it’s automatically polyfilled by @babel/preset-env).

(via Mathias Bynens)

Try out the Native File System API in Chrome

The Native File System API, which is experimentally supported in Chrome, allows web apps to read or save changes directly to local files on the person’s computer. The app is granted permission to view and edit files in a specific folder via two separate prompts.

You can try out this new feature by visiting labs.vaadin.com in Chrome on desktop.

(via Thomas Steiner)

More news…

sunday-issue-18.png

Read more news in my weekly newsletter for web developers. Pledge as little as $ 2 per month to get the latest news from me via email every Monday.

More News →

The post Weekly Platform News: Contrast Ratio Range, replaceAll Method, Native File System API appeared first on CSS-Tricks.

CSS-Tricks

, , , , , , , , , ,
[Top]

The Guardian digital design system

Here’s a fascinating look at The Guardian’s design system with a step-by-step breakdown of what’s gone into it and what options are available to designers and developers. It shows us how the team treats colors, typography, layouts, and visual cues like rules and borders.

I’ve been struggling to think about how to describe design systems internally to folks and this is giving me a ton of inspiration right now. I like that this website has all the benefits of a video (great tone and lovely visuals) with all the benefits of a UI kit (by showing what options are available to folks).

This also loosely ties back into something Chris has been discussing lately, which is being mindful of knowing who a design system is for. Some are meant for internal use and others, some are meant for internal use but are openly available for people like contractors, and others are meant for varying degrees of external use. Here, The Guadian is not explicit about who their design system is for, but the description of it gives a pretty good hint:

A guide to digital design at the Guardian

So please, enjoy looking at this well-documented, highly interactive and gorgeous design system. At the same time, remember it’s made for a specific use case and may not line up with all the needs of your project or organization. It sure is inspirational to look at, one way or the other!

Direct Link to ArticlePermalink

The post The Guardian digital design system appeared first on CSS-Tricks.

CSS-Tricks

, , ,
[Top]