Skip to content
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

Pre-RFC: Splat Areas #517

Open
knownasilya opened this issue Jul 26, 2019 · 5 comments

Comments

@knownasilya
Copy link
Contributor

commented Jul 26, 2019

Based on https://mobile.twitter.com/knownasilya/status/1152293795901464577

With the addition of ...attributes, element modifiers and having multiple top elements in a glimmer component, it has become obvious that ...attributes is too limited (I'm sure the API was mean't to be simple while patterns emerge). Think of a component that wraps an input and a label into a nice package. Currently you'd need to either have the user yield out subcomponents and recreate the same structure or provide custom arguments for each element/component.

What if we could expose elements/components for customization by name, for example:

<UserCard
  @user={{@user}}
  {{on 'click' this.openProfile}}
  [avatar
    class='avatar-sm'
    @size='small'
    {{on 'click' this.openAvatarModal}}
  ]
/>

And the user card would apply it like so:

<div ...attributes class='container'>
  <Avatar @img={{@user.avatar.url}} ...[avatar] class='avatar' />
  {{! more stuff here }}
</div>
@buschtoens

This comment has been minimized.

Copy link

commented Jul 26, 2019

Side note: can you amend your snippet with "root" attributes, that would apply to ...attributes in .container?

Edit: I can't read. L3 ({{on 'click' this.openProfile}})) is a "root" splattribute.

@buschtoens

This comment has been minimized.

Copy link

commented Jul 26, 2019

I hit the same limitation as well... A currently possible solution (for many cases) is to yield the sub-components:

<UserCard
  @user={{@user}}
  {{on 'click' this.openProfile}}
  as |uc|
>
  <uc.Avatar
    class='avatar-sm'
    @size='small'
    {{on 'click' this.openAvatarModal}}
  />
  {{! more stuff here }}
</UserCard>
<div ...attributes class='container'>
  {{yield (hash
    Avatar=(component 'avatar' img=@user.avatar.url classNames='avatar')
  )}}
</div>

I do not think that this ⬆️ is a good solution.

  1. The component consumer needs to nest the yielded components in the correct order and has to remember to yield all required components.
  2. Components that would otherwise only consume data and element modifiers, suddenly consume a nested block and HTML structure.
  3. Passing HTML attributes to the {{component}} helper is still awkward, even with ember-component-attributes, and sometimes not even possible: What if Avatar is a `GlimmerComponent? Do I smell an RFC?
@buschtoens

This comment has been minimized.

Copy link

commented Jul 26, 2019

Have you considered merging this with yieldable blocks somehow?

@knownasilya

This comment has been minimized.

Copy link
Contributor Author

commented Jul 26, 2019

@buschtoens I have thought about a possible way, but nothing stands out.
Something like this might work..

<UserCard
  @user={{@user}}
  {{on 'click' this.openProfile}}
  [:avatar
    class='avatar-sm'
    @size='small'
    {{on 'click' this.openAvatarModal}}
  ]
/>

and

<div ...attributes class='container'>
  <Avatar @img={{@user.avatar.url}} {{yield to='avatar}} class='avatar' />
  {{! more stuff here }}
</div>

But that seems to diverge a bit from ...attributes, which this seems more like.

@ef4

This comment has been minimized.

Copy link
Contributor

commented Jul 26, 2019

While I know the use cases you have in mind are real and I have encountered them too, I have always eventually come to regret making a component that's big enough to have multiple internal elements that users want to customize the markup of.

Also, I suspect named blocks can do the same things as this proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants
You can’t perform that action at this time.