Skip to content

Commit 7136a99

Browse files
committed
fix: alpine attributes in storybook should be handled just like data-* as an object
1 parent c147a29 commit 7136a99

114 files changed

Lines changed: 1347 additions & 514 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/TemplateGenerator/StorybookJSGenerator.php

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,25 @@ public function renderElement(HTMLElementDelegatorInterface $element): string
217217
continue;
218218
}
219219

220+
// Special handling for Alpine attributes - treat like data-* but use x-* prefix
221+
if ($propName === 'alpineAttributes') {
222+
$jsVarName = 'alpineAttributes';
223+
if (! in_array($jsVarName, $props, true)) {
224+
$props[] = $jsVarName;
225+
$argTypes[] = $this->generateArgType($jsVarName, [
226+
'type' => 'object',
227+
'description' => 'Alpine.js directive attributes (x-*). Provide an object with key-value pairs.',
228+
'required' => false,
229+
'defaultValue' => '{}',
230+
'choices' => null,
231+
]);
232+
$defaultArgs[$jsVarName] = '{}';
233+
// Special render assignment for Alpine attributes
234+
$renderAssignmentsMap[$jsVarName] = $this->generateAlpineAttributesAssignment();
235+
}
236+
continue;
237+
}
238+
220239
// some trait file names use camelcase that maps directly to attribute name
221240
$getter = 'get' . ucfirst($propName);
222241
if (! method_exists($example, $getter)) {
@@ -348,20 +367,41 @@ public function renderElement(HTMLElementDelegatorInterface $element): string
348367
$elementSpecificProps[] = $jsVarName;
349368

350369
$props[] = $jsVarName;
351-
$argTypes[] = $this->generateArgType($jsVarName, [
352-
'type' => $phpType,
353-
'description' => '',
354-
'required' => false,
355-
'defaultValue' => $this->getDefaultValue($phpType, $choices),
356-
'choices' => $choices,
357-
]);
358370

359-
$defaultArgs[$jsVarName] = $this->getDefaultValueJs($phpType, $choices);
360-
$renderAssignmentsMap[$jsVarName] = $this->generateRenderAssignment(
361-
$jsVarName,
362-
$this->camelToKebab($propName),
363-
$phpType
364-
);
371+
if ($propName === 'alpineAttributes') {
372+
// Force Alpine attributes to be treated as an object (x-* directives)
373+
$phpType = 'object';
374+
$choices = null;
375+
376+
$argTypes[] = $this->generateArgType($jsVarName, [
377+
'type' => $phpType,
378+
'description' => 'Alpine.js directive attributes (x-*). Provide an object with key-value pairs.',
379+
'required' => false,
380+
'defaultValue' => '{}',
381+
'choices' => null,
382+
]);
383+
384+
// Use object default (unquoted) in generated args
385+
$defaultArgs[$jsVarName] = '{}';
386+
387+
// Use the specialized Alpine assignment
388+
$renderAssignmentsMap[$jsVarName] = $this->generateAlpineAttributesAssignment();
389+
} else {
390+
$argTypes[] = $this->generateArgType($jsVarName, [
391+
'type' => $phpType,
392+
'description' => '',
393+
'required' => false,
394+
'defaultValue' => $this->getDefaultValue($phpType, $choices),
395+
'choices' => $choices,
396+
]);
397+
398+
$defaultArgs[$jsVarName] = $this->getDefaultValueJs($phpType, $choices);
399+
$renderAssignmentsMap[$jsVarName] = $this->generateRenderAssignment(
400+
$jsVarName,
401+
$this->camelToKebab($propName),
402+
$phpType
403+
);
404+
}
365405
}
366406
}
367407

@@ -566,6 +606,17 @@ private function generateDataAttributesAssignment(): string
566606
return $assignment;
567607
}
568608

