Thanks to visit codestin.com
Credit goes to github.com

Skip to content

proposal: Type only class definition #2676

@idoros

Description

@idoros

There are cases where components don't allow passing a CSS class to the root of the component, but expose styling of inner parts.

For example Radix has components with an invisible unstylable wrapper, like Alert and Tooltip that don't accept styling for the grouping component, but accept a class for inner parts like trigger, overlay, and content.

Current state

When writing a selector in Stylable, CSS class might be transformed to namespace or map to a different selector, but the intent to target something is preserved.

If we define an alert.st.css stylesheet today, with inner parts and try to use the alert root class as a selector then we get the alert__root class that won't be in the DOM, so it won't target and apply anything:

/* theme.st.css */
@st-import Alert from './alert.st.css';

Alert::trigger {} /* .alert__root .alert__trigger */
Alert::overlay {} /* .alert__root .alert__overlay */

This means that we can try and model the style API to treat each inner part as a separate component by either:

1. Having a different stylesheet for each part

/* alert-trigger.st.css */
.root {}
/* alert-overlay.st.css */
.root {}
/* theme.st.css */
@st-import AlertTrigger from './alert-trigger.st.css';
@st-import AlertOverlay from './alert-overlay.st.css';

AlertTrigger {} /* .alertTrigger__root */
AlertOverlay {} /* .alertOverlay__root */

2. Import inner parts

/* alert.st.css */
.root {}
.trigger {}
.overlay {}
/* theme.st.css */
@st-import [trigger, overlay] from './alert.st.css';

.trigger {} /* .alert__trigger */
.overlay {} /* .alert__overlay */

The second is probably better as it is less verbose on files and code, but it is still less good then having a component root to group inner parts as syntactic sugar, especially with some component stylesheets containing many parts.

Goals

  • Group a set of parts together
  • Mark a class to only exist for build time - transpiled away

Proposal

  • New interface only class - A new stylable declaration -st-type-only or maybe add an option to -st-extends to accept a "none" value to indicate its not a runtime class and is not intended to target anything.
  • Can only be applied to root class (not sure there is a case for inner parts)
  • Sticky interface - extending is basically stating that a new class is going to be set on the same DOM node as the extended class. Since we are defining a class that cannot exist in the DOM, Then extending such a class would mean the extending class is also an interface only class.
  • transform away interface only class during the build process
  • Report error when a selector subject is unstylable
  • No runtime style API mapping for such classes
  • Filter out interface classes from programmatic reflection APIs (transformIntoSelector, getAllClasses, etc.) - need to see how to differentiate between symbols and runtime classes

definition

/* alert.st.css */
.root {
    -st-extends: (); /* interface only root */
}
.trigger {}
.overlay {}

transform away interface only root

/* theme.st.css */
@st-import Alert from './alert.st.css';

Alert::trigger {} /* .alert__trigger */
Alert::overlay {} /* .alert__overlay */

/* report: unstylable selector subject */
Alert {}

no runtime

/* alert.js */
import { classes } from `./alert.st.css`;

classes.root {}    // undefined
classes.trigger {} // alert__trigger
classes.overlay {} // alert__overlay

extend interface only class

/* super-alert.st.css */
@st-import Alert from './alert.st.css';

.root {
    -st-extends: Alert; /* also set as interface only */
}
.part {};

.root::trigger {} /* .alert__trigger */
.root::overlay {} /* .alert__overlay */
.root::part {}    /* .super-alert__part */

/* report: unstylable selector subject */
root {}

Metadata

Metadata

Assignees

Labels

coreProcessing and transforming logicdiscussionOngoing conversationfeatureNew syntax feature or behavior

Type

No type

Projects

Status

No status

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions