Overview
So far, XB has only had example SDCs and has hence only supported {type: object, …}
SDC prop shapes that have an equivalent field type. For example:
"title": "image",
"type": "object",
"required": ["src"],
"properties": {
"src": {
"title": "Image URL",
"$ref": "json-schema-definitions://experience_builder.module/image-uri"
},
"alt": {
"title": "Alternative text",
"type": "string"
},
"width": {
"title": "Image width",
"type": "integer"
},
"height": {
"title": "Image height",
"type": "integer"
}
}
maps perfectly onto the image
field type (and can also be perfectly represented by a media reference to an @MediaSource=image
-based media type/bundle — see
📌
Introduce `hook_storable_prop_shape_alter()`, use it to prefer the Media Library widget for "image" PropShape if Media Library is installed
Fixed
).
But what about {type: object, …}
shapes that do not happen to have an equivalent in Drupal? How do we map those?
📌
Introduce an example set of representative SDC components; transition from "component list" to "component tree"
Fixed
is introducing the first example SDCs that show that very problem, because it includes for example the following SDC prop JSON schema:
"title": "Heading",
"type": "object",
"required": ["text", "element"],
"properties": {
"text": {
"type": "string",
"title": "Text",
"description": "The heading text.",
"examples": ["A heading element"]
},
"style": {
"type": "string",
"title": "Style",
"description": "The heading style to use.",
"enum": ["primary", "secondary"],
"examples": ["primary", "secondary"]
},
"element": {
"type": "string",
"title": "Element",
"description": "The HTML element to use.",
"enum": ["div", "h1", "h2", "h3", "h4", "h5", "h6"],
"examples": ["h1", "h2", "h3", "h4", "h5", "h6", "div"]
}
}
And perhaps the clearest example: the shoe_button
SDC's icon
prop:
icon:
title: Icon
$ref: json-schema-definitions://experience_builder.module/shoe-icon
type: object
with that schema being defined as:
…
"shoe-icon": {
"title": "Icon",
"type": "object",
"properties": {
"name": {
"type": "string",
"title": "Name",
"description": "The badge’s theme variant.",
"default": "primary",
"enum": [
"moon-stars-fill",
"moon-stars",
"star-fill",
"star",
"stars",
"rocket-fill",
"rocket-takeoff-fill",
"rocket-takeoff",
"rocket"
],
"examples": [
"moon-stars-fill",
"moon-stars",
"star-fill",
"star",
"stars",
"rocket-fill",
"rocket-takeoff-fill",
"rocket-takeoff",
"rocket"
]
},
"label": {
"type": "string",
"title": "Label",
"description": "An alternate description to use for assistive devices. If omitted, the icon will be considered presentational and ignored by assistive devices.",
"default": "This is an icon",
"examples": ["This is an icon"]
},
"size": {
"type": "string",
"title": "Size",
"description": "The icon size.",
"default": "",
"enum": ["", "base", "l", "s", "xs", "xxs"],
"examples": ["", "base", "l", "s", "xs", "xxs"]
},
"color": {
"type": "string",
"title": "Color",
"description": "The icon color",
"default": "",
"enum": [
"",
"gray",
"primary",
"neutral-soft",
"neutral-medium",
"neutral-loud",
"primary-medium",
"primary-loud",
"black",
"white",
"red",
"gold",
"green"
],
"examples": [
"",
"gray",
"primary",
"neutral-soft",
"neutral-medium",
"neutral-loud",
"primary-medium",
"primary-loud",
"black",
"white",
"red",
"gold",
"green"
]
},
"slot": {
"type": "string",
"title": "Slot",
"description": "The slot the icon should appear in",
"examples": []
}
}
},
…
Proposed resolution
Options:
StaticPropSource
currently can only have a single field type (see \Drupal\experience_builder\PropSource\StaticPropSource::__construct(fieldItem)
). As long as that remains the same, the only choice would be to generate a composite field type containing all the necessary field types — basically:
https://www.drupal.org/project/field_union →
- Introduce a new
CompositeStaticPropSource
, that contains multiple StaticPropSource
s — very similar to the current \Drupal\experience_builder\PropSource\AdaptedPropSource
- Either of the above is going to result in rather complex (read: lengthy) JSON blobs. Rather than storing a serialized
StaticPropSource
, for any component prop that does not rely on any computed field property (e.g. the URL of an "image" field type, the processed text of a "text" field type, etc.), store only the resulting value, and "just" compute the appropriate field type on the fly, at edit time, using the infrastructure that
📌
Support complex SDC prop shapes: introduce (Storable)PropShape to compute field type storage settings
Fixed
introduced.
⚠️ Not even considered yet: deep nesting.
📌
Follow-up for #3446722: `side_by_side` + `accordion` (+ maybe `text`) components
Active
contains some SDCs that reuse other SDCs's Twig templates (not, the full SDC, just the Twig template — because SDC does not have the concept of nesting) and hence nest another component's props into a single prop — e.g. the side_by_side
components reusescomponents/simple/heading/heading.component.yml
component. Hence the text
prop for "heading" becomes heading.text
. Another component might even use the "heading" component twice and hence have first_heading.text
and second_heading.text
.
But what if another component reuses side_by_side
? Et cetera? Then it would become side_by_side.first_heading.text
. Do we represent that as nested collapsible fieldsets? That seems bad for UX.
🚨 IOW: I fear that we have far more work to do to properly support every component that
📌
Introduce an example set of representative SDC components; transition from "component list" to "component tree"
Fixed
added, let alone to support arbitrarily complex SDCs.
💡
📌
Auto-create/update Component config entities for all discovered SDCs that meet XB's minimum criteria
Fixed
is adding a mechanism that allows us to define minimum criteria for an SDC to become available in XB. So we could choose to grow those criteria, to only allow SDCs to be used in XB that result in a reasonable UX.
User interface changes
TBD