Giter VIP home page Giter VIP logo

atomizer's Introduction

Atomizer

Atomizer is a tool that helps you create Atomic CSS rules (acss.io).

Atomic CSS is a collection of single purpose styling units for maximum reuse that fits well with components in templated frameworks such as React, Ember or Angular. For more information we recommend that you read "Challenging CSS best practices", watch the Atomic CSS presentation, or check this deck.

Info

This is a monorepo of the various Atomizer ecosystem packages.

Library

  • Atomizer: The library source code is located in the packages/atomizer directory

Plugins

Third Party Extensions

For Chrome

For VSCode

Contributing

Please read through our CONTRIBUTING.md and fill out an issue at atomizer/issues!

License

This software is free to use under the Yahoo Inc. BSD license. See the LICENSE file for license text and copyright information.

Third-party open source code used are listed in our package.json file.

atomizer's People

Contributors

carriemorrison avatar dependabot[bot] avatar dword-design avatar fidian avatar github-actions[bot] avatar gitter-badger avatar idmytro avatar itssumitrai avatar johnnorris avatar kfay avatar lalau avatar lingyan avatar maheshbansod avatar nsaunders avatar nspector avatar okuryu avatar pankajparashar avatar rahulkumarsingh73690 avatar redonkulus avatar renatoi avatar roderickhsiao avatar samlecuyer avatar sarbbottam avatar snyamathi avatar soluml avatar src-code avatar thierryk avatar tom76kimo avatar vijar avatar willthai avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

atomizer's Issues

Flexible Breakpoint config

@thierryk recently pointed out that Atomizer's breakpoint design, which limits you to three breakpoints, is not flexible enough to accommodate common use cases. We probably should allow developers to create unlimited arbitrary breakpoints.

Also, it'd be a good opportunity to revisit whether it makes sense to have any default breakpoints (such as the 3 we have now), and if so, what their default values should be.

@renatoi

RTL parsing could be optimized, made more resiliant

Right now we parse individual keys/values for the RTL $START and $END tokens. We could just be parsing the CSS output for those tokens instead.

Also, these tokens could easily be mistaken for custom values ($ is used for globals in some projects), so maybe Atomizer should use tokens that are a little more unique?

Documentation improvements

Starting this issue to discuss ideas for documentation improvements based on my first impressions trying to play with the lib. fyi @renatoi @thierryk

  1. Right now the README docs are long, and cover both users/consumers of the library as well as developers of the library. Perhaps it'd be better to focus more on consumers in the README, and link off to another page for those who wish to add to or enhance the atomic objects?
  2. The concept of atomic objects vs config is a little confusing right now. I think it'd help to explain each concept via a simple example, such as font-size or text-align or something similar.
  3. Some of the language is confusing in the way things are referred to with similar names, eg "This is the object that tells what it wants from the atomic.css (the atomic rules)..." I'm thinking we should avoid overuse of the word "atomic" here, and call these rules/objects something else, maybe playing up the idea that these "atomic objects" are sort of like the generic declarations of rules, not the actual instantiation of atomic.css styles? This would result in renaming of the atomicConfig.js and atomicObjects.js files as well.
  4. The library appears to ship with sample config in atomicConfig.js, but there's no instructions as to whether that's what users should edit or replace. This could be made more clear (eg, make that file an explicit "example" config)

Helpers: Single-pixel border helpers

From issue #76:

For the record: helpers.css (from another repo) has been updated with border classes meant to help when styling boxes with a single pixel border but those rules need to integrate Atomizer somehow.

More details from @thierryk:

border needs 3 values: width style color. We can get style borders the way we want with Atomizer by using those 3 but a common use case is to style border with a single pixel, so what we added to the helper classes are border declarations mixing both style and width

that way authors can do this: Bd Bdc-000 to get a black border around a box instead of having to go verbose with Atomic Bdc-000 Bds-s Bdw-1px

Let's remove the keyword values for `font-size`

Even though they should belong there since those are valid values for this property, I think it'll confuse people more than it'll help them.
So let's make sm, md, and the like custom values...

Global suffixes

Add support for globally-defined suffixes, which will make it easier for common values to be reused across a number of CSS properties. For example, in config you may specify something like:

{
  globals: {
    foo: '10px'
  }
}

...which would allow you to write classes like H-foo and P-foo, which would output:

.H-foo {
  height: 10px;
}
.P-foo {
  padding: 10px;
}

...without requiring you to write custom config for every class using the foo suffix.

Make border classes more atomic-friendly

We have the following helper classes:

.Bd-0 {
    border: 0;
}
.Bd-1,
.Bdx-1,
.Bdy-1,
.Bdt-1,
.Bdend-1,
.Bdb-1,
.Bdstart-1 {
    border-width: 0;
    border-style: solid;
}
.Bdstart-1 {
    border-left-width: 1px;
}
.Bdend-1 {
    border-right-width: 1px;
}
.Bdx-1 {
    border-right-width: 1px;
    border-left-width: 1px;
}
.Bdy-1 {
    border-top-width: 1px;
    border-bottom-width: 1px;
}

But I think we should move all this to rules.js โ€” using classes like Bdw-, Bds-, Bdc-.
That way users can create border styling without having to create custom Atomic classes.

Thoughts?

Make this rule `!important`

We need to be able to pass ! in the class and have Atomizer writes the rule with !important, for example:

<div class="Bgc-000!"></div>
.Bgc-000\! {
    background: #000 !important;
}

Use semver for config/rulesets

Would be helpful to tag configuration output with semver that's tied to the ruleset, that way as the rulesets change over time we can properly ensure that configuration files work with a particular version of the ruleset.

Modify the config to allow use of pseudo-class

We want to allow the creation of classes like Td-u:h which would style text with an underline on mouseover.
As discussed, it could be in the form of:

{
   suffix: 'f',
   values: ['foo'],
   breakPoints: ['sm'],
   pseudo-classes: ['hover', 'focus']
}

But what about if the user wanted to sandbox this class within a breakpoint? Should that be a concern? I'm not sure there are real use cases for that though.

Add ruleset for helper classes

We've been discussing the addition of a new ruleset for helper classes, which would allow developers to pick and choose which helpers they want to include in their CSS. Let's use this issue to track the helpers we want to add.

@thierryk @renatoi

How do we deal with transform and the like?

For example:

transform: none
transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
transform: translate(12px, 50%)
transform: translateX(2em)
transform: translateY(3in)
transform: scale(2, 0.5)
transform: scaleX(2)
transform: scaleY(0.5)
transform: rotate(0.5turn)
transform: skewX(30deg)
transform: skewY(1.07rad)
transform: matrix3d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0)
transform: translate3d(12px, 50%, 3em)
transform: translateZ(2px)
transform: scale3d(2.5, 1.2, 0.3)
transform: scaleZ(0.3)
transform: rotate3d(1, 2.0, 3.0, 10deg)
transform: rotateX(10deg)
transform: rotateY(10deg)
transform: rotateZ(10deg)
transform: perspective(17px)

transform: translateX(10px) rotate(10deg) translateY(5px)

Plus:

transform-function
transform-origin
transform-style

Following Emmet syntax things should look like this:

Trfskx-30deg {
    transform: rotate(30deg);
}
.Trfsky-0.5 {
    transform: scaleY(0.5);
}

We could also discuss the value of going a slightly different route, using the value as a prefix and the parameter as suffix(?) It may be easier for people to make sense of the class names. For example:

.SkewX-30deg {
    transform: skewX(30deg)
}
.ScaleY-0.5 {
    transform: scaleY(0.5);
}

A depart from what we do, but may be worth making an exception as in my opinion, it makes things much more readable.

In any case, we need to change things a little bit because we cannot plug suffix as parameters yet.

Thoughts?

Allowing "space" inside suffixes

Here is a typical use case (for transition): Trs-all_2s

Atomizer would replace the _ with a space:

