Giter Club home page Giter Club logo

core's Introduction

QuarkSuite Core (v2.1.0)

Table of Contents

Introduction

QuarkSuite Core is the engine of the emerging QuarkSuite toolkit which is focused around using the web platform as a design token development environment.

The core in particular is responsible for generating, assembling, and exporting token collections and dictionaries.

QuarkSuite Core is written in vanilla JavaScript (ES2017+).

Features

  • Generate practical color palettes for apps and sites
    • Color adjustment and blending
    • Built-in colorblindness, contrast sensitivity, and illuminant simulations
    • Material-esque and artistic configurations
    • WCAG-based and colorimetic color accessibility filtering
  • Enforce compositional balance with modular scales
  • Export tokens to take with you
    • Graphic design palettes (GIMP/Inkscape, Sketch)
    • Stylesheet formats (CSS custom properties, Sass, Less, Stylus)
    • Data formats (JSON, YAML)
  • Interop with TailwindCSS and Style Dictionary
  • Scales with your needs
    • from basic generation and assembly
    • to advanced rules and processes
    • to modular configurations
  • Independent modules
    • color.js for color features
    • content.js for content features
    • exporter.js for exporting features
    • workflow.js for advanced features

Packages

In general, prefer the JSDelivr/Statically CDN for availability, features, and speed. The Nest.land package is a failsafe for the repo disappearing or GitHub going down.

Getting Started

Live

If you want to try the library live, load up your console in a modern browser or run a deno repl and copy/paste:

const {
  color,
  content,
  exporter,
  workflow
} = await import("https://cdn.jsdelivr.net/gh/quarksuite/[email protected]/mod.js");

Local Development

For local dev, it’s recommended that you use a buildless stack or work in the browser. QuarkSuite Core is designed especially for that.

Browser/Deno

import {
  color,
  content,
  exporter,
  workflow
} from "https://cdn.jsdelivr.net/gh/quarksuite/[email protected]/mod.js";

Node

The now defunct @quarksuite/core was originally published on NPM, but I started the project over and unpublished the package. The core is now in a state where I feel comfortable putting it back on NPM and exposing it to the wider JavaScript ecosystem.

Ensure that type: module is set in your package.json so that Node is set for ES Modules. Then install the package.

npm install @quarksuite-two/[email protected]

# OR

yarn add @quarksuite-two/[email protected]

And then in your source files:

import {
  color,
  content,
  exporter,
  workflow
} from "@quarksuite-two/core";

Offline

Some engines (like QuickJS) support ES Modules but don’t allow importing from URLs. For those, you can curl/wget the modules you need directly.

curl -o [module] https://cdn.jsdelivr.net/gh/quarksuite/[email protected]/[module]

# OR

wget https://cdn.jsdelivr.net/gh/quarksuite/[email protected]/[module]

Handbook

The QuarkSuite Core Handbook introduces the features of the library from a user perspective. It’s recommended you read that next.

API

The QuarkSuite Core API is a technical overview of the library that also serves as documentation of its functions. It may make more sense after reading the handbook, but some of you may get more out of reading it beforehand.

Demos

I maintain a growing collection of demos for QuarkSuite at various stages of development on Glitch. It includes rough experiments, workflow samples, and practical usage examples, so be sure to check it out.

Contributing

First, clone the repo to your local machine.

git clone https://github.com/quarksuite/core.git

Then make sure you read the contribution guidelines.

Concept

QuarkSuite is a project built around the idea that authoring design tokens shouldn’t be limited to a particular environment or web stack. Many design tools build entire systems around themselves.

I wanted a workflow where I could open a blank page in a browser and start experimenting. I wanted tools with mobility across environments. I wanted something that could grow seamlessly with my needs and allow me to automate my requirements.

QuarkSuite aims to be that toolkit.

Project Objectives

The following objectives guide the ongoing development of QuarkSuite.

Availability

This project focuses on the overall availability of web technologies over the popularity of particular web stacks. Its independent modules, relatively small size, and simple output all work to make the kit extremely portable.

