Document Blade Components within Antlers - #1979
Open
JohnathonKoster wants to merge 3 commits into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documents how to use Blade components within Antlers and how to write Blade components using Antlers (what a sentence 🤣)
Overview
Components are reusable, self-contained chunks of interface, such as callouts, cards, buttons, layouts, or whatever else you keep copying and pasting around your site. Antlers can render Laravel Blade components, and anonymous components can be written with Antlers itself.
That gives you two closely related flavors of angle-bracket syntax:
<x-callout /><s:collection:blog>...</s:collection:blog>{{ collection:blog }}...{{ /collection:blog }}:::tip
Partials inherit the current Antlers scope and are perfect for straightforward includes. Components have their own scope and explicitly receive data through props, the Cascade, and slots.
:::
Creating a component
Anonymous components live in
resources/views/components. Give the view an.antlers.htmlextension to build it with Antlers:Render it from any Antlers template with an
x-tag. Paired components receive everything between their tags as the defaultslot:Components without slot content may self-close:
Components in subdirectories use dot notation. For example,
resources/views/components/menu/item.antlers.htmlbecomes<x-menu.item />.:::tip
Blade components work, too! Use them from Antlers without rewriting anything. Blade and Antlers components may even nest inside each other like one big, happy template-language family.
:::
Props
The
@propsdirective defines the data your component expects. Values with named keys provide defaults, and those defaults are Antlers expressions, not PHP. That means variables, operators, and modifiers likeupperare all fair game, if that's your style.@props([ 'type' => 'info', 'title' => 'Heads up!' | upper, ])Literal attributes pass strings. Prefix an attribute with
:to resolve its value from the Antlers scope, or use:$variablewhen the prop and variable share a name:{{ page_title = 'Back up first' }} {{ type = 'warning' }} <x-callout :title="page_title" :$type />These are Antlers' usual parameter rules, even when the component itself is written in Blade.
Attributes
Attributes not declared as props are collected in the
attributesbag. Render the bag directly, or call its Laravel methods with Antlers' dot syntax:The
mergemethod adds the component's default attributes while preserving those passed by the caller. Class names are combined, so our earlierclass="mt-8"joins the callout classes instead of booting them out of the club.Slots
The
slotvariable contains the component's unnamed content. Use thehas_actual_contentmodifier when whitespace and HTML comments alone should count as empty:{{ if slot | has_actual_content }} <div>{{ slot }}</div> {{ /if }}The closely related
is_stringmodifier is available when you need to distinguish an ordinary string from a slot object or another value:{{ if value | is_string }} {{ value }} {{ /if }}Named slots
Use
<x-slot:name>to send content to a named slot:The component receives the slot as a variable. Any attributes on the slot are available through its own
attributesbag:Scope
A component does not inherit the Antlers variables or Cascade data around it. Variables created inside the component do not leak out, either. Pass values as props when they are part of the component's public API.
Slot content is the intentional exception. It is evaluated in the caller's scope, so variables available where you invoke the component remain available inside its default and named slots.
Cascade data
Use
@cascadewhen a component needs data from Statamic's Cascade. Pass a list to import only the values you need. Values listed without defaults are required; a named key may provide a fallback:@cascade([ 'title', 'eyebrow' => 'Latest', ]) <h2>{{ title }}</h2> <p>{{ eyebrow }}</p>Omit the arguments to import the entire Cascade:
Pulling in everything is convenient, but selecting values keeps the component's dependencies much easier to spot six months from now.
Sharing parent props
The
@awaredirective lets a nested component consume props explicitly passed to an ancestor component. Here, the menu item picks up the menu'stone:Like
@props, the values passed to@awareare Antlers expressions. Providing a fallback keeps the nested component useful when it appears outside its usual parent.Escaping directives
If you need any of these directives to appear as literal text, add another
@:This renders
@props(['example']),@aware(['example']), and@cascadewithout evaluating them.Component-style Statamic Tags
Statamic Tags may also use HTML-like syntax in Antlers. Prefix the Tag with either
s:orstatamic:and otherwise use it as normal:This is equivalent to classic Antlers syntax:
{{ collection:pages limit="3" }} <a href="{{ url }}">{{ title }}</a> {{ /collection:pages }}Parameters still follow Antlers rules, including dynamic values and shorthand:
You may use
s-andstatamic-prefixes instead if dashes feel more HTML-ish, and Tags without enclosed content may self-close. This syntax still invokes a Statamic Tag; it does not look for a component view inresources/views/components.