kripod/otion

Styling a child element using data-attribute selector

efflam opened this issue ยท 11 comments

Description

It's currently impossible to style a child element using a data-attribute selector.

Reproduction

https://codesandbox.io/s/pensive-thunder-ffsow?file=/src/App.js

Expected behavior

The child element should be blue when hovering the parent as seen in this example implemented with emotion:
https://codesandbox.io/s/emotion-vz1ll?file=/index.js

Actual behavior

The child element is not styled when hovering the parent

Thank you for the submission!

This is an atomic CSS library which only allows a limited set of selectors to be used:

/* Extracted from the `csstype` package */

export type SimplePseudos =
  | ":-khtml-any-link"
  // Other vendor-prefixed pseudosโ€ฆ
  | "::-webkit-slider-thumb"
  | "::after"
  | "::backdrop"
  | "::before"
  | "::cue"
  | "::cue-region"
  | "::first-letter"
  | "::first-line"
  | "::grammar-error"
  | "::marker"
  | "::placeholder"
  | "::selection"
  | "::spelling-error"
  | ":active"
  | ":after"
  | ":any-link"
  | ":before"
  | ":blank"
  | ":checked"
  | ":default"
  | ":defined"
  | ":disabled"
  | ":empty"
  | ":enabled"
  | ":first"
  | ":first-child"
  | ":first-letter"
  | ":first-line"
  | ":first-of-type"
  | ":focus"
  | ":focus-visible"
  | ":focus-within"
  | ":fullscreen"
  | ":hover"
  | ":in-range"
  | ":indeterminate"
  | ":invalid"
  | ":last-child"
  | ":last-of-type"
  | ":left"
  | ":link"
  | ":only-child"
  | ":only-of-type"
  | ":optional"
  | ":out-of-range"
  | ":placeholder-shown"
  | ":read-only"
  | ":read-write"
  | ":required"
  | ":right"
  | ":root"
  | ":scope"
  | ":target"
  | ":valid"
  | ":visited";

While the use of an invalid pseudo selector throws an error in TypeScript, JavaScript doesn't warn about the issue. I think there should be a runtime warning emitted about invalid selectors during development, accompanied with documentation about the phenomenon.

Adding this to the list of debug warnings to be emitted, see #2 for details.

jgoux commented

So you can't target children when defining the styles right? It seems like a big limitation no?

Thinking about layout components, how would you implement a margin based Stack component ("& > * + *": { marginTop: 8 }) using otion?

@jgoux I imagine a way to go for a Stack component could be to wrap the children.
@kripod how would you handle a use-case like the one in the codesandbox ? Would you track the hover state in JS and style the children directly based on state ?

@efflam Yes, that's exactly how it should be done, as also suggested by Styletron (please see the Descendant Hover section for an example).

@jgoux Please check out this opinion about the * + * selector:

<Stack> shouldn't use the so-called lobotomised owl selector (* + *) to avoid wrapper elements around child nodes because it doesn't own those nodes. Why? You're mixing CSS from multiple owners on a single node, meaning their styles can clash with yours, breaking the stack.

โ€“ Mark Dalgleish

See how composable the wrapped children become: https://twitter.com/markdalgleish/status/1261282811421417472

I agree that not being able to use attribute selectors feels like a very strong concession for any css library. For example, styling links with [target='_blank'] seems like a very common use-case. Or combining selectors, such as :not(:first-child) etc. which do work, but throw typescript errors.

I would like to note that other atomic css libraries such as stitches have a way of supporting arbitrary selectors (although their solution is of course not applicable here).

Maybe one could add a selectors API that supports arbitrary strings, something like this:

const link = css({
  selectors: {
    "[target='_blank']::after": {
        content: "'โ†—'",
    },
  },
});

What do you think @kripod?

@biowaffeln That's a good idea. The treat library does something very similar to that, while retaining type safety. I support the selectors key, as it feels like an escape hatch from strong atomicity.

Advanced selectors including selector, lists are now supported! ๐ŸŽ‰

Please refer to the updated documentation for information about their usage.

@all-contributors please add @efflam for ideas!

@kripod

I've put up a pull request to add @efflam! ๐ŸŽ‰

@all-contributors please add @biowaffeln for ideas!

@kripod

I've put up a pull request to add @biowaffeln! ๐ŸŽ‰