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

Update ViewComponent docs to reflect new realities #41

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions docs/pages/teamshares/view-components/wrapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ meta:

> TL;DR: If you want to use the auto-generated Stimulus controllers and encapsulated styling for your View Components, you need to:
>
> 1. Call `enable_wrapper` within your `component.rb` class
> 1. Call `with_component_assets` within your `component.rb` class
> 1. Have a single top-level element in your view (if not, a top-level `<div>` will be created automatically)
> 1. Put your top-level styling within a `._base {}` block in your `component.scss`
> 1. Put your styling within a `component.scss` in your component folder -- CSS selectors will be automatically prefixed to apply only to your component

---

The Platform team recently released changes to `teamshares-rails` that allowed almost all the assets for a component to live in the same folder: the Ruby class, Slim template view, Stimulus controller, preview, and stylesheet. In order to do that, we were previously wrapping every component in a `<ts-wrapper>` tag, which served as a top-level wrapper element for the Stimulus controller and a generated CSS class that would encapsulate the component's style rules. However, this wrapper element caused some problems in terms of styling, since it added a new level of hierarchy to the DOM. (More details [here](https://github.com/teamshares/architecture-decision-record/pull/31).)

Our new pattern (as of late January, 2024) is twofold:
Our new pattern (as of October 2024) is twofold:

### 1. Opt-in wrapping via `enable_wrapper`
### 1. Opt-in wrapping via `with_component_assets`

View Components no longer get wrapped by default. Wrapping is now opt-in via the `enable_wrapper` class method, called within the component's class definition:
View Components no longer get wrapped by default. Wrapping is now opt-in via the `with_component_assets` class method, called within the component's class definition:

```ruby
class SharedUI::Demo::Component < SharedUI::ApplicationComponent
enable_wrapper
with_component_assets

def initialize(title:)
super
Expand All @@ -34,7 +34,7 @@ class SharedUI::Demo::Component < SharedUI::ApplicationComponent
end
```

If you don't include `enable_wrapper`, the component will not receive the auto-generated Stimulus controller and CSS class from their folder. We plan to eventually enable this for all components again, making it opt-out rather than opt-in, but this is the intermediate step.
If you don't include `with_component_assets`, the component will not receive the auto-generated Stimulus controller and CSS class from their folder.

### 2. Automatic application of styles and controller

Expand All @@ -51,7 +51,7 @@ If you _do_ enable the wrapper, the component will get wrapped with the `<ts-wra

```
class Foo::Component < ApplicationComponent
enable_wrapper
with_component_assets

def some_method
...
Expand All @@ -69,15 +69,11 @@ Will yield the following raw HTML:
</ts-wrapper>
```

<!-- ---

#### Coming soon (once the latest PR into `design-system is merged`):

Using the magic of the `connectedCallback()` method of web components, the `<ts-wrapper>` tag will be removed as soon as the component hits the DOM, after first applying its properties to the component itself. Effectively, it will appear as though the controller and CSS were applied directly to the top-level element of the View Component.

> Caveat: If your component doesn't have a single top-level element, the code will automatically create a new `<div>` and wrap the contents of your view in it. This is so that it can apply the controller and CSS parent class.

In order to make this work, we now include a `._base {}` class definition in the `component.scss` that's created when you run `rails generate view_component`. Styles that appear within the `._base` block will be applied directly to the generated CSS class for the component. For example, if your component is called `Foo`, and your `._base` class contained a style rule `background: red;`, the compiled CSS that ends up in `application.css` would be:
In order to make this work, we now support a special `._base {}` class definition in the `component.scss` -- styles that appear within the `._base` block will be applied directly to the generated CSS class for the component. For example, if your component is called `Foo`, and your `._base` class contained a style rule `background: red;`, the compiled CSS that ends up in `application.css` would be:

```
c-foo {
Expand Down Expand Up @@ -111,7 +107,7 @@ A component with this file structure and code:

```
class Foo::Component < ApplicationComponent
enable_wrapper
with_component_assets

def some_method
...
Expand Down Expand Up @@ -159,4 +155,4 @@ Will yield the following raw HTML:
.c-foo .baz {
margin: 2rem;
}
``` -->
```
Loading