Replies: 3 comments 3 replies
-
QQ regarding approach 3 – can we still define styles as part of the web component, but they just wouldn't be encapsulated? |
Beta Was this translation helpful? Give feedback.
-
Following the premise that this won't be used as a standalone component, could it be an alternative to combine option 1 and 4. // pie-input component
<label for="foo">
<pie-form-label trailing="x out x" optional=${optional}>${label}</pie-form-label>
</label>
<input id="${elementId}"...> The label string will probably have to be a prop: // consumer app
<pie-input id="foo" label='main label' optional='optional text'> Otherwise I would also consider option 3 in case we have more instances in the future that need to live in the light-dom (eg. table components). If implementing this is too complicated I would leave it for when we have another instance of this issue. |
Beta Was this translation helpful? Give feedback.
-
Hey folks, I believe I have a working proof of concept that might be of interest to this discussion. Here is the PR - I have added some comments to explain my changes: https://github.com/justeattakeaway/pie/pull/1117/files Essentially this allows us to do two things:
<pie-form-label for="switchComp">Some Label Text</pie-form-label>
<pie-switch id="switchComp"></pie-switch>
Option 1 feels more flexible and similar to native HTML in my opinion. This is also how libraries such as Spectrum handle labels. Please let me know if this is useful. I have attached a demo video below. In the demo vid I place the label inside the component but that was just for style purposes. I wouldn't recommend doing this in practice. Screen.Recording.2023-12-15.at.16.22.36.mov |
Beta Was this translation helpful? Give feedback.
-
📓 Background:
When you associate a label with an input element using the
for
attribute, browsers will link both elements in a way that clicking on the label triggers the event of the associated input element as demonstrated hereIn web components, the behavior above will only work if both elements are in the same Shadow DOM, so when we create a custom label element such as
pie-form-label
, we will lose this functionality and other built-in browser features such as screen readers won't announce the label unless you pass an aria-label or use something like aria-labelledby as each element lives in a different and encapsulated Shadow DOM (subtree).I've created this discussion to explore the options we have and decide on what works best for us while ensuring the component is accessible and can be used to trigger the event of another element such as input elements.
🔢 Workarounds:
1- Create the
pie-form-label
as a shell container that renders the layout and styles of our label component. then, consumers (mostly us) have to wrap the component with a label element such asthis way ensures that we reuse the component, and still have the built-in browser features such as screen reader announcement and even dispatching when any part of the container label is clicked.
2- Pass the label element to the slot:
Similar to the first approach, we will have a shell container for the
form-label-component
and the the label element will be set/ passed via the main slot such as:tho this approach will only make the main label clickable, as the children (trailing + optional) will be in the component subtree, unlike slots. and we probably need to use
aria-labelledby
for screen readers and accessibility.3- Render the
pie-form-label
into the light DOM:This will render the component and its children (optional and trailing) into the main DOM tree, which allows us to have the same behavior of regular DOM elements, however, this means we will no longer have access to syle scoping and will need to define our styles globally somewhere. Besides, we need to change the main label to be a prop as slots aren't moved in the DOM tree, but they're rendered as if they were children of the so the main label won't be clickable, only trailing and optional content.
Screen.Recording.2023-10-02.at.17.06.28.mov
4- Create utility classes for the form element layout and reuse them across the needed components (3 components so far). keep in mind that the
pie-form-label
component will probably never be used as a standalone component and will be an internal component so this suggestion isn't as bad as it sounds :)Beta Was this translation helpful? Give feedback.
All reactions