stencil icon indicating copy to clipboard operation
stencil copied to clipboard

feat: Symbol properties

Open tomherni opened this issue 2 years ago • 0 comments

Prerequisites

Describe the Feature Request

Symbol properties are a great way to have a publicly available private API.

The value of a Symbol property can only be set by those who have access to the Symbol reference. This way you could control who would be able to set certain properties.

Describe the Use Case

This feature would be great for design systems, particularly in composition scenarios where the author needs to make component adjustments that regular consumers should not have the ability to perform.

For example: to ensure brand consistency, colors and spacings must remain unchanged. Similarly, for accessibility considerations, labels or specific ARIA attributes must remain unchanged. But, when the author is creating more complex, composite components, they may need to make specific adjustments that should otherwise not be possible (at least through a public API).

Describe Preferred Solution

The ideal solution would be if @Prop could accept Symbols. See the code snippets below.

// foo-element.tsx

import { h, Component } from '@stencil/core';
import { mySymbol } from '../my-private-symbol';

@Component({
  tag: 'foo-element',
  shadow: true,
})
export class FooElement {
  render() {
    const props = { [mySymbol]: 'world' };

    return <bar-element {...props}></bar-element>;
  }
}
// bar-element.tsx

import { h, Component, Prop } from '@stencil/core';
import { mySymbol } from '../my-private-symbol';

@Component({
  tag: 'bar-element',
  shadow: true,
})
export class BarElement {
  @Prop() public [mySymbol]: string;

  render() {
    return <div>Hello {this[mySymbol]}</div>;
  }
}

In short:

  • Both components import the same Symbol
  • Component 1 (foo-element) assigns a Symbol property to bar-element with the value world.
  • Component 2 (bar-element) renders Hello and the Symbol property, resulting in Hello world.

Describe Alternatives

An alternative is a "symbol" property for @Prop's PropOptions.

export class BarElement {
  @Prop({ symbol: mySymbol }) public myProperty: string;

  render() {
    return <div>Hello {this.myProperty}</div>;
  }
}

Pros:

  • Prevents a dynamic property name (just in case that would be a technical challenge for this feature request).
  • The property looks nicer in the template.

Cons:

  • It's confusing. You could think you'd have to assign your value to myProperty, which is incorrect.
  • More magic. The preferred solution stays close to the platform.

Related Code

No response

Additional Information

No response

tomherni avatar Nov 22 '23 15:11 tomherni