Re: [css-houdini-drafts] [css-properties-values-api] Should property registration be scoped? (#939)

This makes sense, but I'm wondering how this could best be solved:

1. you distribute a web component as a library
2. it comes with a set of custom properties so you can adjust its style
3. if the page (or another web component using it) doesn't do anything (no `@property`), the web component still behaves properly
4. users of the web component easily know the available custom properties, their syntax, the defaults, etc.

Points 1 to 3 are pretty much covered by the existing features, so it's really point 4 that I'm interested in.

Right now, you can do `var(--some-name, someDefaultValue)` which expresses the property's existence and an indirect initial value, but you cannot provide a syntax or any other potentially useful information.

So in a way, it feels like the responsibility for defining the "shape" of the custom property is moved to the page rather than the web component that's really the one that should be defining its behavior. Which, don't get me wrong, from a certain point of view also makes sense.

I think I might be able to make myself clearer if I drew a parallel with a random old-fashioned programming language, for example TypeScript (I know it's not a perfect example because CSS simply doesn't work like that but bear with me).

Right now, defining a property with `@property` is - to me - roughly the same as:

```ts
/*
@property --variable {
  syntax: '<Syntax>';
  initial-value: initialValue;
}
*/
let variable: Syntax = initialValue;
// --variable: otherValue;
variable = otherValue;
// --other-variable: var(--variable, valueIfNotSet);
let otherVariable = variable ?? valueIfNotSet;
```

Which is already a very nice thing to have.

The web component that uses the property in its shadow DOM is - again to me, and even though passing arguments would be implicit for CSS - roughly the same as:

```ts
// background-color: var(--variable, defaultValue);
function webComponentStyle(variable /* no type because no syntax */ = defaultValue) {
  backgroundColor = variable;
  // --local-variable: var(--variable, valueIfNotSet)
  let localVariable /* again no type */ = variable ?? valueIfNotSet;
}
```

So my points are:

- the "style parameters" to the web component are not "typed" (e.g. they have no definition like `@property` offers)
- there is no actual list of parameters, references to custom properties are scattered in the style sheet or equivalent, and some of them might be internal to the web component and thus always overridden by the web component

Maybe (probably?) `@property` is not the right tool for everything I'm describing, but having the ability to use it inside the shadow DOM would cover 2 use cases.

The first one being simply using it in the web component itself and it's an internal thing:

```ts
/*
in shadow DOM
@property --variable {
  syntax: '<Syntax>';
  initial-value: initialValue;
}
*/
function webComponentStyle() {
  let variable: Syntax = initialValue;
  // --local-variable: var(--variable, valueIfNotSet);
  let localVariable: Syntax /* now typed */ = variable ?? valueIfNotSet;
}
```

Not much to add there, as that's the same benefits as `@property` outside the shadow DOM: it can be useful for the web component itself but also for defining properties that are used by other web components inside this web component.

The second one, which is in my opinion more useful when it comes to distributing web components (but where `@property` seems like it just might not be the best solution, cf. all the discussions above) is defining an API for the web component's styles:

```ts
/*
in shadow DOM
@property --variable {
  syntax: '<Syntax>';
}
*/
function webComponentStyle(variable?: Syntax) {
  // background-color: var(--variable, defaultValue);
  backgroundColor = variable ?? defaultValue;
}
*/
```

So tooling could look at the `@property` list and use it to generate documentation, offer auto-completion in the IDE (via language services), etc. At the moment I'm extracting `var()`'s from style sheets to find out about the available custom properties, but this is fairly limited information as there is no syntax, and knowing whether it's an internal property or not is not always straightforward (also parsing nested `var(x, var(y, var(z)))` is not much fun 😅).

Maybe a solution could be `@property` available in the shadow DOM for use case 1, and a new `@exposed-property` (or the mentioned `@export @property` available in the shadow DOM for use case 2?


-- 
GitHub Notification of comment by rraziel
Please view or discuss this issue at https://github.com/w3c/css-houdini-drafts/issues/939#issuecomment-1010040517 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 11 January 2022 14:52:53 UTC