glamor icon indicating copy to clipboard operation
glamor copied to clipboard

Respect array/arguments order of css()

Open esamattis opened this issue 7 years ago • 1 comments

New issue from https://github.com/threepointone/glamor/issues/226#issuecomment-318631505

An array or multiple arguments can passed to the css() function but that order is not respected when the css is generated. The style objects are just merged into a one object which is then used to generate the css. This makes the style ordering bit random when existing style keys are being overridden.

Example: https://codesandbox.io/s/qjG2XvykR

In real world code I've hit this with glamorous when I have wanted to extend a component and change it's media query behaviour.

Example: https://codesandbox.io/s/VPAvP6mGO

Fixing this would also make the infamous shorthand properties less brittle when extending components in glamorous. Ie. this would work as expected https://codesandbox.io/s/jzgxvZov

It think it comes down to the fact that when a key is being overridden in an object it's position stays the same.

For example here foo is the first key even thou it's the last one set.

> Object.keys(Object.assign({foo: 1}, {bar: 2}, {foo: 3}))
[ 'foo', 'bar' ]

esamattis avatar Jul 28 '17 12:07 esamattis

Deleting existing properties before assignment might solve the problem.

function preserveOrder(...styles) {
    return styles.reduce((acc, style) => {
    	Object.entries(style).forEach(([prop, val]) => {
            if (prop in acc) { delete acc[prop] }
            acc[prop] = val
        })
        return acc
    }, {})
}

const mergedStyles = preserveOrder({foo: 1}, {bar: 2}, {foo: 3})
Object.keys(mergedStyles) // => [ 'bar', 'foo' ]

marzelin avatar Sep 02 '17 10:09 marzelin