.Trs-all_2s {
    transition: all 2s;
}
``

Plugging info at the top of atomic.css file

I think the config file could hold some "meta data" and output that at the top of atomic.css.
I'm thinking of author's name, project name, version(?), and stuff like that (time stamp too?)...

Allow to pass separated values in suffixes

I am thinking of how we could allow authors to create a rule like the one below by passing the value as a suffix:

transition-delay: 2s, 4ms;

.Trsde-<what should this be?>

List of things I noticed after pulling the latest today

  • As discussed, I think we should replace start and end occurrences with S and E, not necessary to reduce bytes but rather to make sure these standout and are seen by devs as offset values - that stand for start and end. I also think it will make things easier to read across rules/declarations. This is far from perfect, but I think it is better than keeping what we have now. Unfortunately, abstracting left and right keywords comes at a cost :-(
    Examples:
    • Mend would become ME,
    • Bgp-st would become Bgp-St,
    • Bd-start would become Bd-S,
    • Ta-s would become Ta-S,
    • Cl-start would become Cl-S,
    • .Bd-start-0 would become .Bd-S-0,
    • etc..
  • I think there is a problem with box-shadow because we need to be able to pass 4 length (offset-x, offset-y, blur-radius, spread-radius), not just 3, and we should also be able to pass inset as a value.
  • As discussed, it may be better to use a integer as suffix for font-size. Fz-a, Fz-b, Fz-c, etc. sound weird to me.
  • We should allow people to enter percentage (%) values without having to escape them. I think we should do that for them as I'm afraid people would have no clue. Actually, they may have no clue that they can use percentages in the firt place, so may be this is a moot point...
  • As discussed, we should remove the Dn class or add !important to it because as it is today it duplicates what we already have in the D-n class.

Clean up default options

Options currently given defaults by atomizer.js:

{
   require: [],
   morph: null,
   combineSelectors: true,
   minify: false,
   keepCamelCase: false,
   extCSS: '.css',
   banner: '',
   namespace: '#atomic',
   rtl: false
}

banner is used by atomizer.js

morph and require are used by AbsurdJS (via atomizer.js).

rtl and namespace are used by AtomicBuilder.js currently.

extCSS, combineSelectors, minify, and keepCamelCase I believe are not being used, and can be removed.

Expose namespace option via CLI tool

Right now namespace is not exposed via the CLI tool. (Or at best, support is there but not documented.) Need to make sure this is working for 2.0.0

rules.js depends on example-config.js

Right now rules.js require()'s example-config.js to get the $START and $END config values. This seems like something that should be passed in if it needs to be configurable, which means making the export a function rather than an array, I think. Do we still need those values to be configurable, @renatoi and @thierryk?

How to document rules to developers?

An option question that's come up is, how do we want to transform the json representation of rules (in rules.js) to documentation? What should this documentation look like, and what tool should we use to do the transformation?

@renatoi @thierryk thoughts?

Add a mergeConfigs() API to utils

We need to bring back the mergeConfigs() API we had in 1.0, so that various libs (like grunt-atomizer) can easily merge multiple configs before calling Atomizer APIs.

Add CLI options for generating default config

Right now the CLI tool requires you to pass a default config file, because at the very least we need the config preamble at the beginning of the config file (stuff like namespace, start, end are defined within config.) We should allow those config params to be passed as args to the CLI so that users won't have to manually create a config file to get started.

getConfig() should return a merge of generated config and passed-in config

getConfig() accepts an argument representing existing config which is currently used to determine if custom classes have been defined (otherwise a warning is displayed.) However, the config returned by getConfig() doesn't include any of this configuration, so a developer would still have to manually merge the newly generated config with the pre-existing config. This seems unhelpful, so we should have getConfig() just do the merge for you, and return the final configuration.

Add a base style sheet

Let's discuss the value of such style sheet in this project and if we think it makes sense to include one

What about introducing contextual selectors?

We often use rules like this one:

.menu-on .menu-button {
    display: block;
}

What if we created atomic classes to take care of this and remove the need of most of these rule?
Imaging this:

<button class="menu-on--D-b" ..>

Such class would produce this in atomic.css:

.D-b,
.menu-on .menu-on--D-b {
    display: block;
}
  • Pros:
    • selectors are grouped, there is no declaration redundancy
    • it's declarative, the logic is in the class itself
  • Cons:
    • if the contextual class changes, then authors would need to search and replace it in many places.

I don't think this would be a good idea after all, but it was worth writing it down :)

Break apart tests

Right now we have a few tests for getCss() that are a dumping ground for every unique type of class (hex values, hex + alpha, customs, child selectors, customs, etc). It'd be better if we could break this up into one test per class type, so we can be more explicit about having proper coverage for all syntax we support.

Can't use numerics as custom suffixes when allowSuffixToValue is true

Right now it's not possible to have a custom suffix that's numeric if a rule has allowSuffixToValue set to true, such as Fz-10. Currently such a class would be translated into:

.Fz-10 {
  font-size: 10;
}

...which isn't valid.

The problem is that sometimes numerics are valid values, such as in the case of z-index, font-weight, or line-height, but in all other cases, a unit of measure (eg px) would be required.

I propose that we add a boolean to the rules that basically declares that for a given rule, the suffix-to-value requires a unit of measure. Something like suffixRequiresUnit, though I'm not sure how to best word it. By default this setting would be true, but would be false for the exceptions such as the ones listed above.

@renatoi @thierryk thoughts?

Create a smart `LineClamp`

"Line clamping" is not a simple thing as it relies on a few things:

.LineClamp needs:

  • display: -webkit-box;
  • -webkit-box-orient: vertical;
  • overflow: hidden;

while a.LineClamp relies on those:

  • display: inline-block;
  • *display: inline;
  • zoom: 1;

and a.LineClamp:after on these (WebKit bug):

  • content: ".";
  • font-size: 0;
  • visibility: hidden;
  • display: inline-block;
  • overflow: hidden;
  • height: 0;
  • width: 0;

The above are the styles we need regardless of the number of lines to show, because for that we need a couple more declarations:

  • -webkit-line-clamp: <number of lines>;
  • max-height: <line-height * font-size>;

Not sure what is the best way to approach this. I'm thinking of a helper and a modifier would be the easiest way to go here.
And we'd pass both the number of lines and the max-height we want in the suffix?
Something like this may be:

<div class="LineClamp-372px">No more than 3 lines please (font-size is 16px and line-height is 1.5 in here)...</div>

The first digit is the number of lines we want followed by the height we need. This is a helper class, so I think we don't really have to stick to any particular syntax as long as it makes sense somehow without complicating things much.

Then helpers.css contains:

[class*=LineClamp] {
   display: -webkit-box;
   -webkit-box-orient: vertical;
   overflow: hidden;
}
a[class*=LineClamp] {
   display: inline-block;
   *display: inline;
   zoom: 1;
}
a[class*=LineClamp]:after {
   content: ".";
   font-size: 0;
   visibility: hidden;
   display: inline-block;
   overflow: hidden;
   height: 0;
   width: 0;
}

And Atomizer outputs this:

.LineClamp-372px {
   -webkit-line-clamp: 3;
   max-height: 72px; /* 16px * 1.5 * 3 */
}

Thoughts?

Note that I'd prefer to use [class|=LineClamp] instead of [class*=LineClamp] for this, but I think IE8 does not support the former :-(

Going all lowercase (via config)?

We know why we have chosen to capitalize Atomic classes (for a very good reason), but it seems many people are bothered by this. I'm wondering if we should allow users to go full lowercase... Even though it is not a smart move.

D-n can't be made !important

If you try and use a class like D-n!, it will render as:

.D-n\! {
  display: none;
}

However, if I use a suffix that's a value, such as Op-1!, then I get !important as expected:

.Op-1\! {
  opacity: 1 !important;
}

Seems that getCss() is rendering "rule" values without reference the property in the treeo array which has !important appended?

fyi @renatoi

New configuration format

The 1.x configuration format is overly complex and verbose, and no longer fits well with how we're using Atomizer to parse classes. Instead, we'll migrate 2.x to use a new config format that is class-centric, and then @renatoi will refactor/replace AtomicBuilder.js to no longer generate the 1.x config, but instead dump an array of classes into the config output, and then atomizer.js will parse those classes as necessary when generating the CSS. (Basically, we're cutting out the middle stage of configuration and going straight from classes to CSS.)

Custom classes/suffixes will continue to be supported in configuration as in 1.x.

Syntax for rgba() color

I think we could go this route:

.C-FFF\.4 {
    color: rgba(255, 255, 255, .4); 
}

Same as we have now, C- followed by hex value to what we'd add the transparency value.
The . in there can be used as marker since 1 (opaque) should be expressed as plain grb()/hex value.
Thoughts?

DRYing Rules

Currently the rules.js file has 2170 LoC and lots of duplication, that makes it harder to maintain because there is no way for changes in one style to affect others so we have to duplicate a lot of code over and over.

We can allow Rules to inherit from each other so that what we only write the code that different and reuse what is the same, below thee is on suggestion to simplify our Rules.css:

// rules.js
Atomizer.setRules([
    /**
     ==================================================================
     PADDING
     ==================================================================
     */
    // all edges
    {
        type: 'pattern',
        id: 'padding',
        name: 'Padding (all edges)',
        prefix: '.P-',
        properties: ['padding'],
        allowCustom: true,
        allowSuffixToValue: true,
        rules: [
            {suffix: '0', values: [0]},
            {suffix: 'inh', values: ['inherit']}
        ]
    },
    // top
    {
        parent: 'padding',
        id: 'padding-top',
        name: 'Padding top',
        prefix: '.Pt-',
        properties: ['padding-top'],
    },
    // end
    {
        parent: 'padding',
        id: 'padding-end',
        name: 'Padding end',
        prefix: '.Pend-',
        properties: ['padding-$END'],
    },
    ...
]);

module.exports = Atomizer.getRules();

An other advantage of this approach is that we can have rules being defined in different files and even allow the user to set his custom rules. But IMHO the best part is because we because it would make our rules.js file at least half the size.

More explicit syntax for hex values

Currently hex values are ambiguous, since they're just 3 or 6 digits in a suffix with no special char to set them apart. They can easily be confused with custom suffixes (eg, Fz-100 would incorrectly produce font-size: #100).

We need to introduce a more explicit way of specifying colors, eg C-#333

List of things to do before publish

  • Integration to Travis to run tests for the build.
  • Release cycle definition.
  • Add sources of intellectual property used.
  • Create grunt task to generate atomic.css (separate repo).
  • Update README with usage and configuration.
  • Create FAQ
  • Approval from OSWG

Add CLI option for outputting configuration

It'd be helpful if the CLI could output the config file generated during parsing, either in addition to the CSS (aka a sidecar) or in lieu of CSS. The file could be named similar to the value of --output, so like:

atomizer -c base-config.json -o myatomic.css *.html

Which would generate:

myatomic.css
myatomic.config.json

Or, we can have a new flag for config output which is like -o|--output and takes a filename.

Plug oldIE hacks wherever needed

We should plug IE hacks along with Ov-h and D-ib:

.D-ib {
    display: inline-block;
    *display: inline;
    zoom: 1;
}
.Ov-h {
    overflow: hidden;
    zoom: 1;
}

I've removed the Bfc helper classes as it will be meaningless to most users and also because it maps to overflow:hidden, so I think it's better people know what they are dealing with.

Remove dependency on AbsurdJS

Absurd adds extra overhead for not a lot of added value. The kind of conversions we're doing aren't particularly complicated and could probably be done more efficiently with a little custom JS. Will explore what it'd take to pull out Absurd, and do the conversions ourselves.

fyi @renatoi

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.