Is the `Color` module gone for good?


#1

Just wondering what happened to the old core Color module? Is it gone for good, and can someone remind me why? Will there be something to replace it, or should we just re-publish it as a library under new coordinates? Thanks.


#2

It’s reported as gone in the changelog so I guess so.

Maybe it was there to help with css stuff and whatnot and thus it’s much better as an external library.


#3

The Color module in old core was useful in that it provided a common definition of color, that most other packages tended to accept and agree on. I can see that color is not a very ‘core’ thing so it does make sense for it not to be there any more, except for the usefulness of having a common and shared definition.

The type of Color was:

type Color
= RGBA Int Int Int Float
| HSLA Float Float Float Float

Contrast that with a concept like a 2d dimensional point. Some packages have (Float, Float), and some have {x : Float, y : Float} and I am sure there are other definitions too. It makes mixing these packages awkward as one is always translating between the two definitions.

If two packages have definitions like:

type alias Point2d = {x : Float, y: Float}
type alias Coords = {x : Float, y: Float}

The point types are actually compatible between the two packages, since they are just aliases onto the same type.

This is not the case with type definitions. If it were:

type Point2d = Point2d {x : Float, y: Float}
type Coords = Point2d {x : Float, y: Float}

Despite having identical definitions, these do not flow accross without wrangling the constructors.

So if the Colordefinition above is simply lifted into each and every module that needs it, working with color will be more awkward than it previously was.

I think by that reasoning it makes sense to move the Color module into a package somewhere fairly low down the food chain, perhaps as elm-community/color?

Would doing so step on any toes regarding future plans for color? I did read something on Slack about introducing a better color coordinates definition for more designer oriented colors rather that computer oriented, but of course it is lost to the slack sands of time.


#4

This feels like the proper place to me.

Even if designer-oriented colours are introduced at some point, we’ll keep need for the RGB(A) and HSL(A) definitions because they are at the core of how CSS (as well as the HTML5 canvas 2d context) talk about colours.


#5

Yes, that is what I was thinking.

An example might be this package:https://github.com/Janiczek/distinct-colors

Gives you a more high-level way of working with color, but builds on top of Color. Same would be true of more sophisticated color spaces; the computer still needs RGB to render the pixels.


#6

I think having raw records for colors makes sense, because then everything would be compatible automatically. If you need a custom type of colors you can just choose the ones you want to handle. So we’d have:

type alias Rgb256 =
    { red : Int
    , green : Int
    , blue : Int }

type alias Rgb1 =
    { red : Float
    , green : Float
    , blue : Float }

type alias Hsv =
    { hue : Float
    , saturation : Float
    , value : Float }

type alias Hsl =
    { hue : Float
    , saturation : Float
    , lightness : Float }

#7

The trouble with that is that if I want to provide a public API function that takes a color as argument, I now need 4 versions:

drawTheColourfullThingRgb256 : Rgb256 -> Html msg
drawTheColourfullThingRgb1 : Rgb1 -> Html msg
drawTheColourfullThingRgbHsv : Hsv -> Html msg
drawTheColourfullThingRgbHsl : Hsl -> Html msg

When before I just needed Color?


#8

Well, my thinking is that your function only accepts the color that you actually want, and it’s up to the caller to provide it, using a standard conversion function from whatever color they have.


#9

The way the old Color module worked, was that Color was an opaque type. Then it had functions to extract different color spaces:

toHsl : Color -> { hue:Float, saturation:Float, lightness:Float, alpha:Float }
toRgb : Color -> { red:Int, green:Int, blue:Int, alpha:Float }

That means code can be agnostic about the input color space and still work.


#10

You can also then have things like this. Not sure if it’s a good idea or not, but it shows why raw records are very convenient.

type alias WithAlpha color = { color | alpha : Float }

type alias Rgba1 = WithAlpha Rgb1

#11

It also means that if you have a color not in the Color type, you have to guess which type to convert to before passing it in, potentially triggering double conversion. I think making it the responsibility of the caller to provide data in the way the function wants it makes more sense.


#12

Maybe it would lead to double conversion, but I think the most likely case is conversion down to RGBa for rendering - this is the conversion the computer will be doing anyway to colour pixels on the screen. You can pas HSL as CSS, but it will still be getting converted to RGBa, so might as well stick with that conversion path.


#13

Exactly!
So why not just make the function take an Rgba256 and that’s it? If you have an Hsl then you call drawTheColourfulThing (Hsl.toRgba256 myHslColor) and that’s it. Not that hard to use, and completely open with what it expects.


#14

So, to get elm-community/typed-svg to 0.19, I think they way to go will be to add a very simple definition of a Color type to it, that is identical to the old one; makes upgrading to the new release as simple as possible.

If a better colour module comes along somewhere further down the food-chain, swap over to that when it happens.


#15

I published this based on the old Color module, but tried to make it even more minimal. As described in the readme, this is a temporary solution and will deprecate and move over as the official line develops.

https://package.elm-lang.org/packages/the-sett/elm-color/1.0.0/


#16

Could you point me to the changelog? I can’t seem to find it. :no_mouth:


#17

Indeed, I can’t seem to find it from a Google search. It’s a file in the compiler’s repo: https://github.com/elm/compiler/blob/master/upgrade-docs/0.19.md


#18

There was a discussion on the issue tracker for that module, and it has now moved to https://github.com/avh4/elm-color/issues

To coordinate, and pool our resources, I would suggest getting involved there.


#19

Just noting that this is getting close to being published. If anyone is interested in reviewing the progress or the API, you can do so here: https://github.com/avh4/elm-color/pull/9


#20

I still think this is way too complicated to have as a standard type. It’s perfectly fine to have color manipulation libraries, but I would advise a regular module that wants to accept color input or give color output to use plain records.

That way you will be compatible with any advanced color manipulation library that accepts plain records, but you will not have to depend on it.