609+
private function generateAlpineAttributesAssignment(): string
610+
{
611+
$assignment = " if (alpineAttributes && typeof alpineAttributes === 'object') {\n";
612+
$assignment .= " Object.keys(alpineAttributes).forEach(key => {\n";
613+
$assignment .= " el.setAttribute(`x-\${key}`, alpineAttributes[key]);\n";
614+
$assignment .= " });\n";
615+
$assignment .= ' }';
616+
617+
return $assignment;
618+
}
619+
569620
private function buildStorybookJS(
570621
string $elementName,
571622
string $name,
@@ -630,6 +681,13 @@ private function buildStorybookJS(
630681
$js .= " };\n";
631682
$js .= " Object.entries(args).forEach(([key, value]) => {\n";
632683
$js .= " if (key === 'text' || value === undefined || value === \"\") return;\n";
684+
$js .= " if (key === 'alpineAttributes' && typeof value === 'object') {\n";
685+
$js .= " Object.keys(value).forEach(attrKey => {\n";
686+
$js .= " el.setAttribute(`x-\${attrKey}`, value[attrKey]);\n";
687+
$js .= " });\n";
688+
$js .= " return;\n";
689+
$js .= " }\n";
690+
633691
$js .= " if (key === 'data' && typeof value === 'object') {\n";
634692
$js .= " Object.keys(value).forEach(dataKey => {\n";
635693
$js .= " el.setAttribute(`data-\${dataKey}`, value[dataKey]);\n";

templates/storybook/stories/block/article/article.stories.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Article
77
* @description The article element represents a self-contained composition in a document, page, application, or site, which is intended to be independently distributable or reusable.
88
*/
@@ -48,12 +48,13 @@ export default {
4848
},
4949
alpineAttributes: {
5050
type: {
51-
name: "string",
51+
name: "object",
5252
required: false
5353
},
54-
defaultValue: "Sample value",
54+
description: "Alpine.js directive attributes (x-*). Provide an object with key-value pairs.",
55+
defaultValue: {},
5556
control: {
56-
type: "text"
57+
type: "object"
5758
},
5859
},
5960
ariaAtomic: {
@@ -382,6 +383,12 @@ export default {
382383
};
383384
Object.entries(args).forEach(([key, value]) => {
384385
if (key === 'text' || value === undefined || value === "") return;
386+
if (key === 'alpineAttributes' && typeof value === 'object') {
387+
Object.keys(value).forEach(attrKey => {
388+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
389+
});
390+
return;
391+
}
385392
if (key === 'data' && typeof value === 'object') {
386393
Object.keys(value).forEach(dataKey => {
387394
el.setAttribute(`data-${dataKey}`, value[dataKey]);
@@ -414,7 +421,7 @@ export const Default = {
414421
args: {
415422
text: "Sample text",
416423
accesskey: "Sample value",
417-
alpineAttributes: "Sample value",
424+
alpineAttributes: {},
418425
ariaAtomic: "",
419426
ariaBusy: "",
420427
ariaControls: "Sample value",

templates/storybook/stories/block/aside/aside.stories.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Aside
77
* @description The aside element represents a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content.
88
*/
@@ -48,12 +48,13 @@ export default {
4848
},
4949
alpineAttributes: {
5050
type: {
51-
name: "string",
51+
name: "object",
5252
required: false
5353
},
54-
defaultValue: "Sample value",
54+
description: "Alpine.js directive attributes (x-*). Provide an object with key-value pairs.",
55+
defaultValue: {},
5556
control: {
56-
type: "text"
57+
type: "object"
5758
},
5859
},
5960
ariaAtomic: {
@@ -392,6 +393,12 @@ export default {
392393
};
393394
Object.entries(args).forEach(([key, value]) => {
394395
if (key === 'text' || value === undefined || value === "") return;
396+
if (key === 'alpineAttributes' && typeof value === 'object') {
397+
Object.keys(value).forEach(attrKey => {
398+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
399+
});
400+
return;
401+
}
395402
if (key === 'data' && typeof value === 'object') {
396403
Object.keys(value).forEach(dataKey => {
397404
el.setAttribute(`data-${dataKey}`, value[dataKey]);
@@ -424,7 +431,7 @@ export const Default = {
424431
args: {
425432
text: "Sample text",
426433
accesskey: "Sample value",
427-
alpineAttributes: "Sample value",
434+
alpineAttributes: {},
428435
ariaAtomic: "",
429436
ariaBusy: "",
430437
ariaControls: "Sample value",

templates/storybook/stories/block/audio/audio.stories.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Audio
77
* @description The audio element is used to embed sound content in documents. It may contain one or more audio sources, represented using the src attribute or the source element.
88
*/
@@ -48,12 +48,13 @@ export default {
4848
},
4949
alpineAttributes: {
5050
type: {
51-
name: "string",
51+
name: "object",
5252
required: false
5353
},
54-
defaultValue: "Sample value",
54+
description: "Alpine.js directive attributes (x-*). Provide an object with key-value pairs.",
55+
defaultValue: {},
5556
control: {
56-
type: "text"
57+
type: "object"
5758
},
5859
},
5960
ariaAtomic: {
@@ -379,6 +380,12 @@ export default {
379380
};
380381
Object.entries(args).forEach(([key, value]) => {
381382
if (key === 'text' || value === undefined || value === "") return;
383+
if (key === 'alpineAttributes' && typeof value === 'object') {
384+
Object.keys(value).forEach(attrKey => {
385+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
386+
});
387+
return;
388+
}
382389
if (key === 'data' && typeof value === 'object') {
383390
Object.keys(value).forEach(dataKey => {
384391
el.setAttribute(`data-${dataKey}`, value[dataKey]);
@@ -411,7 +418,7 @@ export const Default = {
411418
args: {
412419
text: "Sample text",
413420
accesskey: "Sample value",
414-
alpineAttributes: "Sample value",
421+
alpineAttributes: {},
415422
ariaAtomic: "",
416423
ariaBusy: "",
417424
ariaControls: "Sample value",

templates/storybook/stories/block/blockquote/blockquote.stories.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Blockquote
77
* @description The blockquote element represents a section that is quoted from another source. Content inside a blockquote must be quoted from another source, whose address, if it has one, may be cited in the cite attribute.
88
*/
@@ -48,12 +48,13 @@ export default {
4848
},
4949
alpineAttributes: {
5050
type: {
51-
name: "string",
51+
name: "object",
5252
required: false
5353
},
54-
defaultValue: "Sample value",
54+
description: "Alpine.js directive attributes (x-*). Provide an object with key-value pairs.",
55+
defaultValue: {},
5556
control: {
56-
type: "text"
57+
type: "object"
5758
},
5859
},
5960
ariaAtomic: {
@@ -393,6 +394,12 @@ export default {
393394
};
394395
Object.entries(args).forEach(([key, value]) => {
395396
if (key === 'text' || value === undefined || value === "") return;
397+
if (key === 'alpineAttributes' && typeof value === 'object') {
398+
Object.keys(value).forEach(attrKey => {
399+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
400+
});
401+
return;
402+
}
396403
if (key === 'data' && typeof value === 'object') {
397404
Object.keys(value).forEach(dataKey => {
398405
el.setAttribute(`data-${dataKey}`, value[dataKey]);
@@ -425,7 +432,7 @@ export const Default = {
425432
args: {
426433
text: "Sample text",
427434
accesskey: "Sample value",
428-
alpineAttributes: "Sample value",
435+
alpineAttributes: {},
429436
ariaAtomic: "",
430437
ariaBusy: "",
431438
ariaControls: "Sample value",

templates/storybook/stories/block/body/body.stories.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Body
77
* @description The body element represents the content of an HTML document. All the contents such as text, images, headings, links, tables, etc. are placed between the body tags.
88
*/
@@ -332,6 +332,12 @@ export default {
332332
};
333333
Object.entries(args).forEach(([key, value]) => {
334334
if (key === 'text' || value === undefined || value === "") return;
335+
if (key === 'alpineAttributes' && typeof value === 'object') {
336+
Object.keys(value).forEach(attrKey => {
337+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
338+
});
339+
return;
340+
}
335341
if (key === 'data' && typeof value === 'object') {
336342
Object.keys(value).forEach(dataKey => {
337343
el.setAttribute(`data-${dataKey}`, value[dataKey]);

templates/storybook/stories/block/canvas/canvas.stories.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
*
33
* THIS FILE IS AUTOGENERATED. DO NOT EDIT IT.
44
*
5-
* @generated December 31, 2025 00:35
5+
* @generated January 12, 2026 07:07
66
* @component Canvas
77
* @description The canvas element is used to draw graphics, on the fly, via scripting (usually JavaScript).
88
*/
@@ -48,12 +48,13 @@ export default {
4848
},
4949
alpineAttributes: {
5050
type: {
51-
name: "string",
51+
name: "object",
5252
required: false
5353
},
54-
defaultValue: "Sample value",
54+
description: "Alpine.js directive attributes (x-*). Provide an object with key-value pairs.",
55+
defaultValue: {},
5556
control: {
56-
type: "text"
57+
type: "object"
5758
},
5859
},
5960
ariaAtomic: {
@@ -403,6 +404,12 @@ export default {
403404
};
404405
Object.entries(args).forEach(([key, value]) => {
405406
if (key === 'text' || value === undefined || value === "") return;
407+
if (key === 'alpineAttributes' && typeof value === 'object') {
408+
Object.keys(value).forEach(attrKey => {
409+
el.setAttribute(`x-${attrKey}`, value[attrKey]);
410+
});
411+
return;
412+
}
406413
if (key === 'data' && typeof value === 'object') {
407414
Object.keys(value).forEach(dataKey => {
408415
el.setAttribute(`data-${dataKey}`, value[dataKey]);
@@ -435,7 +442,7 @@ export const Default = {
435442
args: {
436443
text: "Sample text",
437444
accesskey: "Sample value",
438-
alpineAttributes: "Sample value",
445+
alpineAttributes: {},
439446
ariaAtomic: "",
440447
ariaBusy: "",
441448
ariaControls: "Sample value",

0 commit comments

Comments
 (0)