diff --git a/compare/slim.md b/compare/slim.md index e6aa248..bd9a003 100644 --- a/compare/slim.md +++ b/compare/slim.md @@ -1 +1,40 @@ # Phlex vs Slim + +[Slim](https://slim-template.github.io)’s goal is reduce templating syntax to just the essential parts without becoming cryptic. + +We can’t really make a direct comparison between Phlex and Slim becuase Slim is not a component framework and Phlex is not a templating language. However, there are some similarities between the two that we can look at. We can also get into why Phlex is designed around this idea of a “component”. + +### Minimal templating syntax + +If you’re using Slim, there’s a good chance you wanted something with a more minimal syntax than ERB, especially when it comes to switching between the HTML parts and the Ruby parts, such as an `if` conditional. + +Phlex too has a pretty minimal syntax, with one significant difference: the Phlex syntax is just Ruby. You don’t need to learn anything else, you already know it. Modules, classes, methods, arguments, blocks. That’s it. + +Because it’s just Ruby, the transition between the Ruby code and the template code is even more seamless. There’s no transition because it’s all Ruby. One factor to consider is Ruby doesn’t have significant whitespace. + +### Components and abstraction + +Phlex is designed around the idea of a “component”. A component is a Ruby class that represents a small part of the page. Extracting small components helps keep your user experience consistent and makes your code much easier to maintain in the long run. + +Additionally, because Phlex is just Ruby, you can start by extracting methods. + +```ruby +def MyButton(...) + button(class: "my button classes", ...) +end +``` + +When you realise you need more options, you can upgrade that to a class. + +```ruby +class MyButton < ApplicationComponent + def initialize(style:, color:) + @style = style + @color = color + end + + def view_template(&) + button(class: [@style, @color], &) + end +end +``` diff --git a/handbook/attributes.md b/handbook/attributes.md index 86ed62f..1b0d10c 100644 --- a/handbook/attributes.md +++ b/handbook/attributes.md @@ -48,7 +48,21 @@ h1(data: { controller: "hello" }) { "Hello!" } ## Attribute values -You’ve seen how string values work. Symbols behave the same way. You’ve also seen how to nest attributes with hashes. But Phlex allows a few other types of attribute value. +### Symbols + +Like keys, if you use symbols for values, Phlex will convert them to strings, replacing underscores `_` with dashes `-`. + +::: code-group + +```ruby [component] +div(contenteditable: :plaintext_only) +``` + +```html [output] +
+``` + +::: ### Arrays and sets @@ -84,7 +98,9 @@ textarea(disabled: false) ::: ::: tip -Some HTML attributes such as `contenteditable` require you to pass `"true"` or `"false"` as a string. These are not technically “boolean” attributes, they're “enumerated” attributes. The distinction is subtle but important. +Some HTML attributes such as `contenteditable` require you to pass `"true"` or `"false"` as strings. These are not really _boolean_ attributes even though they look similar; they’re technically _“enumerated”_ attributes. + +According to [the MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/contenteditable), `contenteditable` accepts `"true"`, `"false"` or `"plaintext-only"`. The presence of this third option explains why `contenteditable` is not a boolean attribute. It also means new modes could be added in the future without breaking existing code. ::: @@ -130,8 +146,24 @@ a( 👋 Hello World! ``` +::: + In this example, the `button` class is always added, while the `active` and `disabled` classes are conditional. You can read `=>` as “if”. +Phlex also ignores `nil` values, so another way you could write this is: + +```ruby +a( + class: [ + ("button"), + ("active" if is_active), + ("disabled" if is_disabled) + ] +) { "Click me" } +``` + +The parentheses around `"button"` here are not strictly necessary because it’s not paired with a conditional, but they make the code more consistent. Also, this last technique works for any attribute, not just `class`. + ### `style` Like `class`, the `style` attribute has special behaviour. If you pass a Hash to `style`, Phlex will convert it to a CSS string: diff --git a/handbook/helpers.md b/handbook/helpers.md new file mode 100644 index 0000000..d5347a3 --- /dev/null +++ b/handbook/helpers.md @@ -0,0 +1 @@ +# Helpers diff --git a/handbook/testing.md b/handbook/testing.md new file mode 100644 index 0000000..f00b526 --- /dev/null +++ b/handbook/testing.md @@ -0,0 +1 @@ +# Testing diff --git a/index.md b/index.md index 94ef432..94654a0 100644 --- a/index.md +++ b/index.md @@ -16,17 +16,17 @@ hero: features: - title: Pure, beautiful Ruby - icon: 💎 - details: Phlex gives you HTML semantics in Ruby syntax so you can use your existing skills designing object-oriented views. Plus, you get to use tools like RubyLSP, Rubocop and Simplecov. + icon: 🧑‍🍳 + details: Phlex gives you HTML semantics in Ruby so you can use your existing skills designing object-oriented views. Plus, you get to use tools like RubyLSP, Rubocop and Simplecov. - title: Fast enough icon: 🚀 - details: Phlex renders HTML at over 1gbps on a MacBook Pro and unlike Rails partials, it doesn’t slow down the more components you extract. + details: Phlex renders HTML at ~1gbps per core on a MacBook Pro (M3 Max) and it doesn’t slow down the more components you extract. - title: Rails integration icon: 🚂 details: Phlex works great with Rails. It supports all Rails helpers and plays nicely with ViewComponent, ActionView, Stimulus, Turbo and Tailwind. - title: Structural safety icon: 🛡️ - details: Phlex is designed to prevent cross-site-scripting (XSS) attacks by default. + details: Phlex is designed to structurally prevent cross-site-scripting (XSS) attacks by default. - title: Sensible isolation icon: 🧪 details: Phlex components only depend on the data you pass in, making them easier to test and reuse. @@ -39,7 +39,7 @@ features: - title: Selective rendering icon: 🔎 details: You can render a view targeting a specific DOM ID. Phlex only does the work to render just the parts you want. This is great for partial Hotwire updates like Turbo Frames. - - title: Streamable + - title: Streaming icon: 🌊 - details: Phlex can stream responses to boost time to first byte (TTFB). In some cases users can see static content before the database has even responded. + details: Phlex can stream responses to boost time to first byte (TTFB). In some cases users can see the first static content before the database has even responded. --- diff --git a/project/community.md b/project/community.md index 868bbb6..c228e6e 100644 --- a/project/community.md +++ b/project/community.md @@ -19,7 +19,7 @@ ## Articles 📝 -- [Phlex not ERB](https://judoscale.com/blog/phlex-not-erb) +- [Say No To Partials And Helpers For A Maintainable Rails Front-End](https://judoscale.com/blog/phlex-not-erb) - [A Tale of two Phlexes](https://blog.willcosgrove.com/a-tale-of-two-phlexes) ## Third-party component libraries 📚