From 5eab791bd4fda40e25aa18c1431022bbd0c594fa Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Wed, 1 Jan 2020 15:01:51 -0800 Subject: [PATCH 1/2] chore: add slot-attributes doc --- text/0000-slot-attributes.md | 267 +++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 text/0000-slot-attributes.md diff --git a/text/0000-slot-attributes.md b/text/0000-slot-attributes.md new file mode 100644 index 0000000..7b32202 --- /dev/null +++ b/text/0000-slot-attributes.md @@ -0,0 +1,267 @@ +- Start Date: 2020-01-01 +- RFC PR: (leave this empty) +- Svelte Issue: (leave this empty) + +# Slot Attributes + +## Summary + +Slot attributes allow a Component to assign attributes (eg, classnames) to the content of a slot if & when it holds content. + +## Motivation + +> I'll be using Bootstrap to help illustrate examples for this RFC, but the problem is **most definitely** not limited to Bootstrap by any means. I've run into this in _every_ design system I've worked with. Bootstrap is chosen solely for its familiarity and simplicity. + +The majority of design systems have conditional content slots for their elements – we know & expect this. However, when a Svelte developer goes to wire up the UX slots to actual ``s, they'll run into problems: + +#### 1. Slot elements generally have CSS side-effects when empty. + +Most of these slots' act as parent wrappers for what they contain. This means that there's almost always some level of `padding`, `background-color`, `margin`, etc applied to that parent, even when it contains no children. This, then, prevents the Svelte developer from including those parent containers within the Component directly: + +```html +
+
+ +
+ +
+ +
+ + +
+``` + +> [See REPL example](https://svelte.dev/repl/e73cff770b274fe89117608232277145?version=3.16.7) + +As you will see, the `.card-header` and `.card-footer` carry their own paddings & background colors, rendering a visual effect even though they weren't defined/used by the Card's consumer. + +Y Self-contained component styles +Y Does not require internal knowledge +Y&N Slot is configurable from consumer POV +N Slot leaves no trace when unused/empty. + + +| Pass/Fail | Requirement | +|--------------------|-----------------------------------------| +| :white_check_mark: | Self-contained component styles | +| :white_check_mark: | Does not require internal knowledge | +| :wavy_dash:* | Slot is configurable from consumer POV | +| :no_entry_sign: | Slot leaves no trace when unused/empty | + +> * You can't add additional classes to `.card-footer` (ideal) but still can to internals + +This then forces us into the second problem... + +#### 2. External `` access requires internal knowledge + +In order to truly conditionally render parent classes (eg, `card-header`) we, the `` consumers, have to know _how_ to recreate the `` in a way that the design element (eg, Bootstrap's `.card`) expected. + +What this means is that we have to have internal knowledge of the Component's design mechanics AND it forces us to split the Component's markup across multiple boundaries. + +Additionally, this forces `` to ship `:global(.card-footer)` style selectors since it does not _actually contain_ any `.card-footer` elements in its markup. + +```html + + +
Featured
+ +
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ + + + +
+``` + +> [See REPL example](https://svelte.dev/repl/64594c7de23e4b1fa4a123f15ec479e2?version=3.16.7) + +| Pass/Fail | Requirement | +|--------------------|-----------------------------------------| +| :no_entry_sign: | Self-contained component styles | +| :no_entry_sign: | Does not require internal knowledge | +| :white_check_mark: | Slot is configurable from consumer POV | +| :white_check_mark: | Slot leaves no trace when unused/empty | + + +## Detailed Design + +A `` can hold attributes like any other tag.
+In English, this is the same as saying "this slot's (top-level) children _will_ inherit these attributes". This is true for named & unnamed slots alike. + +```html + +
+ + + + + + + + +
+``` + +> **Note:** Example is restricted to `class` for simplicity. + +As mentioned, the slot's attributes will be coerced/assigned to the incoming content. +In this example, we have not defined any of our own `class` values, so it's a direct assignment: + +```html + + + +

My title

+ + +
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+ + +
2 days ago
+
+ + +
+

My title

+
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+ +
+``` + +Now, when a `` is unused, it has nothing to spread its attributes onto: + +```html + + +
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+
+ + +
+
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+
+``` + +And finally, _when there are attribute conflicts_, we simply merge the `` values into the consumer values.
+Again, the Component author has said "this `` needs to have these attributes" – anything else is presumably relevant to the Consumer-side: + +```html + + + +

My title

+ + +
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+ + +
2 days ago
+
+ + +
+

My title

+
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ +
+ +
+``` + +## How we teach this + +This would be a simple add-on tutorial for the Svelte website. + +In plain English, we say "Any attributes (except `name`) on a defined `` will be applied to its top-level children" + +## Drawbacks + +These are pretty lame, but it's all I could muster: + +1) There's a built-in exception of `name` not being passed down – reserved for slot identification. +2) This becomes an additional API to learn (lol) +3) This is unique to Svelte – the closest is a React HoC using a fairly lengthy `cloneElement` loop to add properties to children. + +## Alternatives + +Current alernatives and workarounds are: + +1) Do nothing – expect Component consumers to know which classes need to appear when defining the slot: + + ```html + +
+

My title

+
+
+

My content

+
+ +
+ ``` + +2) Extract a Component's slots as separate Sub-Components: + + ```html + + +

My title

+
+ +

My content

+
+ + + +
+ ``` + +3) Limit all slotted content to plain text: + + This is a bit extreme – and a no-go for most designers – but it's possible to get what we want by replacing all ``s with props and a series of `{#if}` blocks. + + It semi-works for this example, but still requires one of the other two workarounds for non-plaintext content. + + ```html + +

My content

+ + + +
+ ``` + + +## Unresolved questions + +* Which attributes, if any others besides `name`, should not be allowed? From 03291d297534d386c36895b558314126c79dce46 Mon Sep 17 00:00:00 2001 From: Luke Edwards Date: Wed, 1 Jan 2020 15:04:32 -0800 Subject: [PATCH 2/2] fix: add final score card --- text/0000-slot-attributes.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/text/0000-slot-attributes.md b/text/0000-slot-attributes.md index 7b32202..bbd5994 100644 --- a/text/0000-slot-attributes.md +++ b/text/0000-slot-attributes.md @@ -1,5 +1,5 @@ - Start Date: 2020-01-01 -- RFC PR: (leave this empty) +- RFC PR: [#15](https://github.com/sveltejs/rfcs/pull/15) - Svelte Issue: (leave this empty) # Slot Attributes @@ -196,6 +196,13 @@ Again, the Component author has said "this `` needs to have these attribu ``` +| Pass/Fail | Requirement | +|--------------------|-----------------------------------------| +| :white_check_mark: | Self-contained component styles | +| :white_check_mark: | Does not require internal knowledge | +| :white_check_mark: | Slot is configurable from consumer POV | +| :white_check_mark: | Slot leaves no trace when unused/empty | + ## How we teach this This would be a simple add-on tutorial for the Svelte website.