Adaptability

QuarkSuite Core aims to grow or shrink according to your needs. Its functional nature makes it straightforward to use and extend as you see fit.

Invisibility

This project is a means to an end: creating design tokens. I don’t want its processes to call attention to themselves or its design to get in your way. Use what you need and leave the rest.

Interoperability

QuarkSuite Core is built to work with what already exists in the design token and UI theming space. It can be used on its own, but its schema is nothing but a plain object.

This makes it particularly suited for integration with design tools that use their own schemas (such as TailwindCSS and Style Dictionary).

Stability

Where applicable, this project aims to adhere as closely as possible to current and emerging web standards. From its use of standard CSS color formats to its avoidance of bleeding-edge syntax.

Credit

core's People

Contributors

cr-jr avatar

Watchers

 avatar

core's Issues

Add temperature modifier to color_adjust

This seems like a good time to implement a correlated color temperature (CCT) function

Spec

color_temperature(modifiers, color) => string

  • modifiers: {}: color temperature options
    • modifiers.temperature = 6500: number: temperature (in kelvin)
    • modifiers.intensity = 50: number: strength of color overlay (as a percentage)
  • color: string: color to overlay temperature result

Notes

I'll most likely be using be using an adaptation of this gist to convert kelvin to RGB (@paulkaplan) for the implementation, because it's accurate enough for most of my use cases and overlaying through the OKLab space will ensure relative perceptual accuracy.

So yeah, I'll get on that.


Then again, temperature could be considered a property of color because it affects how a color is perceived. This might make more sense as a modifier for color_adjust instead.

Factory object propagation is incomplete (fixed in 1.2.0)

Problem

In cases where a method has to operate on a collection of values rather than a single value, the propagated version drills too deeply to an unusable value.

Example

The operation most illustrative of the bug is the following sequence:

// Assuming a factory object derived from 'ms' utilities is already created
Ms(1) // initialize factory
  .create({ ratio: [1.25, 1.5], values: 8 }) // create a new scale
  .$create({ ratio: 1.5, values: 4 }) // propagate to create an array of scales
  .$modify((n) => n * 10) // Error thrown here

Reasoning

The error throws because propagated methods don't currently know how to handle a utility that transforms collections instead of individual values.

I'll fix this on Monday.

Workaround

In the meantime, getting the collected values and using them as the initial value of new factory objects satisfies the expected behavior.

const { value: collected } = Ms(1)
  .create({ ratio: [1.25, 1.5], values: 8 })
  .$create({ ratio: 1.5, values: 4 })

const scales = collected.map(
  (scale) => Ms(scale).modify((n) => n * 10)
);

Fix (v1.2.0)

Modifying the original example to use scale propagation ($$_) resolves the bug. 😄

// Assuming an object derived from 'ms' utilities is already created
Ms(1) // initialize factory
  .create({ ratio: [1.25, 1.5], values: 8 }) // create a new scale
  .$_create({ ratio: 1.5, values: 4 }) // propagate over values to create an array of scales
  .$$_modify((n) => n * 10) // propagate over scales to multiple every value by 10

Please let me know about any other bugs in the object factory interface.

Road to v2

Quarks System Core v2 Announcement

While I've been enhancing and fixing the library as I use it, my eyes are also on improvements for v2. The major things I want to do for the library include:

  • Refine the language and implementation of actions and emitters
  • Clarify the library's intention as a browser-focused tool
  • Implement robust, contextual error handling
  • Split the data types into individual modules that work independently of each other
  • Implement HTML rendering for data types and token collections
  • Refactor the internals for performance
  • Tighten the workflow enough to make formulas and bootstrappers superfluous

With the main demos complete and the workflow settled, its time to build on what already works.

It might come in a month. It might come in three months. But it's coming. So see ya then. 👋🏾


Update: 2022-03-15

The color API is now more or less settled. The only thing left to implement is the color_simulate() action for simulating various conditions that influence color perception such as:

  • Color vision deficiency (colorblindness)
  • Contrast sensitivity
  • Correlated color temperature

