Replies: 2 comments 2 replies
-
interesting, especially because its a solution for the presentational props problem we talked about long ago with somewhat of the ideas we came up with just lately we had when trying to solve the Kaleidoscope riddle. just to elaborate what i understand as the presentational problem: its the dilemma of having to specify props in the integration already which are rather independent of integration like the font or colour. Imagine a box with dark background where a subcomponent, the text should be light. Now how should the integration now that headlines in this box should use the variant light? Without having designed the components themselves this must be tested out. When we talked before about that i think we also considered options like specifying just the Headline props and separating the rendering
Or possibly also overriding the variant from a headline by recreating it:
|
Beta Was this translation helpful? Give feedback.
-
That's another great example, yes! In the above schema it would be
, transpiled to final readonly class Headline extends AbstractComponent
{
/**
* @internal only for deserialization
*/
public function __construct(
public TagName $tagName,
public string $content,
public Color $color,
) {
}
/**
* @api to be used in integration
*/
public static function create(
TagName $tagName,
string $content
): self {
return new self(
tagName: $tagName,
content: $content,
color: Color::DARK, // the default
);
}
/**
* @internal to be used for prop merging
*/
public function with(
?TagName $tagName = null,
?string $content = null,
?Color $color = null,
): self {
return new self(
$tagName !== null ? $tagName : $tagName->image,
$content !== null ? $content : $this->content,
$color !== null ? $color : $this->color,
);
}
public function render(): string
{
return '<' . $this->tagName . ' class="' . match($this->color) { Color::LIGHT => 'color-light', Color::DARK => 'color-dark' } . '">' . $this->content . '</' . $this->tagName . '>';
}
} and
transpiling to final readonly class Box extends AbstractComponent
{
/**
* @internal only for deserialization
*/
public function __construct(
public Headline $headline,
) {
}
/**
* @api to be used in integration
*/
public static function create(
Headline $headline, // a headline without meaningful color, which cannot be set by integration
): self {
return new self(
headline: $headline->with(color: Color::LIGHT),
);
}
/**
* @internal to be used for prop merging
*/
public function with(
?Headline $headline,
): self {
return new self(
$headline !== null ? $headline : $this->headline,
);
}
public function render(): string
{
return '<div class="bg-dark">' . $this->headline . '</div>';
}
} In the factory we can now just call class SomeFactory
{
public function forSomeNode(Node $node): Box
{
return Box::create(
headline: Headline::create(
type: HeadlineType::H2,
content: $node->getProperty('headline')
),
);
}
} to wrap the headline properly in a (dark background) box. The followup question would now be: What if the box itself can be dark or light and the headline must always have the inverse color? Is that something we have to handle here (like doing a match on the internal headline color) or can this be done more elegantly in CSS without needing this? |
Beta Was this translation helpful? Give feedback.
-
When using nested components, it makes sense to separate props into those that are passed in from outside (e.g. content, a Kaleidoscope image source or a headline type) from those the outer component wants to define for its children. A composite card component might want to enforce the size of its headline e.g.
Let's assume we have three components: Headline, ImageTag and Card, which combines the first two:
which transpiles to
,
which transpiles to
and
which transpiles to
In the PHP integration we can now call
The handling of component proxies, like Kaleidoscope does it, follows in the next part.
WDYT?
Beta Was this translation helpful? Give feedback.
All reactions