Skip to content

Add new 'card' page to example site + new tests for cards #305

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: content-re-grid
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 44 additions & 44 deletions assets/css/v2/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,9 @@ nav {
[data-grid="last-third"] {
grid-column: 1;
}
[data-grid="halve"] {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be half, since halve is the verb 🤔

grid-column: 1;
}

@media (min-width: 55rem) {
max-width: var(--content-max-width);
Expand All @@ -905,6 +908,10 @@ nav {
[data-grid="last-third"] {
grid-column: 8 / -1;
}

[data-grid="halve"] {
grid-column: span 6;
}
}
}

Expand Down Expand Up @@ -1451,7 +1458,7 @@ h6:has(a):hover {
}

/* Landing page cards */
.text-content .card-layout {
.card-layout {
grid-column: 1;

.card-section {
Expand All @@ -1463,65 +1470,58 @@ h6:has(a):hover {
font-weight: 500;
}

/* Hide all the cards past 3 if it is a featured card section */
&.featured-section {
.card-section-content.card-grid
> *:nth-child(n + 4 of div.card-container) {
/* Hide all the cards past 3 if it is a featured card section */
.card-section-content > *:nth-child(n + 4 of div.card) {
display: none;
}
}
}
}

/* Optional grid layout */
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(33%, 1fr));
gap: 1.5rem;

.card-container {
border: 1px solid oklch(var(--color-codeblock-border));
box-shadow: 3px 3px 0px oklch(var(--color-shadow));
padding: 1rem;
.card {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
order: 2;

&.featured-card {
/* If there is a need for a featured card, only the featured card should be full length */
grid-column: 1 / -1;
order: 1;
}

/* If there is a featured card AND two cards, the last one should be full length */
~ .card-container:nth-child(2n):last-child {
grid-column: 1 / -1;
.card-header {
display: flex;
flex-direction: row;
gap: 0.5rem;

.card-brand-icon {
height: 20px;
width: auto;
}
}
}

/* If there is no featured card, last card that is the 3rd one should be full width */
&:not(:has(.featured-card)) *:nth-child(n + 3 of div.card-container) {
grid-column: 1 / -1;
h2 {
padding: 0;
margin: 0;
font-size: 1rem;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use one of the clamped font variables here, I think --font-step-1 should be pretty close.

}
}
}
}

.card-container {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;

.card-header {
display: flex;
flex-direction: row;
gap: 0.5rem;
/* Optional grid layout */
.card-grid {
display: grid;
grid-template-columns: repeat(var(--grid-columns), 1fr);
gap: 1.5rem;

.card-brand-icon {
height: 20px;
width: auto;
}
@media (max-width: 68rem) {
grid-template-columns: 1fr;
}

h2 {
padding: 0;
margin: 0;
font-size: 1rem;
}
.card {
border: 1px solid oklch(var(--color-codeblock-border));
box-shadow: 3px 3px 0px oklch(var(--color-shadow));
padding: 1rem;
}
}

Expand Down
5 changes: 5 additions & 0 deletions exampleSite/content/test-product/cards/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
description: Card usage
title: Cards
weight: 300
---
120 changes: 120 additions & 0 deletions exampleSite/content/test-product/cards/permitted.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
---
description: Card usage
title: Usage
weight: 100
---
## General usage
The structure of a card looks like the following:
```plaintext
<card-layout >
<card-section>
<card title="SOME_TITLE">SOME CONTENT icon="SOME_LUCIDE_ICON"><\card>
...
<card>SOME CONTENT<\card>
</card-section>
</card-layout >
```

and will render as the following:
<div data-testid="cards-test__basic">
{{<card-layout >}}
{{<card-section>}}
{{<card title="SOME_TITLE">}}
SOME CONTENT
{{</card >}}
{{</card-section>}}
{{</card-layout >}}
</div>

### Params
To support customization, there are also some params you can add to the shortcode `<card>` such as `title`, `titleUrl`, `icon`, `brandIcon`, `isFeaturedCard`, `isFullSize`.

* `title` - Title of the card.
<br>
* `titleUrl` - URL for the card.
<br>
* `icon` - Custom icon using <a href="https://lucide.dev/icons/">lucide</a> icons.
<br>
* `brandIcon` - Custom icon using image from `nginx-hugo-theme/static/images/icons`.
* Usage: `<card brandIcon="NGINX-App-Protect-WAF-product-icon"...>`
<br>
* `isFeaturedCard` - Boolean indicating whether or not the card should be the first one and full size. By default, false.
* Usage: `<card isFeaturedCard="true"...>`
<br>
* `isFullSize` - Boolean indicating whether or not the card should be full size. By default, cards are half sized.
* Usage: `<card isFullSize="true"...>`

For the `<card-section>`, there are some params you can add such as `title`, `isFeaturedSection`, and `showAsCards`.
* `title` - Title of the section.
<br>
* `isFeaturedSection` - Boolean indicating whether or not the section is a featured one - will discuss later down the page. By default, false.
<br>
* `showAsCards` - Boolean indicating whether or not the cards in the section should appear with borders. By default, false.

### Additional Information
While it may come immediate, you can't use a `<card>` shortcode on its own in your markdown or else the build will fail. This is because if you call a card, there is no way to structure it in a writer-friendly customizable way.

## Show as cards
As you can see from the above example in 'General usage', it renders as a plain box that does not resemble a card. To change the appearance and render as a card, use the param `showAsCards` in the shortcode `<card-section>`. The usage as seen below:
```plaintext
<card-layout >
<card-section showAsCards="true">
<card title="SOME_TITLE">SOME CONTENT icon="SOME_LUCIDE_ICON"><\card>
...
<card>SOME CONTENT<\card>
</card-section>
</card-layout >
```
and will render as the following:
<div data-testid="cards-test__showAsCards">
{{<card-layout >}}
{{<card-section showAsCards="true">}}
{{<card title="SOME_TITLE">}}
SOME CONTENT
{{</card >}}
{{</card-section>}}
{{</card-layout >}}
</div>

## Featured Section
Denoted by the param `isFeaturedSection` in the shortcode `<card-layout>`, this block of cards can contain only up to three cards.

<div data-testid="cards-test__featuredSection">
{{<card-layout >}}
{{<card-section showAsCards="true" isFeaturedSection="true">}}
{{<card title="Everything" titleUrl="everything" icon="circle-dot-dashed">}}
All shortcodes in one page.
{{</card >}}
{{<card title="Call Out usages" titleUrl="call-out/all-callouts/" icon="message-square">}}
Examples for call-out shortcode
{{</card >}}
{{<card title="Code Block usages" titleUrl="code-blocks/code-blocks-highlighting/" icon="code">}}
Examples for codeblock shortcode
{{</card >}}
{{<card title="Code Block usages" titleUrl="code-blocks/code-blocks-highlighting/" icon="code">}}
Examples for codeblock shortcode
{{</card >}}
{{</card-section>}}
{{</card-layout >}}
</div>

## Featured Card
Denoted by the param `isFeaturedCard` in the shortcode `<card>`, this will push the card up to very top of the section and make it full length.
<div data-testid="cards-test__featuredCard">
{{<card-layout >}}
{{<card-section showAsCards="true">}}
{{<card title="Everything" titleUrl="everything" icon="circle-dot-dashed">}}
All shortcodes in one page.
{{</card >}}
{{<card title="Call Out usages" titleUrl="call-out/all-callouts/" icon="message-square">}}
Examples for call-out shortcode
{{</card >}}
{{<card title="Code Block usages" titleUrl="code-blocks/code-blocks-highlighting/" icon="code" isFeaturedCard="true">}}
Examples for codeblock shortcode
{{</card >}}
{{<card title="Code Block usages" titleUrl="code-blocks/code-blocks-highlighting/" icon="code">}}
Examples for codeblock shortcode
{{</card >}}
{{</card-section>}}
{{</card-layout >}}
</div>
2 changes: 1 addition & 1 deletion layouts/shortcodes/card-layout.html
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<!-- Render the main content first with modifications, then render the custom content -->
<div class="card-layout">{{- .Inner | markdownify -}}</div>
<div class="card-layout" data-testid="card-layout">{{- .Inner | markdownify -}}</div>
11 changes: 8 additions & 3 deletions layouts/shortcodes/card-section.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{{ $title := .Get "title" }}
{{ $isFeaturedSectionParam := .Get "isFeaturedSection" | default "false" }}
{{ $showAsCardsParam := .Get "showAsCards" | default "false"}}

{{- /* Validate the parameter strictly */ -}}
{{- if not (in (slice "true" "false") $showAsCardsParam) -}}
{{- warnf "The '<card-section>' Shortcode parameter 'showAsCards' must be 'true' or 'false', but got: '%s'. This will now default to 'false'" $showAsCardsParam -}}
Expand All @@ -15,14 +16,18 @@
{{- end -}}
{{- $isFeaturedSection := cond (eq $isFeaturedSectionParam "true") "true" "false" -}}
{{- $class := "card-grid" -}}

{{- /* Get number of cards */ -}}
{{ $cardCount := len (findRE "<div\\s+class=\"card\"[\\s\\S]*?>" .Inner) }}

{{- /* Validate that the parent is card-layout */ -}}
{{ if eq .Parent.Name "card-layout"}}
<div class="card-section {{if eq $isFeaturedSection "true"}}featured-section{{ end }}">
<div class="card-section {{if eq $isFeaturedSection "true"}}featured-section{{ end }}" data-testid="{{if eq $isFeaturedSection "true"}}card-section__featured-section{{else}}card-section{{ end }}">
{{- if $title -}}
<strong class="card-section-title">{{- $title -}}</strong>
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }} {{ end }}">{{- .Inner -}}</div>
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }}{{ end }}" data-testid="{{ if eq $showAsCards "true" }}card-section-content__card-grid{{else}}card-section-content{{ end }}">{{- .Inner -}}</div>
{{ else }}
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }} {{ end }}">{{ .Inner }}</div>
<div class="card-section-content{{ if eq $showAsCards "true" }} {{ $class }}{{ end }}" data-testid="{{ if eq $showAsCards "true" }}card-section-content__card-grid{{else}}card-section-content{{ end }}">{{ .Inner }}</div>
{{ end }}
</div>
{{ else }}
Expand Down
25 changes: 19 additions & 6 deletions layouts/shortcodes/card.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,31 @@
{{- $titleUrl := .Get "titleUrl" | default "/" -}}
{{- $icon := .Get "icon" | default "book-open" -}}
{{- $brandIcon := .Get "brandIcon" -}}
{{- $isFeaturedParam := .Get "isFeatured" | default "false" }}
{{- $isFeaturedParam := .Get "isFeaturedCard" | default "false" }}
{{- $isFullSizeParam := .Get "isFullSize" | default "false" -}}