Other major changes include:

  • Narrowing the focus of palette generation around two conventional configurations with a consistent internal structure
  • Clarifying the use cases for color interpolation
  • A standard color token format
  • Shifting the purpose of color and palette generation from general use and arbitrary scaling toward granular use and judicious scaling

You can check out the changes and my reasoning in the v2 notes.

Update: 2022-04-14

Color Module

Done pretty much everything I wanted to cover with colors and reduced the utility count from >21 in v1 to 10 focused functions for working with color in v2:

  • convert(to, color)
  • adjust(properties, color)
  • mix(settings, color)
  • harmony(settings, color)
  • vision(settings, color)
  • contrast(settings, color)
  • illuminant(settings, color)
  • palette(settings, color)
  • accessibility(settings, palette)
  • tokens(palette)

Content Module

Modular scale functionality has been overhauled and simplified in ways that deprecate the formula and bootstrapper concepts relied on in v1.

In addition, content utilities are now contained in their own module. Token generation for modular scales is now handled by one dedicated function that outputs simplified data (no more arrays) from conventional configurations.

The standard scale configuration types are:

  • Bidirectional (the default)
  • Unidirectional
  • Ranged

A grid type is specially handled for creating CSS grid tokens.

This means the final content module API (for now) contains the following:

  • text(settings, font)
  • ms(settings, base)
  • modify(calc, ms)
  • tokens(settings, ms)

text() handles font stacks and weights, ms() creates the raw modular scales that then get passed to modify() for adjustment and tokens() for output.

Modular scale token structure is deliberately generic so you can still use the hierarchy or groupings you want.

Tomorrow, I'm going to begin refactoring and improving the token exporters.

Update: 2022-04-18

After about a month and 19 days, the initial development phase of Core v2 is complete. This means that the API is complete and sealed. The core functionality has also been tested. Now, I can use my tests to guide the refinement phase where I check for particular edge cases and clean up the code.

Core v2 API (23)

The API of QuarkSuite Core v2 slimmed significantly since v1. The functionality has been drilled down to a leaner collection of utilities and a better directed workflow.

In the process, the formula/bootstrapper flow is entirely deprecated because they're now less powerful and more constrained than the utilities provided in v2.

The object factory workflow is also deprecated because the improved action/emitter functional workflow means it's now needlessly complicated in comparison.

Color Module (11)

  • convert(to, color)
  • adjust(properties, color)
  • mix(settings, color)
  • harmony(settings, color)
  • vision(settings, color)
  • contrast(settings, color)
  • illuminant(settings, color)
  • palette(settings, color)
  • accessibility(settings, palette)
  • tokens(palette)
  • output(format, dict)

output() is a new utility that really just wraps the behavior of the v1 tokens_to_gpl(), tokens_to_sketchpalette() into its own interface. These particular utilities only ever use or care about color dictionaries, so it made sense to place in the color module.

Content Module (4)

  • text(settings, font)
  • ms(settings, base)
  • modify(calc, ms)
  • tokens(settings, ms)

The content module has no changes made since the last update.

Exporter Module (3)

  • stylesheet(format, dict)
  • data(format, dict)
  • interop(format, dict)

The exporter module splits the remaining tokens_to_* exporters into categories that handle particular formats. This cleans up the interface without asking the user to be aware of every exporting function in the API.

Workflow Module (5)

  • process(...emitters)
  • preset(action, y)
  • pipeline(x, ...processes)
  • propagate(emitter, xs)
  • delegate(emitters, xs)

The workflow module (previously named the functional module) contains a small subset of functional helpers which provide advanced data composition patterns for those who need them.

Unlike v1 where working with data was impractical without using the functional helpers, Core v2 makes them truly optional.

The simplest projects won't need them, but they excel in situations where you have certain expectations for your data and would like to reuse a given workflow across your projects.

Refinement Phase

The next 1-2 weeks will focus on making internal readability improvements and attempting to squeeze a little more performance out of the library.

Y'all take care for now.

Update 2022-04-22

