Name what a component tag takes in place of each Blade directive

The guard said a directive does not compile inside a component tag but
not what to write instead, and the skill's note said only "use {{ }}".
SealShare's two-factor challenge had @js in an x-data on <x-stack>, and
its implementer had to work out {{ Js::from() }} from Laravel's source.
Each message now names the form: Js::from for @js, json_encode for
@json, Arr::toCssClasses and toCssStyles for @class and @style,
$wire.entangle for @entangle, a bound attribute for @disabled and its
kin, and a prop, an echo or a plain element for control structures
(plan step 46).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 11:13:49 +02:00
co-authored by Claude Opus 5
parent d0bed0da69
commit a5ad6af698
4 changed files with 39 additions and 3 deletions
+18 -1
View File
@@ -376,7 +376,7 @@ class DesignGuard
}
foreach ($this->directivesInComponentTags($contents) as [$line, $directive]) {
$violations[] = "{$where}:{$line} Blade directive `{$directive}` inside a component tag, where it does not compile";
$violations[] = "{$where}:{$line} Blade directive `{$directive}` inside a component tag, where it does not compile".$this->directiveInTag($directive);
}
foreach ($this->forbiddenRoleProps($contents) as [$line, $what]) {
@@ -1208,6 +1208,23 @@ class DesignGuard
return $unknown;
}
/**
* What a component tag takes in place of a directive: an attribute expression, which Blade
* compiles inside the tag.
*/
protected function directiveInTag(string $directive): string
{
return match ($directive) {
'@js' => 'use `{{ \\Illuminate\\Support\\Js::from(…) }}`',
'@json' => 'use `{{ json_encode(…) }}`',
'@class' => 'use `:class="\\Illuminate\\Support\\Arr::toCssClasses([…])"`',
'@style' => 'use `:style="\\Illuminate\\Support\\Arr::toCssStyles([…])"`',
'@entangle' => "use `\$wire.entangle('…')` in the Alpine expression",
'@disabled', '@checked', '@selected', '@readonly', '@required' => 'use `:'.substr($directive, 1).'="…"`',
default => 'use a `:prop` binding or `{{ }}`, or move it to a plain element inside the slot',
};
}
/**
* Blade compiles a component tag before its directives, so `<x-icon @class([...])>` or
* `x-show="ok(@js($v))"` on a component reaches the browser as literal text. Use `:class`