Giter Site home page Giter Site logo

japgolly / scalacss Goto Github PK

View Code? Open in Web Editor NEW
338.0 15.0 51.0 12.64 MB

Super type-safe CSS for Scala and Scala.JS.

Home Page: https://japgolly.github.io/scalacss/book

License: Apache License 2.0

Scala 98.15% Shell 1.28% Java 0.58%
scala css scalajs type-safe type-safety scalajs-react scalatags

scalacss's Introduction

ScalaCSS

Build Status Gitter Latest version Javadocs

ScalaCSS aims to bring type-safety and clarity to

  • creating CSS
  • using CSS
  • maintaining CSS
  • correctness of CSS

The goals and vision of the project are documented in its requirements. Most requirements are satisfied; some will be addressed a little later.

Documentation

Documentation is here.

Support

If you like what I do —my OSS libraries, my contributions to other OSS libs, my programming blog— and you'd like to support me, more content, more lib maintenance, please become a patron! I do all my OSS work unpaid so showing your support will make a big difference.

scalacss's People

Contributors

a1kemist avatar allantl avatar baweaver avatar cquiroz avatar ex0ns avatar fabiopinheiro avatar freexd avatar gbeaty avatar gitter-badger avatar grant avatar grzesiul avatar japgolly avatar joprice avatar maanaben avatar malcheg avatar mike-neck avatar mikla avatar ptxmac avatar scala-steward avatar scalawilliam 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

scalacss's Issues

ReactDefaults ?

Current Defaults trait full fills general needs , what about ReactDefaults which contains react specific helpers .

trait ReactDefaults extends Defaults {

  implicit override def register: Register = ???

}

its good to have register which will prefix class names with react component name , at this moment i am not sure weather its possible or not!

Mixins not allowed in media queries

  var bar = mixin(
    backgroundColor.yellow
  )
  val foo = style("foo")(
    media.maxWidth(100 px)(
      bar
    )
  )

produces the following compiler error:

overloaded method value apply with alternatives:
[error]   (h: scalacss.AV,t: scalacss.AV*)scalacss.DslBase.ToStyle <and>
[error]   (avs: scalacss.AVs)scalacss.DslBase.ToStyle
[error]  cannot be applied to (scalacss.StyleS)
[error]     media.maxWidth(100 px)(

Add a colour literal macro

I'd like to replace:

"#123".color
"#112233".color

with

#"123"
#"112233"
#"11223" // compile error len=5
#"ffeexa" // compile error x

unsafeChild not allowed in media queries

  val foo = style("foo")(
    media.maxWidth(100 px)(
      unsafeChild("bar")(
        backgroundColor(yellow)
      )
    )
  )

should produce:

  @media(max-width: 100px) {
    .foo .bar {
      background-color: yellow;
    }
  }

But it does not compile, failing with:

overloaded method value apply with alternatives:
[error]   (h: scalacss.AV,t: scalacss.AV*)scalacss.DslBase.ToStyle <and>
[error]   (avs: scalacss.AVs)scalacss.DslBase.ToStyle
[error]  cannot be applied to (scalacss.Style.UnsafeExt)
[error]     media.maxWidth(100 px)(

Optimise: Reduce Scala.JS output size

Stats from my simple scalajs-react project ...

_fastOptJS_ :

 1.2M Mar 25 07:52 scalacss-playground-fast-opt.js ( without scalacss)
 3.4M Mar 25 07:53 scalacss-playground-fast-opt.js (with scalacss)

_fullOptJS_ :

231K Mar 25 07:55 scalacss-playground-opt.js ( without scalacss)
655K Mar 25 07:54 scalacss-playground-opt.js (with scalacss)

Prevent need for shapeless import to use StyleC

StyleC callsite requires this

import shapeless.syntax.singleton._

or else one gets confusing errors like this:

[error] /home/.../Blah.scala:261: type mismatch;
[error]  found   : Symbol
[error]  required: Symbol with shapeless.tag.Tagged[String("req")]
[error]           *.reqAutoComplete('req)(r => _('desc)(d =>
[error]                             ^
[error] /home/.../Blah.scala:261: missing parameter type for expanded function ((x$24) => x$24(scala.Symbol("desc"))(((d) => $less.div($less.div(r, v.display), $less.div(d, v.desc)))))
[error]           *.reqAutoComplete('req)(r => _('desc)(d =>
[error]                                        ^
[error] two errors found

Change so that import isn't required.

When multiple media queries are used, only the the last is generated

When specifying multiple media queri

  val foo = style("foo") {

    (media.maxWidth(100 px)) {
      content := "\"big\""
    }

    (media.minWidth(100 px)) {
      content := "\"small\""
    }
  }

should produce:

@media (min-width:100px) {
  .foo {
    content: "small";
  }
}

@media (max-width:100px) {
  .foo {
    content: "big";
  }
}

However, it appears only the last media query in the list (minWidth in this case) shows up in the result.

Reuse style tags - GlobalRegistry.onRegistration(_.addToDocument())

 GlobalRegistry.register(
      GlobalStyle,
      NavMenu.Style,
    HomePage.Style)
    GlobalRegistry.onRegistration(_.addToDocument())

currently its creating new style tag for every new registration

it looks like there is constrain on number of style tags

IE. :) They had a limit on 31 stylesheets at one point, and a max limit on the number of selectors allowed in a stylesheet. If you imported things with @ import you could only do so 31 at a time per level or something.
I have hit that limit before, in a framework that pretty much gave every component/widget its own stylesheet and some of those created their own dynamic style tags on the fly.
We ended up cheating by sharing the same dynamic style tag across all that needed it.
Version 3 of the framework changed approaches so we're not even close to the limit anymore.

It would be cool if we reuse style tags instead of creating new ones!

Composing styles (named and unnamed) causes unwanted name clash

The following app generates two classes with identical names:

import japgolly.scalajs.react._
import japgolly.scalajs.react.vdom.all._
import japgolly.scalajs.react.extra._
import japgolly.scalajs.react.extra.router._
import japgolly.scalacss.Defaults._
import japgolly.scalacss.ScalaCssReact._
import org.scalajs.dom.document
import scala.scalajs.js.JSApp
import org.scalajs.dom.raw.HTMLStyleElement

import com.ccadllc.monocle.common._

import components._
import service._

import japgolly.scalacss.Color
import japgolly.scalacss.Defaults._

object SampleStyles extends StyleSheet.Inline {

  import scala.language.postfixOps
  import dsl._

  val outer = style("outer")(
    fontWeight.bold
  )

  // If left unnamed, seems to inherit the name of 'outer' 
  // "[CSS WARNING] .outer -- Another style in the register has the same classname."
  val inner = style(
    color.red,
    outer
  )
}

object StyleBugApp extends JSApp with MainContext {

  override def main: Unit = {
    SampleStyles.addToDocument()

    React.render(
      div(SampleStyles.outer,
        div(SampleStyles.inner)
      ), document.body)
  }
}
.outer {
  font-weight: bold;
}

.outer {
  color: red;
  font-weight: bold;
}

If you either have both styles go nameless (use autogenerated names) or give both names, the problem goes away.

Doc: Add a DSL guide

For instance, it's not very clear that there's a difference between style and styleS in inline styles.

Abandon StyleC

It might be time to go back to the drawing board for StyleC. I barely use it and I was its biggest proponent. Does anyone else use it?

Similar to the Router situation in scalajs-react, it might be better to trade-in a little safety for a much larger portion of usability and Scala-friendliness. Would also allow us to drop the Shapeless dependency.

Any plans about SBT plugin?

It will be cool to use ScalaCSS in compile time. For example I have an Scala.js module named my-super-components. I have creating a set of applications using this module. Sometimes I want dark theme, sometimes light. So I make two ScalaCSS modules (just jar with classes) and plug one of them to project by perforce. Then I enable scalaCSSPlugin in my project. After compilation I will have js file which creates DOM and static css for it.

Add loose & strict dialects of inline stylesheet

I like my styles strict - unsafe things are marked as such, styleC used for composites & children.
Not everyone needs/wants that level of safety, or the usability trade-off made to achieve it.

Inline styles can be split into loose and strict variants, with strict being as is, and loose providing a nicer DSL for unsafe children and unsafeRoot.

Otto also suggested providing types for html elements (in unsafe children) to avoid using strings.

Psuedoclasses don't mix well with unsafeChild

I have the following ScalaCSS. I'm trying to change the style of 'inner' when 'outerStyle' is hovered on.

  val outerStyle = style(
    cursor.none,

    &.hover(
      cursor.pointer,
      unsafeChild("inner") {
        display.block
      }
    )
  )

// I thought this would generate:

  .outerStyle {
    cursor: none;
  }

  .outerStyle:hover {
    cursor: pointer;
  }

  .outerStyle:hover .inner {
    display: block;
  }

// But instead it generates the hover on the .innner:

  .outerStyle {
    cursor: none;
  }

  .outerStyle:hover .inner {
    cursor: pointer;
  }

  // Note the hover is moved onto the .inner unsafeChild instead of on .outerStyle
  .outerStyle .inner:hover {
    display: block;
  }

What's interesting is the cursor style does get applied in the right place. The same hover condition is treated differently whether there is a unsafeChild mixed in.

Optimise: Speed up Scala.JS fastOptJS time

Using ScalaCSS adds around 40% more time to fastOptJS in an 8600 LoC Scala.JS project.

I ran

;clean ;compile ;fastOptJS
;clean ;compile ;fastOptJS

without ScalaCSS, with ScalaCSS on classpath but unused, used a little (2 styles), and used more (14 styles). Results are of compile/fastOptJS (x2) times in seconds.

   before: 44/10, 26/7
   addDep: 42/10, 26/6
useLittle: 45/13, 28/9
  useMore: 43/14, 29/10

order of media queries?

val test = style(display.flex,
      flexDirection.column,
      boxShadow := "0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24)",
      media.maxWidth(740 px)(
        boxShadow := "none"
       )
      )

its generating media

@media (max-width:740px) {
  .Test_Style-0002 {
    -webkit-box-shadow: none;
    box-shadow: none;
  }
.Test_Style-0002 {
  display: -webkit-flex;
  display: flex;
  -webkit-flex-direction: column;
  flex-direction: column;
  -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12), 0 1px 2px 0 rgba(0, 0, 0, 0.24);
}

if media query is on top box-shadow is not overriden .

Here is codepen to demonstrate this (move media query to bottom and resize window)
http://codepen.io/chandu0101/pen/MwEoNY

Media queries always on top?

I am trying to mimic some CSS in the wild that looks like this:

.main {
  padding: 20px;
}
@media (min-width: 768px) {
  .main {
    padding-right: 40px;
    padding-left: 40px;
  }
}

When in this order, browsers respect all values, but if the media queries are above, then they are not respected and they get overridden. So when I write a direct translation like:

  ".main" - (
    padding(20 px),
    &(media.minWidth(768 px)) - (
      paddingRight(40 px),
      paddingLeft(40 px)
    )
  )

It puts the media queries up top. I can't even break apart the rules to keep the media queries from going to the top. And even when I write this:

  ".main" - padding(20 px)

  "@media (min-width: 768px)" - (
    &(".main") - (
      paddingRight(40 px),
      paddingLeft(40 px)
    )
  )

I get:

.main {
  padding: 20px;
}

@media (min-width: 768px) .main {
  padding-right: 40px;
  padding-left: 40px;
}

Which is not the same as having .main nested inside. Any ideas on how to achieve my goal?

Compose only checks CSS name, not name + value for conflicts

Given the following styles:

  val styleA = style(
    display.block
  )

  val styleB = style(
    display.block,
    styleA
  )

The console emits the following warning:

// [CSS WARNING] .scalacss-0002 -- display overridden by display."

Since both 'display' keys have the same value 'block' there really shouldn't be a warning. Ideally the conflict checker should compare both attribute AND value. And display the conflicting value in the string (in addition to key name). For example, the following code:

  val styleA = style(
    display.block
  )

  val styleB = style(
    display.flex,
    styleA
  )

should generate a warning:

// [CSS WARNING] .scalacss-0002 -- 'display: block' overridden by 'display: flex'."

Type: textDecoration

textDecorationLine doesn't work in Chrome.

Contrary to the syntax on MDN, "line-through red" dosen't work either. "line-through" by itself does.

text_decoration <'text_decoration_line'> || <'text_decoration_style'> || <'text_decoration_color'>

Psuedoelements/classes not allowed in media queries

  val foo = style("foo")(
    media.maxWidth(100 px)(
      &.hover {
        backgroundColor(yellow)
      }
    )
  )

Produces the following compiler error:

overloaded method value apply with alternatives:
[error]   (h: scalacss.AV,t: scalacss.AV*)scalacss.DslBase.ToStyle <and>
[error]   (avs: scalacss.AVs)scalacss.DslBase.ToStyle
[error]  cannot be applied to (scalacss.DslBase.ToStyle)
[error]     media.maxWidth(100 px)(
[error]                   ^

styleF suffix fn - customise per A, apply everywhere

When specifying a domain to styleF, the suffix fn can be specified alongside it. To do so is repetitive though. I'd rather eithier

  • combine it with Domain (can do! It not connected to Nyaya)
  • make a new class that pairs Domain with a suffix fn
  • make the suffix fn implicit

Doc: customisation guide

Document how to customise or create custom:

  • attributes
  • pseudo selectors
  • media queries (?)
  • CSS values
  • CSS format (string renderer)
  • defaults

Unify the condition DSL

There was originally:
&.psuedo
&(media)
&(cond)

With 0.3.0 cond can apply to styles directly, only need &.psuedo now

standalone style nesting

It is clear how to nest styles one inside another in InlineMode, but it is not clear how it works in standalone mode (if it is implemented). It will be great if it will be possible to deal with style nesting in a similar to LESS way

borderBottomColor (and possibly others) not accepting string color

When attempting something like borderBottom(1 px, solid, "#eee") in a standalone sheet, I get the following error whereas borderBottomColor("#eee") works.

diverging implicit expansion for type scalacss.ValueT.==>[String,B]
starting with method ruleChain in class Rules
    borderBottom(1 px, solid, "#eee")

I saw 9424999 and I see that I can do borderBottom(1 px, solid, Color("#eee")) (but sadly I have to manually import scalacss.Color though I know I could use rgb in ColorOps). Is this limitation by intention? If so it might be worth mentioning in the guide if not already present (I could not find it).

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.