A good sign of how much cruft was removed from the API while preserving functionality: documenting the modules and their expected types is already done.

Elements Module

Okay, so the core API is done, but it bugs me that QuarkSuite has no way of actually rendering data in a browser. I experimented with a prototypal DSL that does some of its own, but it dawned on me that means it's doing way too much.

I think the better approach would be to create an elements.js module to separate data rendering from the rest of the environment. And especialy from environments that may not need it. That way, the DSL can be concerned solely with translation and transmission of data as a declarative workflow in HTML.

So I may focus on that and leave the further internal refinements for v2.1

Update 2022-05-16

The core API is now fully documented. After I take an extended break (2-3 weeks), I'm gonna write up the handbook. After the handbook, I'll rewrite the README and launch the core.

The elements.js module mentioned in the last update is no longer a thing. Instead, I've begun implementing the rendering elements as a separate project built on top of the core.

This ensures that data rendering code won't pollute the other JavaScript environments that the core works in (server-side and embedded).

I'll work on the other bits of the project with greater focus once the core is buttoned up, so look forward to that.

Anyway, resting time. Later.

Support CSS Color Module 4 spec for OKLab/OKLCh (added in v1.3.0)

When I implemented OKlab support for Quarks System Core, the format was at the time non-standard and unsupported. That doesn't seem to be the case anymore.

Since one of the project goals is to adhere as closely to the evolution of the web platform as possible, I'll have to take some time to reimplement how OKLab and OKLCh are read and processed by the library.

This isn't an urgent development, but I'll get on it soon.


I'm on it now.

Implementation details

Quarks System Core already supports OKLCH because it's the format where all the color adjustments and generation happens. I just called it oklab() while it was non-standard. So for that, I only require a name change.

As for OKLab, the existing OKLCH format has a parser that takes the valid format and transforms its values back to OKLab, so the process goes as follows:

  • Rename oklab() to oklch() and update the validator, converters, and emitter accordingly
  • Rename color_to_oklab() utility to color_to_oklch()
  • Add a validator, converters, and emitter for standard oklab()
  • Add a color_to_oklab() utility
  • Add tests for the new standard formats

Shouldn't take long, but we'll see. 😄

tokens_to_tailwindcss() is incompatible with the theme changes in v3

Problem

Tailwind v3 theme config made some changes. The most notable ones that break interoperability:

  • nested objects are no longer valid in some categories (exempting colors, of course)
  • any key with a '-' is now invalid

I'm also gonna fix that Monday since it's really nothing. The output of tokens_to_tailwindcss() still works fine with v2. It's just that v3 works too well to leave this alone. 😛


Honestly, I don't use Tailwind much myself, so this one may sit for a while. Sorry.

IMPORTANT: Migrating to Codeberg

I've thought about it for a while, and I'm uncomfortable with continuing to host my projects on GitHub now that it's owned by Microsoft. I've hesitated because GitHub is basically the place to host FOSS projects and especially to reach other developers.

I'm aware that Microsoft has gotten better in a sense, but I also have those experiences that remind me how corporations are gonna do corporation things. And a lot of it is simply not in alignment with my values.

QuarkSuite will still be available and worked on, but join me on Codeberg once it's finished migrating.

OKLab chroma adjustment and filtering inaccuracies (fixed in 1.2.1)

Problem

The color adjustment utilities are not capped at 0.5 for the OKLab space. This means the maximum adjustment value you can input is actually 50.


It also turned out that the underlying math was a bit wonky, too. 😅

Example

color_adjust({ chroma: 100 }); // yields weird results

Workaround

color_adjust({ chroma: 50 }); // the actual maximum  because the range is current 0-1, not 0-0.5 -_-

How'd I overlook something like that? 😩 This gets fixed first thing tomrorrow.

Fix

Update to v1.2.1. The workaround is wrong because chroma wasn't being calculated within the range of 0-0.5 to begin with. The patch resolves both issues and makes chromatic adjustment and palette filtering more accurate besides. It also locks the lightness adjustment at 100 per the W3C recommendation for OKLCh.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.