-
Notifications
You must be signed in to change notification settings - Fork 187
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to handle descendant selection of pseudo-states? #10
Comments
In general, having parents affect the styles of their children is a pattern we want to avoid, but I can see why this particular example might occur within a single component's markup. I'm reluctant to see patterns like this become first class citizens, but we do need some escape hatch way of writing arbitrary CSS (whether it's globally scoped or scoped to the generated selector), akin to |
One hack which we're cautiously using right now works only because of the way pseudo-selectors are handled.
Which is totally not part of the API, and I fully expect it to break at some point. |
Come to think of it, this also might break on merge |
Interesting! That definitely was not an intention of the API design, but perhaps is something we should support for the sake of API simplicity. I don't see any immediate reason for that to break on merging. |
I also just ran into this case. I'll proceed with @zgotsch's workaround. Is there anything specific that we could do to make this a first-class citizen so I could rely on it and not worry about this breaking in future releases? I'm happy to contribute to the project with a little direction :-) |
Actually, thinking about this more, I think that this is a scenario that would be better to avoid supporting and we should find another way to work around this issue. Here's the kind of API I'd like to see (and maybe help build): const styles = StyleSheet.create({
parent: {
':hover': {
backgroundColor: 'white',
nonCssPropertyShouldCreateAnotherClass: {
color: 'black',
},
},
},
})
const { parentClassName, nonCssPropertyShouldCreateAnotherClassClassName } = cssWithDecendents(styles.parent)
// parentClassName === 'parent-blahblah'
// nonCssPropertyShouldCreateAnotherClassClassName === 'nonCssPropertyShouldCreateAnotherClass-blahblah' Which would produce classes with the following CSS: .parent-blahblah:hover {
background-color: 'white';
}
.parent-blahblah:hover .nonCssPropertyShouldCreateAnotherClass {
color: 'black';
} Obviously, the names are up for debate. But I think an entirely new method should be used and we shouldn't overload the Thoughts 💭? |
@kentcdodds I really like that interface. Seems like a great balance between being flexible and still sorta following the "inline-styling way". Some random thoughts:
|
Seems reasonable to me 👍 As for depth, I don't see why aphrodite should concern itself with enforcing a depth ¯_(ツ)_/¯ while I agree developers should probably not go too deep on this, I don't think we'd have to put in extra effort to combat it. It'd turn into a serious code smell before it caused aphrodite trouble I think. |
If there was an API for defining a ruleset you could easily determine which are properties vs a descendantClass: const child = StyleSheet.createRuleset({
color: 'black'
}
const styles = StyleSheet.create({
parent: {
':hover': {
backgroundColor: 'white',
child: child
}
}
})
const { parent, child } = css(styles)
// parent === 'parent-blahblah'
// child === 'child-xyz' |
Ok, I think that we've got two solid ideas, which should we go with? Use const styles = StyleSheet.create({
parent: {
':hover': {
backgroundColor: 'white',
'>child': {color: 'black'}
}
}
})
const { parent, child } = css(styles.parent)
// parent === 'parent-blahblah'
// child === 'child-xyz' Have a special API for creating rule sets const styles = StyleSheet.create({
parent: {
':hover': {
backgroundColor: 'white',
child: StyleSheet.createRuleset({color: 'black'}
}
}
})
const { parent, child } = css(styles.parent)
// parent === 'parent-blahblah'
// child === 'child-xyz' I'm not sure which I like better. Would love to get feedback from others. |
I like the simplicity (for the developer using aphrodite) of The I think that this would be a misleading choice of api. Am I misinterpreting? Also, is the goal to be able to support both direct and arbitrary descendents? It seems like arbitrary descendents should cover all desired use cases since the class names are uniquely generated, whereas direct descendents would not. |
Agreed. That would be misleading... I also think that I prefer the simplicity of the |
Also, I think I agree with this:
|
@montemishkin You are correct, the |
Would we still want to have this syntax if we supported |
Is there a reason we couldn't just do: const styles = StyleSheet.create({
parent: {
':hover': {
backgroundColor: 'white',
child: {color: 'black'}
}
}
})
const { parent, child } = css.descendents(styles.parent)
// parent === 'parent-blahblah'
// child === 'child-xyz' I'm pretty sure that we can just say that if the value of a css property is an object, consider it a descendant. As for the |
This wouldn't work, because we sometimes allow real objects as values for css properties, for instance with |
Just a drive-by kibbitz, but one possible syntax for "direct or indirect descendant" could be ">>descendentClass". |
Okay, I played around with a couple different alternatives, and it looks like we haven't really talked about what gets done with the results of
Would we be doing I also played around with something that looks like
but I don't think that we'll actually be able to generate appropriate class names using this interface (even though it looks even nicer than the |
Just a drive-by, but I really like the second API, Emily (the one with |
@zgotsch I like that too. I'm a little scared of a situation like this though:
Presumably we would want to generate CSS like...
but then you might want
to do the same thing? But we can't make
Sorry for brain dumping. I'm gonna play around with this... |
Summary: It turns out descendant selectors are kinda hard. In particular, it's difficult to let *descendants have unique classnames* for themselves, at the same time as allowing *merging between styles which contain descendant selectors*. This pull request attempts to do both of these things. The code is a bit messy, so I'll lay out what's going on in this pull request. Please ask questions, if something is confusing! The Aphrodite code is nice because it's all fairly easily understood, and I'm afraid that this adding too much complexity. An example of the syntax (and an example for the explanation in this commit message), consider: ```js const styles = StyleSheet.create({ parent: { '>>child': { color: "red" }, ':hover': { '>>child': { color: "blue" }, '>>otherchild': { color: "white" } }, }, altparent: { ':hover': { '>>child': { color: "green" } } } }); The basic flow of this diff is: 1. In `StyleSheet.create`, we recurse through the passed-in styles, and find each of the descendant selectors (which have keys that look like `>>blah`). In the example above, it would find `parent['>>child']`, `parent[':hover']['>>child']`, `parent[':hover']['>>otherchild']`, and `altparent[':hover']['>>child']`. In each place, we: - generate a class name for that descendant selector. This is based on the class name of the parent class, as well as the key name. For example, if the class name for `styles.parent` was `parent_abcdef`, we might generate the class name `parent_abcdef__child` for `parent['>>child']`. - tag the style by adding a `_names` object, with the class name as a key of the object. For example, `parent['>>child']` would end up looking like `{ color: "red", _names: { parent_abcdef__child: true } }`. - collect a map of each of the keys (without the `>>` bit) to their class names. For example, for `styles.parent`, we would generate a map that looks like `{ child: "parent_abcdef__child", otherchild: "parent_abcdef__otherchild" }`. We merge in the map from key to class name into the generated style, so that the class names can be accessed using a syntax like `styles.parent.child`. 2. When *parent* styles are passed into `css()`, their styles are merged together. If one style overrides another's descendant styling, the `_names` object will be merged together and will contain all of the associated class names. For example, when evaluating `css(styles.parent, styles.altparent)`, we would end up with merged styles looking like: ``` { '>>child': { color: "red", _names: { parent_abcdef__child: true }, }, ':hover': { '>>child': { color: "green", _names: { parent_abcdef__child: true, altparent_123456__child: true, }, }, '>>otherchild': { color: "white", _names: { parent_abcdef__otherchild: true }, } } } ``` We then generate a map from the descendent keys to all of the class names that could be associated with a given key by recursing and looking at each of the `_names` objects. For example, the map would look like: ``` { '>>child': ["parent_abcdef__child", "altparent_123456__child"], '>>otherchild': ["parent_abcdef__otherchild"] } ``` When generating the styles, we look at this map and then generate styles for each of the classnames listed. This is so that these styles will match up with uses of both `css(styles.parent.child)` and `css(styles.altparent.child)`. For example, when generating the `style[':hover']['>>child']` styles, we generate: ``` .parent_abcdef-o_O-altparent_123456:hover .parent_abcdef__child { ... } .parent_abcdef-o_O-altparent_123456:hover .altparent_123456__child { ... } ``` 3. When *descendant* styles are passed into `css()`, like `css(styles.parent.child)`, we simply return the associated class name (in this case, `"parent_abcdef__child"`) in the output. Fixes #10 Test Plan: - `npm run test` - `cd examples && npm run examples`, then visit http://localhost:4114/ and see that the last line starts green and when "Hover over me" is hovered, the other part turns blue. @zgotsch @jlfwong @kentcdodds @montemishkin
Summary: It turns out descendant selectors are kinda hard. In particular, it's difficult to let *descendants have unique classnames* for themselves, at the same time as allowing *merging between styles which contain descendant selectors*. This pull request attempts to do both of these things. The code is a bit messy, so I'll lay out what's going on in this pull request. Please ask questions, if something is confusing! The Aphrodite code is nice because it's all fairly easily understood, and I'm afraid that this adding too much complexity. An example of the syntax (and an example for the explanation in this commit message), consider: ```js const styles = StyleSheet.create({ parent: { '>>child': { color: "red" }, ':hover': { '>>child': { color: "blue" }, '>>otherchild': { color: "white" } }, }, altparent: { ':hover': { '>>child': { color: "green" } } } }); The basic flow of this diff is: 1. In `StyleSheet.create`, we recurse through the passed-in styles, and find each of the descendant selectors (which have keys that look like `>>blah`). In the example above, it would find `parent['>>child']`, `parent[':hover']['>>child']`, `parent[':hover']['>>otherchild']`, and `altparent[':hover']['>>child']`. In each place, we: - generate a class name for that descendant selector. This is based on the class name of the parent class, as well as the key name. For example, if the class name for `styles.parent` was `parent_abcdef`, we might generate the class name `parent_abcdef__child` for `parent['>>child']`. - tag the style by adding a `_names` object, with the class name as a key of the object. For example, `parent['>>child']` would end up looking like `{ color: "red", _names: { parent_abcdef__child: true } }`. - collect a map of each of the keys (without the `>>` bit) to their class names. For example, for `styles.parent`, we would generate a map that looks like `{ child: "parent_abcdef__child", otherchild: "parent_abcdef__otherchild" }`. We merge in the map from key to class name into the generated style, so that the class names can be accessed using a syntax like `styles.parent.child`. 2. When *parent* styles are passed into `css()`, their styles are merged together. If one style overrides another's descendant styling, the `_names` object will be merged together and will contain all of the associated class names. For example, when evaluating `css(styles.parent, styles.altparent)`, we would end up with merged styles looking like: ``` { '>>child': { color: "red", _names: { parent_abcdef__child: true }, }, ':hover': { '>>child': { color: "green", _names: { parent_abcdef__child: true, altparent_123456__child: true, }, }, '>>otherchild': { color: "white", _names: { parent_abcdef__otherchild: true }, } } } ``` We then generate a map from the descendent keys to all of the class names that could be associated with a given key by recursing and looking at each of the `_names` objects. For example, the map would look like: ``` { '>>child': ["parent_abcdef__child", "altparent_123456__child"], '>>otherchild': ["parent_abcdef__otherchild"] } ``` When generating the styles, we look at this map and then generate styles for each of the classnames listed. This is so that these styles will match up with uses of both `css(styles.parent.child)` and `css(styles.altparent.child)`. For example, when generating the `style[':hover']['>>child']` styles, we generate: ``` .parent_abcdef-o_O-altparent_123456:hover .parent_abcdef__child { ... } .parent_abcdef-o_O-altparent_123456:hover .altparent_123456__child { ... } ``` 3. When *descendant* styles are passed into `css()`, like `css(styles.parent.child)`, we simply return the associated class name (in this case, `"parent_abcdef__child"`) in the output. Fixes #10 Test Plan: - `npm run test` - `cd examples && npm run examples`, then visit http://localhost:4114/ and see that the last line starts green and when "Hover over me" is hovered, the other part turns blue. @zgotsch @jlfwong @kentcdodds @montemishkin
Is there any update regarding this issue? |
Summary: It turns out descendant selectors are kinda hard. In particular, it's difficult to let *descendants have unique classnames* for themselves, at the same time as allowing *merging between styles which contain descendant selectors*. This pull request attempts to do both of these things. The code is a bit messy, so I'll lay out what's going on in this pull request. Please ask questions, if something is confusing! The Aphrodite code is nice because it's all fairly easily understood, and I'm afraid that this adding too much complexity. An example of the syntax (and an example for the explanation in this commit message), consider: ```js const styles = StyleSheet.create({ parent: { '>>child': { color: "red" }, ':hover': { '>>child': { color: "blue" }, '>>otherchild': { color: "white" } }, }, altparent: { ':hover': { '>>child': { color: "green" } } } }); The basic flow of this diff is: 1. In `StyleSheet.create`, we recurse through the passed-in styles, and find each of the descendant selectors (which have keys that look like `>>blah`). In the example above, it would find `parent['>>child']`, `parent[':hover']['>>child']`, `parent[':hover']['>>otherchild']`, and `altparent[':hover']['>>child']`. In each place, we: - generate a class name for that descendant selector. This is based on the class name of the parent class, as well as the key name. For example, if the class name for `styles.parent` was `parent_abcdef`, we might generate the class name `parent_abcdef__child` for `parent['>>child']`. - tag the style by adding a `_names` object, with the class name as a key of the object. For example, `parent['>>child']` would end up looking like `{ color: "red", _names: { parent_abcdef__child: true } }`. - collect a map of each of the keys (without the `>>` bit) to their class names. For example, for `styles.parent`, we would generate a map that looks like `{ child: "parent_abcdef__child", otherchild: "parent_abcdef__otherchild" }`. We merge in the map from key to class name into the generated style, so that the class names can be accessed using a syntax like `styles.parent.child`. 2. When *parent* styles are passed into `css()`, their styles are merged together. If one style overrides another's descendant styling, the `_names` object will be merged together and will contain all of the associated class names. For example, when evaluating `css(styles.parent, styles.altparent)`, we would end up with merged styles looking like: ``` { '>>child': { color: "red", _names: { parent_abcdef__child: true }, }, ':hover': { '>>child': { color: "green", _names: { parent_abcdef__child: true, altparent_123456__child: true, }, }, '>>otherchild': { color: "white", _names: { parent_abcdef__otherchild: true }, } } } ``` We then generate a map from the descendent keys to all of the class names that could be associated with a given key by recursing and looking at each of the `_names` objects. For example, the map would look like: ``` { '>>child': ["parent_abcdef__child", "altparent_123456__child"], '>>otherchild': ["parent_abcdef__otherchild"] } ``` When generating the styles, we look at this map and then generate styles for each of the classnames listed. This is so that these styles will match up with uses of both `css(styles.parent.child)` and `css(styles.altparent.child)`. For example, when generating the `style[':hover']['>>child']` styles, we generate: ``` .parent_abcdef-o_O-altparent_123456:hover .parent_abcdef__child { ... } .parent_abcdef-o_O-altparent_123456:hover .altparent_123456__child { ... } ``` 3. When *descendant* styles are passed into `css()`, like `css(styles.parent.child)`, we simply return the associated class name (in this case, `"parent_abcdef__child"`) in the output. Fixes #10 Test Plan: - `npm run test` - `cd examples && npm run examples`, then visit http://localhost:4114/ and see that the last line starts green and when "Hover over me" is hovered, the other part turns blue. @zgotsch @jlfwong @kentcdodds @montemishkin
Summary: It turns out descendant selectors are kinda hard. In particular, it's difficult to let *descendants have unique classnames* for themselves, at the same time as allowing *merging between styles which contain descendant selectors*. This pull request attempts to do both of these things. The code is a bit messy, so I'll lay out what's going on in this pull request. Please ask questions, if something is confusing! The Aphrodite code is nice because it's all fairly easily understood, and I'm afraid that this adding too much complexity. An example of the syntax (and an example for the explanation in this commit message), consider: ```js const styles = StyleSheet.create({ parent: { '>>child': { color: "red" }, ':hover': { '>>child': { color: "blue" }, '>>otherchild': { color: "white" } }, }, altparent: { ':hover': { '>>child': { color: "green" } } } }); The basic flow of this diff is: 1. In `StyleSheet.create`, we recurse through the passed-in styles, and find each of the descendant selectors (which have keys that look like `>>blah`). In the example above, it would find `parent['>>child']`, `parent[':hover']['>>child']`, `parent[':hover']['>>otherchild']`, and `altparent[':hover']['>>child']`. In each place, we: - generate a class name for that descendant selector. This is based on the class name of the parent class, as well as the key name. For example, if the class name for `styles.parent` was `parent_abcdef`, we might generate the class name `parent_abcdef__child` for `parent['>>child']`. - tag the style by adding a `_names` object, with the class name as a key of the object. For example, `parent['>>child']` would end up looking like `{ color: "red", _names: { parent_abcdef__child: true } }`. - collect a map of each of the keys (without the `>>` bit) to their class names. For example, for `styles.parent`, we would generate a map that looks like `{ child: "parent_abcdef__child", otherchild: "parent_abcdef__otherchild" }`. We merge in the map from key to class name into the generated style, so that the class names can be accessed using a syntax like `styles.parent.child`. 2. When *parent* styles are passed into `css()`, their styles are merged together. If one style overrides another's descendant styling, the `_names` object will be merged together and will contain all of the associated class names. For example, when evaluating `css(styles.parent, styles.altparent)`, we would end up with merged styles looking like: ``` { '>>child': { color: "red", _names: { parent_abcdef__child: true }, }, ':hover': { '>>child': { color: "green", _names: { parent_abcdef__child: true, altparent_123456__child: true, }, }, '>>otherchild': { color: "white", _names: { parent_abcdef__otherchild: true }, } } } ``` We then generate a map from the descendent keys to all of the class names that could be associated with a given key by recursing and looking at each of the `_names` objects. For example, the map would look like: ``` { '>>child': ["parent_abcdef__child", "altparent_123456__child"], '>>otherchild': ["parent_abcdef__otherchild"] } ``` When generating the styles, we look at this map and then generate styles for each of the classnames listed. This is so that these styles will match up with uses of both `css(styles.parent.child)` and `css(styles.altparent.child)`. For example, when generating the `style[':hover']['>>child']` styles, we generate: ``` .parent_abcdef-o_O-altparent_123456:hover .parent_abcdef__child { ... } .parent_abcdef-o_O-altparent_123456:hover .altparent_123456__child { ... } ``` 3. When *descendant* styles are passed into `css()`, like `css(styles.parent.child)`, we simply return the associated class name (in this case, `"parent_abcdef__child"`) in the output. Fixes #10 Test Plan: - `npm run test` - `cd examples && npm run examples`, then visit http://localhost:4114/ and see that the last line starts green and when "Hover over me" is hovered, the other part turns blue. @zgotsch @jlfwong @kentcdodds @montemishkin
Summary: It turns out descendant selectors are kinda hard. In particular, it's difficult to let *descendants have unique classnames* for themselves, at the same time as allowing *merging between styles which contain descendant selectors*. This pull request attempts to do both of these things. The code is a bit messy, so I'll lay out what's going on in this pull request. Please ask questions, if something is confusing! The Aphrodite code is nice because it's all fairly easily understood, and I'm afraid that this adding too much complexity. An example of the syntax (and an example for the explanation in this commit message), consider: ```js const styles = StyleSheet.create({ parent: { '>>child': { color: "red" }, ':hover': { '>>child': { color: "blue" }, '>>otherchild': { color: "white" } }, }, altparent: { ':hover': { '>>child': { color: "green" } } } }); The basic flow of this diff is: 1. In `StyleSheet.create`, we recurse through the passed-in styles, and find each of the descendant selectors (which have keys that look like `>>blah`). In the example above, it would find `parent['>>child']`, `parent[':hover']['>>child']`, `parent[':hover']['>>otherchild']`, and `altparent[':hover']['>>child']`. In each place, we: - generate a class name for that descendant selector. This is based on the class name of the parent class, as well as the key name. For example, if the class name for `styles.parent` was `parent_abcdef`, we might generate the class name `parent_abcdef__child` for `parent['>>child']`. - tag the style by adding a `_names` object, with the class name as a key of the object. For example, `parent['>>child']` would end up looking like `{ color: "red", _names: { parent_abcdef__child: true } }`. - collect a map of each of the keys (without the `>>` bit) to their class names. For example, for `styles.parent`, we would generate a map that looks like `{ child: "parent_abcdef__child", otherchild: "parent_abcdef__otherchild" }`. We merge in the map from key to class name into the generated style, so that the class names can be accessed using a syntax like `styles.parent.child`. 2. When *parent* styles are passed into `css()`, their styles are merged together. If one style overrides another's descendant styling, the `_names` object will be merged together and will contain all of the associated class names. For example, when evaluating `css(styles.parent, styles.altparent)`, we would end up with merged styles looking like: ``` { '>>child': { color: "red", _names: { parent_abcdef__child: true }, }, ':hover': { '>>child': { color: "green", _names: { parent_abcdef__child: true, altparent_123456__child: true, }, }, '>>otherchild': { color: "white", _names: { parent_abcdef__otherchild: true }, } } } ``` We then generate a map from the descendent keys to all of the class names that could be associated with a given key by recursing and looking at each of the `_names` objects. For example, the map would look like: ``` { '>>child': ["parent_abcdef__child", "altparent_123456__child"], '>>otherchild': ["parent_abcdef__otherchild"] } ``` When generating the styles, we look at this map and then generate styles for each of the classnames listed. This is so that these styles will match up with uses of both `css(styles.parent.child)` and `css(styles.altparent.child)`. For example, when generating the `style[':hover']['>>child']` styles, we generate: ``` .parent_abcdef-o_O-altparent_123456:hover .parent_abcdef__child { ... } .parent_abcdef-o_O-altparent_123456:hover .altparent_123456__child { ... } ``` 3. When *descendant* styles are passed into `css()`, like `css(styles.parent.child)`, we simply return the associated class name (in this case, `"parent_abcdef__child"`) in the output. Fixes #10 Test Plan: - `npm run test` - `cd examples && npm run examples`, then visit http://localhost:4114/ and see that the last line starts green and when "Hover over me" is hovered, the other part turns blue. @zgotsch @jlfwong @kentcdodds @montemishkin
Another motivation for supporting child selectors (outside of pseudo-classes even) is to style React components that we don't control. For example, React Bootstrap has a NavItem component that renders In this case I want to write: StyleSheet.create({
navItem: {
'selector(a)': { color: linkColor }
}
}); but sometimes would want more nested selectors like |
@ide The syntax I'm proposing would have you do |
@ide I am facing the same problem. I came up with a pretty hacky function to select children: function children(selector) {
return `:active, ${selector}`;
}
/// use it like this
StyleSheet.create({
header: {
color: 'red',
[children('li a')]: {
color: 'blue',
}
},
}) Clearly, this works as expected only if the parent component cannot be active, otherwise you'd have to use another selector. I am using it until an official API is designed |
Thinking more about the
The color of the resulting span will depend on the injection order of To see why this happens, consider the following:
with CSS
In this case, "Hello" will be red. The selectors have equivalent precedence, so the latter is used. If the CSS is switched to:
Then "Hello" becomes green. This reversal of the declaration order mimics what would happen in aphrodite depending on whether I don't think there's a clear implementation of the proposed |
@jlfwong :( Oof. I guess that probably happens with my pull request implementation, as well? |
Is this kind of non-determinism already an issue with multiple styles on the same component? For example: <div className={css(styles.s1, styles.s2)} />
// or
<div className={classNames(css(styles.s1), css(styles.s2))} />
const styles = StyleSheet.create({
s1: { color: 'red' },
s2: { color: 'green' },
}); My understanding is that Aphrodite will emit two class selectors of the same specificity, so the last one emitted wins. I guess technically it's deterministic but hard to reason about since the order of the |
@ide That is true, but you should always do The point is, adding two classnames is non-determinism that you can avoid (by combining the calls to |
This is actually rather intuitive. I'm using it in a project. |
@misterfresh That's fine, but do recognize that it is a hack that's not specifically supported by aphrodite, and might break in future versions. |
@xymostech if hey way that @misterfresh is handling child elements is a hack, did the main contributors to this project decide on what will be the recommended way to implement styles on nested children in the future? I can use this now as we only have a beta application, but my boss just gave me the nod on using Aphrodite (AWESOME library btw) and I'll need to know the recommended way to handle this in the future. Thanks. |
has there been any progress for this? I am trying to select td's in a table |
Yeah, I want to selected all the anchors in a div (need to style component I don't control), whats the status of this? I see its closed but as far as I can tell there was no resolution? |
@sontek This was closed due to the solution in #95, which is documented here: https://github.com/Khan/aphrodite#advanced-extensions |
This hacky solution might help if you end up in this thread... .parent {
--child-background-color: red
}
.parent:hover {
--child-background-color: blue
}
.child {
background-color: var(--child-background-color)
} |
If I want to apply styles to a child based on its parent's
:hover
state, I think I have to track hover state in js. Is that accurate? Do you think handling this is in the scope of aphrodite?Specifically I am thinking of something that emulates the CSS:
The text was updated successfully, but these errors were encountered: