npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@kbai/design-system

v0.3.2

Published

Typescript design system

Downloads

10,877

Readme

Design System

Currently, just a central place to keep my thoughts where I jot down current ideas for this project.

This design system extends past theming and consistent components. It implements a new layout conceptual model that transpiled into CSS. The purpose of this layout model is to be simple, easy to reason with, and easy to be autogenerated with logical rules. Additionally, it's purpose is to be able to powerfully generate declarative layouts that are completely fluid and responsive.

Concepts

In this design-system, the simplest building blocks are called a Box. For clarity, in HTML, it is simply a div.

In 99% of the user interfaces we build, we can break down the layout of our user interface down into a few simple relationships: position, size, and layout.

Position

Position refers to the positioning of a Box on the screen (the x, y coordinates). There should only exist 2 ways: absolute positioning and relative positioning. These are the same two CSS positioning properties.

Absolute positioning refers to specifying an x,y coordinate. The Box will be placed at that x,y coordinate regardless of where everything else is.

Relative positioning means that the Box will not control its own x,y coordinates. It will simply let its parent control where on the screen it is positioned.

CSS positioning properties such as fixed and sticky aren't quite needed. With the scroll model from this design-system, fixed and sticky properties can be done just relative and absolute positioning.

Layout

Every Box defines some sort of layout. The nice thing is that there are only two types of layout: Rows and Columns. Although seemingly over simplified, with some additional configuration options & nesting Boxes, rows and columns can powerfully express the layout of any user interface.

Size

Size is a tricky parameter. Although the only 2 properties of size are width and height, there are three different ways size can be calculated.

  1. Size can be calculated from its children's size.
  2. A Box can provide its own size
  3. Its parent can define the size of the child through layout

It gets complicated when the size is dependent on more than one of the above points. For example, a box which is going to let its children determine the size, but also has a maximum size that it can't go over is tricky to layout, especially when considering responsivity.

Concepts of Layout

Layout can be determined in a very functional way.

Width of the parent is our main parameter:

layout([ParentLayout, ParentPosition, width])
    => [width, Layout, Position]
    => eachChild([childLayout, Layout, Position, width])
    => [Layout, Position, Size, width]

For a Box, given a parameter width, it returns a tuple of [width, Layout, Position] which is then used to calculate

We can wrap this function above with higher order functions to allow our UI to be constrained with other parameters in addition to width. This allows for complete flexibility. However, we don't need this amount of flexibility or even necessarily want it. It would make our UI overly complex to reason with and it would make rendering the UI slow.

If we can define our user-interfaces with a set of functions, then we can generally say that layouts in our UIs are simply defined by piecewise linear functions. This means our properties are in the form of ax + b, where a is a multiplier, b is a constant, and x is the width (or the property it depends on). With more properties, we can represent the UI as a linear combination of x1, x2, etc.

Translating our concepts of Layout into Code

Since our layouts are simply piecewise functions, all we have representing our layout is many linear functions separated by if statements (breakpoints). In CSS they are handled with @media queries. With CSS, we're limited to choosing a handful of media queries that act as our application breakpoints.

However, with our new model, we can powerfully express custom breakpoints for each child based on its parent's size.

We don't try and calculate these functions on the fly at run-time. Instead, we can interpret them into static CSS properties.

For style changes based on state, we can extract those functions and run them at runtime.

Basic Example

let boxLayout = cond(switch = size.width, values = {
    =>[0 to 1200] = { layout = row }
    =>[1200 to inf] = { layout = col, position = (5%, 10%) }
})

Box(spread = boxLayout, style = { fg = theme.background, bg = theme.white })
(children = [
    RowItem(text = `Item`),
    RowItem(text = `Item2`)
])

// output css for layout (use grid to layout rows and columns to take advantage of grid-gap)
.box {
    display: grid;
    grid-template-rows: 1fr;
    grid-auto-flow: column;
    grid-template-columns: auto;
    min-width: 100px;
    max-width: 500px;
    width: 50%;
    height: 80%;
}

@media only screen and (min-width: 1200px) {
    .box {
        display: grid;
        grid-template-rows: auto;
        grid-auto-flow: row;
        grid-template-columns: 1fr;
        position: absolute;
        left: 5%;
        top: 10%;
    }
}

Conceptually, it's a functional language that compiles computes the layout of any user interface.

It's a tree representation of each component + a tree representation of each component's layout. Except, it takes advantage of powerful pattern matching for an expressive syntax.

It's like html or css where it only contains information about the structure, but it represents the data in a very powerful way.