2024-11-13
Card component architecture design decisions
Card components are very flexible, which means they could basically do anything - making the design of it a surprising challenge. Let's talk about that.
By just looking at the examples below card-alternative.html
is much more elegant and semantic than the card you'll find today in Open Props UI.
<div class="card">
<hgroup>
<!-- -->
</hgroup>
<div class="content">
<!-- -->
</div>
<div class="actions">
<!-- -->
</div>
</div>
<article class="card">
<header>
<!-- -->
</header>
<div class="content">
<!-- -->
</div>
<footer>
<!-- -->
</footer>
</article>
This would unfortunately cause inconsistencies between components. The accordion component already follows the heading/content/actions pattern - having cards use a different structure would mean developers would need to remember two different approaches for basically the same layout.
<details>
<summary>
<!-- -->
</summary>
<div class="content">
<!-- -->
</div>
<div class="actions">
<!-- -->
</div>
</details>
<div class="card">
<hgroup>
<!-- -->
</hgroup>
<div class="content">
<!-- -->
</div>
<div class="actions">
<!-- -->
</div>
</div>
The alternative is to wrap the accordion content in an <article>
element so we can define a sectioning content, thereby allowing us to use the <footer>
instead of the .actions
class.
<details>
<summary>
<!-- -->
</summary>
<article>
<div class="content">
<!-- -->
</div>
<footer>
<!-- -->
</footer>
</article>
</details>
This though, doesn't look right at all. Why? Well, according to the MDN each <article>
should among other things:
- represent a self-contained, independent item of content
- "be identified, typically by including a heading (
<h1>
-<h6>
element) as a child of the<article>
element".
This solution doesn't really meet those criteria.
The decision
❌ Have different HTML structures for the accordion, card and any other future component that might share the same heading, content, actions structure. This solution should promote more semantic HTML.
✅ Streamline the structure into a more cohesive one. It prioritizes DX over perfect semantics and should result in less things to memorize and reduce cognitive load.
Reasoning
Reducing the learning curve and barrier to entry when making a component library is one of the most important aspects. This isn't black and white and, of course depends ™️ but in this case it was the right call. This perfectly illustrates the tension in component library design between what's theoretically pure and practical.
Do you agree? If not, let me know or why not open an issue or a PR? 😃