{{- /* Validate the parameter strictly */ -}}
{{- if not (in (slice "true" "false") $isFeaturedParam) -}}
{{- warnf "The '<card>' Shortcode parameter 'isFeatured' must be 'true' or 'false', but got: '%s'. This will now default to 'false'" $isFeaturedParam -}}
{{- warnf "The '<card>' Shortcode parameter 'isFeaturedCard' must be 'true' or 'false', but got: '%s'. This will now default to 'false'" $isFeaturedParam -}}
{{- end -}}
{{- $isFeatured := cond (eq $isFeaturedParam "true") "true" "false" -}}
{{- $current := .Page.Scratch.Get "cards" | default (slice) -}}
{{- $newCard := dict "title" ($title) "content" (.Inner) -}}
{{- .Page.Scratch.Set "cards" ($current | append $newCard) -}}

{{- if not (in (slice "true" "false") $isFullSizeParam) -}}
{{- warnf "The '<card>' Shortcode parameter 'isFullSize' must be 'true' or 'false', but got: '%s'. This will now default to 'false'" $isFullSizeParam -}}
{{- end -}}
{{- $isFullSize := cond (eq $isFullSizeParam "true") "true" "false" -}}

{{- /* Set up the positioning */ -}}
{{ $dataGrid := "" }}
{{ if or (eq $isFullSize "true") (eq $isFeatured "true") }}
{{ $dataGrid = "wide"}}
{{ else }}
{{ $dataGrid = "halve"}}
{{ end }}

{{- /* Validate that the parent is card-section and under 3 cards */ -}}
{{- if (eq .Parent.Name "card-section") -}}
<div class="card-container {{ if eq $isFeatured "true" }}featured-card{{ end }}">
<div class="card{{ if eq $isFeatured "true" }} featured-card{{ end }}" data-grid="{{ $dataGrid }}" data-testid="{{ if eq $isFeatured "true" }}card__featured-card{{else}}card{{ end }}">
{{- if $title -}}
<div class="card-header">
{{- if $brandIcon -}}
Expand Down
Loading