-
Notifications
You must be signed in to change notification settings - Fork 62
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
proposal: Explicit exports #2604
Comments
|
I think that as a first step for this feature, we can skip the nested overrides part of the API (unless it ends up being very trivial to implement. I think there's also a question of addressing the |
We need to specify how With implicit exports, like today, all classes (including For example, a .label {}
.icon {} Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == button__root
root == button__root
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === 'button__root';
classes.label === 'button__label';
classes.icon === 'button__icon'; Explicit root exportWith explicit exports, the question is, what is the default export and how is it declared. To make things a bit easier, I suggest we start by only allowing a class to be exported as default, maybe even just the root itself. We can ease this limitation in the future. Exporting nothing will result in no root: @st-export [label, icon]; Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == undefined
root == undefined
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === undefined;
classes.label === 'button__label';
classes.icon === 'button__icon'; Option 1: default as rootExport @st-export root, [label, icon]; Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == button__root
root == button__root
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === 'button__root';
classes.label === 'button__label';
classes.icon === 'button__icon'; Option 2: named root to defaultThe symbol that is exported as @st-export [root, label, icon]; Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == button__root
root == button__root
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === 'button__root';
classes.label === 'button__label';
classes.icon === 'button__icon'; |
I prefer the 2nd option with the addition of allowing to default export something else.
|
So if I understand you correctly:
There is also another options I failed to mention: Option 3: root as default
@st-export [root, label, icon]; Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == button__root
root == button__root
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === 'button__root';
classes.label === 'button__label';
classes.icon === 'button__icon'; Or with a another class as root: @st-export [another as root, label, icon]; Result import /* css */
@st-import Btn, [root, label, icon] from './button.st.css';
/*
Btn == button__another
root == button__another
label == button__label
icon == button__icon
*/
/* js */
import { classes } from './button.st.css';
classes.root === 'button__another';
classes.label === 'button__label';
classes.icon === 'button__icon'; |
This proposal has encountered some resistance offline. The main issue is that a lot of the classes in a stylesheets are actually inner "parts" that are meant to be public, and opting-in to "private-by-default" with the approach offered here means that all the classes (and other symbols) would need to me marked as public, adding to the source size (making developers read and write more code). An alternative to keep everything public and only mark private definitions was offered, but we have some unresolved issues with it.
The first is covered by the alternative suggestion, but the other 2 are less covered. With the more strict "private-by-default" there was no unintentional leakage of definitions to be used as API or to bloat the runtime. And in addition we can't seem to settle on a syntax (bikeshedding here): control declaration .class {
-st-access: private;
}
:vars {
myVar: green; /* issue: no body */
}
@keyframes myFrames {
-st-access: private; /* issue: prefer not to add into native definitions */
} control with annotation-like atrule /* issue: there is nothing like this in CSS - prefer not to add an atrule that affects an adjacent definition */
@access private;
.class {}
:vars {
@access private;
myVar: green;
}
@access private;
@keyframes myFrames {} control nested definitions /* much more verbose in cases with styling and not just interface */
@access private {
.class {}
:vars {
myVar: green;
}
@keyframes myFrames {}
}
.class {} /* should it be public when defined outside? */ control by convention /* start with "_" to mark private */
._class {}
:_vars {
_myVar: green;
}
@keyframes _myFrames {}
/* issue: no way to mark mapping */ control accessor-like-prefix /* issue: wraps all syntax into atrule, makes processing, syntax highlighting and generally everything more complex */
@access(private) .class {}
:vars {
@access(private) myVar: green; /* issue: no body */
}
@access(private) @keyframes myFrames {}
This boils down mostly to a DX vs UX preferences, and I feel that by not going with the "private-by-default" approach it's not worth adding the complexity. ATM an initial "_" character can be used to symbolize private symbols with no changes to stylable. |
Stylable stylesheet has 2 different export targets:
@st-import
for customization, interface defintion or re-exportimport
for view binding and dynamic CSS customization.There are several stylesheet entities that can be exported today (element-type, class, custom-property, keyframes, layer, st-var), and we can assume there will be more in the future (e.g. container-name).
Current state
Today there is no way to mark which symbols are exported, and implicitly all symbols are considered public and exported for other stylesheets, while javascript gets all symbols except the imported
st-var
types (to reduce the bloat of probably unneeded data at run time).Goals
Proposal
Add a new
@st-export
atrule to allow explicit exports control (taken from #1489):@st-export
are allowed - with additive behavior@st-import
for typed/namespaced definitions (e.g.keyframes
andlayer
)pseudo-element
(private are not)pseudo-states
are not part of this proposalroot
is automatically exported as default export (not to JS). This behavior will continue with explicit exports. And a user might be able to opt-in to explicit default export in the future (see discussion in the comments below).Examples
export specific symbols for CSS and JS:
export specific symbols just for CSS or JS:
override specific symbol export target:
additive definition:
rename export:
Related
-st-access
proposal (Support private classes #294)The text was updated successfully, but these errors were encountered: