Refactor timeline to support bookshop component

This commit is contained in:
Mark Dumay
2025-06-04 07:17:33 +02:00
parent 2fb48b51f5
commit 494f203866
21 changed files with 357 additions and 207 deletions

View File

@@ -5,6 +5,8 @@
--bs-primary-dark: #{$primary-bg-subtle-dark};
--bs-primary-bg-subtle: #{$primary-bg-subtle-dark};
--bg-primary-subtle: rgba(var(--bs-primary-rgb), var(--bs-link-opacity, 0.1));
--bs-body: var(--bs-body-bg);
--bs-body-tertiary: var(--bs-tertiary-bg);
.bg-primary-subtle {
background-color: var(--bg-primary-subtle) if($enable-important-utilities, !important, null);

View File

@@ -35,8 +35,10 @@ $warning: h.$warning;
$danger: h.$danger;
$light: h.$light;
$dark: h.$dark;
$white: #fff !default;
$black: #000 !default;
$body-bg: #fff !default;
$gray-100: #f8f9fa !default;
$btn-toggle-color: $black !default;
$carousel-dark-indicator-active-bg: #fff !default;
@@ -52,3 +54,18 @@ $primary-border-subtle-dark: mix(black, h.$primary, calc(h.$dark-mode-sha
$dropdown-transition: opacity .15s ease-in-out !default;
$dropdown-horizontal-margin-top: calc((-1.5 * 1rem) - 2px);
$dropdown-horizontal-padding-y: calc(1rem + 2px);
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark,
"white": $white,
"black": $black,
"body": $body-bg,
"body-tertiary": $gray-100,
);

View File

@@ -24,7 +24,10 @@ strong {
}
// scss-docs-end font
$white: #fff !default;
$black: #000 !default;
$body-bg: #fff !default;
$gray-100: #f8f9fa !default;
$btn-toggle-color: $black !default;
$card-color: var(--bs-body-color);
@@ -46,3 +49,18 @@ $dropdown-transition: opacity .15s ease-in-out !default;
$dropdown-horizontal-margin-top: calc((-1.5 * 1rem) - 2px);
$dropdown-horizontal-padding-y: calc(1rem + 2px);
// scss-docs-end horizontal-nav
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
"success": $success,
"info": $info,
"warning": $warning,
"danger": $danger,
"light": $light,
"dark": $dark,
"white": $white,
"black": $black,
"body": $body-bg,
"body-tertiary": $gray-100,
);

View File

@@ -12,7 +12,15 @@ $semi-circle-border: 0.2rem;
@each $state in map-keys($theme-colors) {
.timeline-#{$state} {
--timeline-highlight: var(--#{$prefix}#{$state});
--timeline-highlight: var(--#{$prefix}#{$state});
}
.timeline-bg-#{$state} {
--timeline-connector-bg: var(--#{$prefix}#{$state});
}
.timeline-bg-#{$state}-subtle {
--timeline-connector-bg: var(--#{$prefix}#{$state}-bg-subtle);
}
}

View File

@@ -3,6 +3,7 @@
@import "modules/bookshop/components/articles/articles";
@import "modules/bookshop/components/faq/faq";
@import "modules/bookshop/components/hero/hero";
@import "modules/bookshop/components/releases/releases";
@import "modules/bookshop/components/separator/separator";
@import "modules/bookshop/components/video-message/video-message";
@import "modules/bookshop/theme";

View File

@@ -0,0 +1,24 @@
# Metadata about this component, to be used in the CMS
spec:
structures:
- content_blocks
label: Releases
description: Release timeline
icon: fingerprint
tags: []
# Defines the structure of this component, as well as the default values
blueprint:
heading:
preheading:
title:
content:
align:
arrangement:
width:
size:
background:
backdrop:
color:
subtle:
data:

View File

@@ -0,0 +1,27 @@
{{/*
Copyright © 2025 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
*/}}
{{/* Initialize arguments */}}
{{ $args := partial "utilities/InitArgs.html" (dict "bookshop" "releases" "args" .) }}
{{ if or $args.err $args.warnmsg }}
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
"partial" "component-library/components/releases/releases.hugo.html"
"msg" " Invalid arguments"
"details" ($args.errmsg | append $args.warnmsg)
"file" page.File
)}}
{{- end -}}
{{/* Main code */}}
{{ if not $args.error }}
{{ partial "assets/timeline.html" (dict
"page" page
"background" $args.background
"heading" $args.heading
"data" $args.data
)
}}
{{- end -}}

View File

@@ -36,7 +36,9 @@
{{ with $background }}
{{/* warnf "bg: '%s'" . */}}
{{ $wrapper = partial "utilities/GetBackgroundStyle.html" (dict "background" . "class" $style) }}
{{ with $background.backdrop }}{{ $wrapper = "" }}{{ $backdrop = . }}{{ end }}
{{ if reflect.IsMap $background }}
{{ with $background.backdrop }}{{ $wrapper = "" }}{{ $backdrop = . }}{{ end }}
{{ end }}
{{ end }}
{{/* warnf "wrapper: '%s'" $wrapper */}}
{{- $theme := index $component_props "theme" -}}

View File

@@ -125,7 +125,9 @@ arguments:
optional: true
comment: Background image with a mask to improve contrast.
background:
type: background
type:
- background
- string
optional: true
comment: Background style of the section.
# badge:
@@ -348,6 +350,12 @@ arguments:
# to the setting `main.externalLinks.cue` in the site's parameters.
# # d
data:
type: string
comment: >-
Path of the input data relative to the site's data folder. Supported data
formats include `JSON`, `TOML`, `YAML`, and `XML`. You can omit the file
extension.
# data:
# type: string
# # default: abbr.yaml

View File

@@ -1,31 +1,11 @@
comment: >-
Shows items ordered on a vertical timelime.
arguments:
page:
group: partial
heading:
group: partial
data:
type: string
optional: false
comment: >-
Filename of the timeline input data. You can omit the file extension. The
file should reside in the data folder.
background:
type: select
optional: true
comment: >-
Border color of the connector dots, defaults to the body background color.
If set, uses a subtle background color that is adaptive to the current
color mode.
options:
values:
- primary
- secondary
- success
- danger
- warning
- info
- light
- dark
class:
type: string
optional: true
comment: >-
Class attribute of the timeline's container.

View File

@@ -122,7 +122,8 @@
# themeFontPath = "https://fonts.googleapis.com/css2?family=Inter:wght@200;300;600&display=swap" # external path
themeFontPath = "/fonts" # local path
themeFontPreload = "/fonts/inter-v12-latin-regular.woff2"
purge = true
# TODO: adjust purge settings
purge = false
# toml-docs-end theme-colors
[schema]

View File

@@ -0,0 +1,34 @@
---
_schema: default
title: Releases
description: Use the releases content block to display a timeline with release information.
icon: fas timeline fa-rotate-90
---
## Overview
The `releases` content block displays a timeline with release information.
<!-- markdownlint-disable MD037 -->
{{< example-bookshop lang="bookshop" >}}
```yml
- _bookshop_name: releases
heading:
preheading: Preheading
title: Heading
content: Content
align: start
width: 8
background:
color: primary
subtle: true
data: timeline
```
{{< /example-bookshop >}}
<!-- markdownlint-enable MD037 -->
## Arguments
The content block supports the following arguments:
{{< args bookshop-releases >}}

View File

@@ -446,7 +446,7 @@ As an example, the following shortcode displays a timeline with the file `data/t
<!-- markdownlint-disable MD037 -->
{{< example lang="hugo" >}}
{{</* timeline data="timeline" background="dark" */>}}
{{</* timeline data="timeline" background="body-tertiary" */>}}
{{< /example >}}
<!-- markdownlint-enable MD037 -->

View File

@@ -394,7 +394,7 @@ H{{</* sub 2 */>}}O est un liquide.
<!-- markdownlint-disable MD037 -->
{{< example lang="hugo" >}}
{{</* timeline data="timeline-fr" background="dark" */>}}
{{</* timeline data="timeline-fr" background="body-tertiary" */>}}
{{< /example >}}
<!-- markdownlint-enable MD037 -->

View File

@@ -7,7 +7,6 @@
url: https://github.com/gethinode/hinode/releases/tag/v0.15.2
content:
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate ducimus officiis quod! Aperiam eveniet nam nostrum odit quasi ullam voluptatum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate ducimus officiis quod! Aperiam eveniet nam nostrum odit quasi ullam voluptatum.
- title: I18N support
icon: fas globe
@@ -32,4 +31,3 @@
# url: v0.1
content:
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate ducimus officiis quod! Aperiam eveniet nam nostrum odit quasi ullam voluptatum.
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate ducimus officiis quod! Aperiam eveniet nam nostrum odit quasi ullam voluptatum.

View File

@@ -93,6 +93,8 @@
"background-img-fluid",
"badge",
"ball",
"bg-bg-body-tertiary",
"bg-bg-primary-subtle",
"bg-body",
"bg-body-tertiary",
"bg-danger",
@@ -249,10 +251,12 @@
"fa-medium",
"fa-moon",
"fa-rocket",
"fa-rotate-90",
"fa-share-nodes",
"fa-sort",
"fa-square-check",
"fa-sun",
"fa-timeline",
"fa-up-right-from-square",
"fa-whatsapp",
"fa-wrapper",
@@ -427,6 +431,7 @@
"py-md-5",
"ratio",
"ratio-16x9",
"releases",
"rounded",
"rounded-2",
"rounded-5",
@@ -491,7 +496,10 @@
"text-uppercase",
"tickmark",
"timeline",
"timeline-bg-dark",
"timeline-bg-bg-body-tertiary",
"timeline-bg-bg-primary-subtle",
"timeline-bg-body-tertiary",
"timeline-bg-primary-subtle",
"timeline-connector-end",
"timeline-connector-start",
"timeline-description-text-end",
@@ -533,9 +541,6 @@
"w-50"
],
"ids": [
"0-0",
"0-1",
"0-2",
"abbr",
"accordion",
"accordion-0",
@@ -551,7 +556,6 @@
"animatie",
"animation",
"arguments",
"background-type",
"badge",
"barre-de-navigation",
"block-diagram",
@@ -597,76 +601,11 @@
"fab-medium",
"fab-whatsapp",
"fab-x-twitter",
"faq-03a78c57000541cd865f2bfc1b11a6a7",
"faq-03a78c57000541cd865f2bfc1b11a6a7-heading-faq-03a78c57000541cd865f2bfc1b11a6a7",
"faq-03a78c57000541cd865f2bfc1b11a6a7-item-0",
"faq-03a78c57000541cd865f2bfc1b11a6a7-item-1",
"faq-03a78c57000541cd865f2bfc1b11a6a7-item-2",
"faq-0d4697377645d34ad522dbe7359ccc21",
"faq-0d4697377645d34ad522dbe7359ccc21-heading-faq-0d4697377645d34ad522dbe7359ccc21",
"faq-0d4697377645d34ad522dbe7359ccc21-item-0",
"faq-0d4697377645d34ad522dbe7359ccc21-item-1",
"faq-0d4697377645d34ad522dbe7359ccc21-item-2",
"faq-2b10fb70406b13be422dc94aaa43f2c5",
"faq-2b10fb70406b13be422dc94aaa43f2c5-heading-faq-2b10fb70406b13be422dc94aaa43f2c5",
"faq-2b10fb70406b13be422dc94aaa43f2c5-item-0",
"faq-2b10fb70406b13be422dc94aaa43f2c5-item-1",
"faq-2b10fb70406b13be422dc94aaa43f2c5-item-2",
"faq-2e2e60387f883a9fa433384b93350884",
"faq-2e2e60387f883a9fa433384b93350884-heading-faq-2e2e60387f883a9fa433384b93350884",
"faq-2e2e60387f883a9fa433384b93350884-item-0",
"faq-2e2e60387f883a9fa433384b93350884-item-1",
"faq-2e2e60387f883a9fa433384b93350884-item-2",
"faq-5e3abaab0ade75deb100d8efcc9d83c3",
"faq-5e3abaab0ade75deb100d8efcc9d83c3-heading-faq-5e3abaab0ade75deb100d8efcc9d83c3",
"faq-5e3abaab0ade75deb100d8efcc9d83c3-item-0",
"faq-5e3abaab0ade75deb100d8efcc9d83c3-item-1",
"faq-5e3abaab0ade75deb100d8efcc9d83c3-item-2",
"faq-786252d796f76ca27e57ed92fb675e78",
"faq-786252d796f76ca27e57ed92fb675e78-heading-faq-786252d796f76ca27e57ed92fb675e78",
"faq-786252d796f76ca27e57ed92fb675e78-item-0",
"faq-786252d796f76ca27e57ed92fb675e78-item-1",
"faq-786252d796f76ca27e57ed92fb675e78-item-2",
"faq-854c525fd2c2c0142033a257a4319c4d",
"faq-854c525fd2c2c0142033a257a4319c4d-heading-faq-854c525fd2c2c0142033a257a4319c4d",
"faq-854c525fd2c2c0142033a257a4319c4d-item-0",
"faq-854c525fd2c2c0142033a257a4319c4d-item-1",
"faq-854c525fd2c2c0142033a257a4319c4d-item-2",
"faq-8ab4bdc86e22e0fc110078f7fa3819e6",
"faq-8ab4bdc86e22e0fc110078f7fa3819e6-heading-faq-8ab4bdc86e22e0fc110078f7fa3819e6",
"faq-8ab4bdc86e22e0fc110078f7fa3819e6-item-0",
"faq-8ab4bdc86e22e0fc110078f7fa3819e6-item-1",
"faq-8ab4bdc86e22e0fc110078f7fa3819e6-item-2",
"faq-8e2fa9bdb8db14286118c9982ba08b12",
"faq-8e2fa9bdb8db14286118c9982ba08b12-heading-faq-8e2fa9bdb8db14286118c9982ba08b12",
"faq-8e2fa9bdb8db14286118c9982ba08b12-item-0",
"faq-8e2fa9bdb8db14286118c9982ba08b12-item-1",
"faq-8e2fa9bdb8db14286118c9982ba08b12-item-2",
"faq-a22c07a294b0977d95067662cf5d61cf",
"faq-a22c07a294b0977d95067662cf5d61cf-heading-faq-a22c07a294b0977d95067662cf5d61cf",
"faq-a22c07a294b0977d95067662cf5d61cf-item-0",
"faq-a22c07a294b0977d95067662cf5d61cf-item-1",
"faq-a22c07a294b0977d95067662cf5d61cf-item-2",
"faq-ac36629ab178e542fbfac94a7a8c30b9",
"faq-ac36629ab178e542fbfac94a7a8c30b9-heading-faq-ac36629ab178e542fbfac94a7a8c30b9",
"faq-ac36629ab178e542fbfac94a7a8c30b9-item-0",
"faq-ac36629ab178e542fbfac94a7a8c30b9-item-1",
"faq-ac36629ab178e542fbfac94a7a8c30b9-item-2",
"faq-d0b044c32fcfec92a27caa084c061130",
"faq-d0b044c32fcfec92a27caa084c061130-heading-faq-d0b044c32fcfec92a27caa084c061130",
"faq-d0b044c32fcfec92a27caa084c061130-item-0",
"faq-d0b044c32fcfec92a27caa084c061130-item-1",
"faq-d0b044c32fcfec92a27caa084c061130-item-2",
"faq-d3edc229f1cec11149e81b8dc3fc0d19",
"faq-d3edc229f1cec11149e81b8dc3fc0d19-heading-faq-d3edc229f1cec11149e81b8dc3fc0d19",
"faq-d3edc229f1cec11149e81b8dc3fc0d19-item-0",
"faq-d3edc229f1cec11149e81b8dc3fc0d19-item-1",
"faq-d3edc229f1cec11149e81b8dc3fc0d19-item-2",
"faq-e9ea998a940c51f7509b7c9e01551ace",
"faq-e9ea998a940c51f7509b7c9e01551ace-heading-faq-e9ea998a940c51f7509b7c9e01551ace",
"faq-e9ea998a940c51f7509b7c9e01551ace-item-0",
"faq-e9ea998a940c51f7509b7c9e01551ace-item-1",
"faq-e9ea998a940c51f7509b7c9e01551ace-item-2",
"faq-f7a89358f6722c10536737dcec601534",
"faq-f7a89358f6722c10536737dcec601534-heading-faq-f7a89358f6722c10536737dcec601534",
"faq-f7a89358f6722c10536737dcec601534-item-0",
"faq-f7a89358f6722c10536737dcec601534-item-1",
"faq-f7a89358f6722c10536737dcec601534-item-2",
"fas-1",
"fas-2",
"fas-3",
@@ -692,6 +631,7 @@
"fas-share-nodes",
"fas-sort",
"fas-sun",
"fas-timeline",
"fas-up-right-from-square",
"fichier",
"fil-dariane",

View File

@@ -0,0 +1,147 @@
{{/*
Copyright © 2022 - 2025 The Hinode Team / Mark Dumay. All rights reserved.
Use of this source code is governed by The MIT License (MIT) that can be found in the LICENSE file.
Visit gethinode.com/license for more details.
Inspired by the timeline snippet from Siddharth Panchal at https://bootsnipp.com/snippets/Q0ppE
*/}}
{{ $error := false }}
{{/* Initialize arguments */}}
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "timeline" "args" . "group" "partial" )}}
{{ if or $args.err $args.warnmsg }}
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
"partial" "assets/timeline.html"
"msg" "Invalid arguments"
"details" ($args.errmsg | append $args.warnmsg)
"file" page.File
)}}
{{ $error = $args.err }}
{{ end }}
{{/* Initialize global variables */}}
{{ $arrangement := site.Params.modules.bookshop.title.arrangement }}
{{/* Initialize local arguments */}}
{{- $page := $args.page -}}
{{- $data := partial "utilities/GetI18nData.html" (dict "page" $page "data" $args.data) }}
{{ if not $data -}}
{{ errorf "Invalid timeline data '%s': %s" $page.File -}}
{{ $error = true }}
{{ end -}}
{{ $background := partial "utilities/GetBackgroundStyle.html" (dict "background" $args.background) }}
{{/* Inline partial to render icon */}}
{{- define "_partials/inline/timeline-icon.html" -}}
{{- $col := default 6 .col -}}
{{- $icon := .icon -}}
{{- $direction := .direction -}}
<div class="col-{{ $col }} d-flex justify-content-{{ $direction }} align-items-center">
<div class="d-flex">
<div class="d-flex timeline-semi-circle-{{ $direction }} fa-wrapper align-items-center justify-content-center">
{{ partial "assets/icon.html" (dict "icon" (printf "%s fa-fluid" $icon) "spacing" false) }}
</div>
<div class="timeline-connector-{{ $direction }} {{ if eq $direction "start" }} order-first{{ end }}"></div>
</div>
</div>
{{- end -}}
{{/* Inline partial to render icon */}}
{{- define "_partials/inline/timeline-panel.html" -}}
{{- $col := default 6 .col -}}
{{- $page := .page -}}
{{- $content := .content -}}
{{- $color := .color -}}
{{- $title := .title -}}
{{- $badge := .badge -}}
{{- $url := .url -}}
{{- $date := .date -}}
{{- if and $url (not (hasPrefix $url "http")) -}}
{{- $url = partial "utilities/URLJoin.html" (dict "base" site.Params.docs.release "path" $url) }}
{{- end -}}
{{- $direction := .direction -}}
<div class="col-{{ $col }} d-flex align-items-center">
<div class="d-flex h-100 w-100">
<div class="timeline-panel-{{ $direction }}"></div>
<div class="timeline-description-text-{{ $direction }} p-3 w-100">
<div>
{{ with $url }}
<a class="fs-5 fw-bold text-uppercase link-{{ $color }} text-break align-middle" href="{{ . }}">{{ $title }}</a>
<span class="badge rounded-pill text-bg-{{ $color }} ms-1">{{ if $badge }}<a class="link-bg-{{ $color }}" href="{{ . }}">{{ $badge }}</a>{{ end }}</span>
{{ else}}
<span class="fs-5 fw-bold text-uppercase text-{{ $color }} text-break align-middle">{{ $title }}</span>
<span class="badge rounded-pill text-bg-{{ $color }} ms-1">{{ if $badge }}{{ $badge }}{{ end }}</span>
{{ end }}
</div>
{{ if $date }}
{{ $datestr := (partial "utilities/date.html" (dict "date" $date "format" "long")) -}}
<p class="mb-0"><small class="text-body-secondary text-uppercase">{{ $datestr -}}</small></p>
{{ end }}
<p class="mt-3 mb-0">{{ $content | $page.RenderString }}</p>
</div>
</div>
</div>
{{- end -}}
{{/* Main code */}}
{{ $title := "" }}
{{ if $args.heading }}
{{ $title = partial "assets/section-title.html" (dict
"heading" $args.heading
"use-title" $args.useTitle
"size" $args.size
"links" $args.links
"type" (or $args.linkType $args.type)
"class" "pb-4"
"arrangement" $arrangement
) }}
{{ end }}
{{/* Render default timeline */}}
<div class="container p-0 d-none d-md-block mb-5 {{ with $background }} timeline-{{ . }} {{ . }}{{ end }}{{ with $args.class }} {{ . }}{{ end }}">
{{ $title | safeHTML }}
{{ range $index, $item := $data }}
<div class="row timeline timeline-{{ $item.color }} timeline-dot g-0 ">
{{- $params := dict
"page" $args.page
"content" $item.content
"color" $item.color
"title" $item.title
"badge" $item.badge
"date" $item.date
"url" $item.url
}}
{{ if eq (mod $index 2) 1 }}
{{ partial "inline/timeline-panel.html" (merge $params (dict "direction" "start")) }}
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "start") }}
{{ else }}
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "end") }}
{{ partial "inline/timeline-panel.html" (merge $params (dict "direction" "end")) }}
{{ end }}
</div>
<div class="row timeline g-0 p-3"> </div>
{{ end }}
</div>
{{/* Render timeline for smaller devices */}}
<div class="container p-0 d-block d-md-none small{{ with $background }} timeline-bg-{{ . }} bg-{{ . }}{{ end }}{{ with $args.class }} {{ . }}{{ end }}">
{{ range $index, $item := $data }}
<div class="row timeline-sm timeline-{{ $item.color }} timeline-dot g-0">
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "end" "col" 3) }}
{{ partial "inline/timeline-panel.html" (dict
"page" $args.page
"content" $item.content
"color" $item.color
"title" $item.title
"badge" $item.badge
"date" $item.date
"url" $item.url
"direction" "end"
"col" 9
) }}
</div>
<div class="row timeline-sm g-0 p-3"> </div>
{{ end }}
</div>

View File

@@ -3,7 +3,7 @@
-->
{{/* Initialize arguments */}}
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "background" "args" .)}}
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "background" "args" .) }}
{{ if or $args.err $args.warnmsg }}
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
"partial" "utilities/GetBackgroundStyle.html"
@@ -15,11 +15,20 @@
{{ $style := $args.class }}
{{ if and (not $args.err) $args.background }}
{{ if and $args.background.subtle (not (hasPrefix $args.background.color "body")) }}
{{- $style = printf "%s bg-%s-subtle" $style $args.background.color -}}
{{ else if $args.background.color}}
{{- $style = printf "%s bg-%s" $style $args.background.color -}}
{{ $background := "" }}
{{ $subtle := false }}
{{ if reflect.IsMap $args.background }}
{{ $background = $args.background.color }}
{{ $subtle = $args.background.subtle }}
{{ else }}
{{ $background = $args.background }}
{{ end }}
{{ if and $subtle (not (hasPrefix $background "body")) }}
{{- $style = printf "%s bg-%s-subtle" (or $style "") $background -}}
{{ else if $background }}
{{- $style = printf "%s bg-%s" (or $style "") $background -}}
{{ end }}
{{ end }}
{{ return $style }}
{{ return (trim $style " ") }}

View File

@@ -6,11 +6,17 @@
{{ $error := false }}
{{/* Validate arguments */}}
{{ if partial "utilities/IsInvalidArgs.html" (dict "structure" "image" "child" "nav-item" "args" .Params "group" "shortcode") }}
{{ errorf "Invalid arguments: %s" .Position -}}
{{ $error = true }}
{{ end }}
{{/* Initialize arguments */}}
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "image" "child" "nav-item" "args" .Params "group" "shortcode" "named" .IsNamedParams) }}
{{ if or $args.err $args.warnmsg }}
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
"partial" "shortcodes/image.html"
"msg" "Invalid arguments"
"details" ($args.errmsg | append $args.warnmsg)
"file" page.File
"position" .Position
)}}
{{- end -}}
{{/* Initialize arguments */}}
{{- $url := "" -}}

View File

@@ -8,100 +8,28 @@
{{ $error := false }}
{{/* Validate arguments */}}
{{ if partial "utilities/IsInvalidArgs.html" (dict "structure" "timeline" "args" .Params) }}
{{ errorf "Invalid arguments: %s" .Position -}}
{{/* Initialize arguments */}}
{{ $args := partial "utilities/InitArgs.html" (dict "structure" "timeline" "args" .Params "named" .IsNamedParams "group" "shortcode") }}
{{ if or $args.err $args.warnmsg }}
{{ partial (cond $args.err "utilities/LogErr.html" "utilities/LogWarn.html") (dict
"partial" "shortcodes/timeline.html"
"msg" "Invalid arguments"
"details" ($args.errmsg | append $args.warnmsg)
"file" page.File
"position" .Position
)}}
{{ $error = true }}
{{ end }}
{{/* Initialize arguments */}}
{{/* Initialize local arguments */}}
{{- $page := .Page -}}
{{- $data := partial "utilities/GetI18nData.html" (dict "page" $page "data" (.Get "data"))}}
{{- $data := partial "utilities/GetI18nData.html" (dict "page" $page "data" $args.data) }}
{{ if not $data -}}
{{ errorf "Invalid timeline data '%s': %s" .Get "data" .Position -}}
{{ errorf "Invalid timeline data '%s': %s" $args.data .Position -}}
{{ $error = true }}
{{ end -}}
{{ $background := .Get "background" | default "" -}}
{{- $class := .Get "class" | default "" -}}
{{/* Inline partial to render icon */}}
{{- define "_partials/inline/timeline-icon.html" -}}
{{- $col := default 6 .col -}}
{{- $icon := .icon -}}
{{- $direction := .direction -}}
<div class="col-{{ $col }} d-flex justify-content-{{ $direction }} align-items-center">
<div class="d-flex">
<div class="d-flex timeline-semi-circle-{{ $direction }} fa-wrapper align-items-center justify-content-center">
{{ partial "assets/icon.html" (dict "icon" (printf "%s fa-fluid" $icon) "spacing" false) }}
</div>
<div class="timeline-connector-{{ $direction }} {{ if eq $direction "start" }} order-first{{ end }}"></div>
</div>
</div>
{{- end -}}
{{/* Inline partial to render icon */}}
{{- define "_partials/inline/timeline-panel.html" -}}
{{- $col := default 6 .col -}}
{{- $page := .page -}}
{{- $content := .content -}}
{{- $color := .color -}}
{{- $title := .title -}}
{{- $badge := .badge -}}
{{- $url := .url -}}
{{- $date := .date -}}
{{- if and $url (not (hasPrefix $url "http")) -}}
{{- $url = partial "utilities/URLJoin.html" (dict "base" site.Params.docs.release "path" $url) }}
{{- end -}}
{{- $direction := .direction -}}
<div class="col-{{ $col }} d-flex align-items-center">
<div class="d-flex h-100 w-100">
<div class="timeline-panel-{{ $direction }}"></div>
<div class="timeline-description-text-{{ $direction }} p-3 w-100">
<div>
{{ with $url }}
<a class="fs-5 fw-bold text-uppercase link-{{ $color }} text-break align-middle" href="{{ . }}">{{ $title }}</a>
<span class="badge rounded-pill text-bg-{{ $color }} ms-1">{{ if $badge }}<a class="link-bg-{{ $color }}" href="{{ . }}">{{ $badge }}</a>{{ end }}</span>
{{ else}}
<span class="fs-5 fw-bold text-uppercase text-{{ $color }} text-break align-middle">{{ $title }}</span>
<span class="badge rounded-pill text-bg-{{ $color }} ms-1">{{ if $badge }}{{ $badge }}{{ end }}</span>
{{ end }}
</div>
{{ if $date }}
{{ $datestr := (partial "utilities/date.html" (dict "date" $date "format" "long")) -}}
<p class="mb-0"><small class="text-body-secondary text-uppercase">{{ $datestr -}}</small></p>
{{ end }}
<p class="mt-3 mb-0">{{ $content | $page.RenderString }}</p>
</div>
</div>
</div>
{{- end -}}
{{/* Main code */}}
{{/* Render default timeline */}}
<div class="container p-0 d-none d-md-block mb-5 {{ with $background }} timeline-bg-{{ . }}{{ end }}{{ with $class }} {{ . }}{{ end }}">
{{ range $index, $item := $data }}
<div class="row timeline timeline-{{ $item.color }} timeline-dot g-0 ">
{{ if eq (mod $index 2) 1 }}
{{ partial "inline/timeline-panel.html" (dict "page" $page "content" $item.content "color" $item.color "title" $item.title "badge" $item.badge "date" $item.date "url" $item.url "direction" "start") }}
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "start") }}
{{ else }}
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "end") }}
{{ partial "inline/timeline-panel.html" (dict "page" $page "content" $item.content "color" $item.color "title" $item.title "badge" $item.badge "date" $item.date "url" $item.url "direction" "end") }}
{{ end }}
</div>
<div class="row timeline g-0 p-3"> </div>
{{ end }}
</div>
{{/* Render timeline for smaller devices */}}
<div class="container p-0 d-block d-md-none small{{ with $background }} timeline-bg-{{ . }}{{ end }}{{ with $class }} {{ . }}{{ end }}">
{{ range $index, $item := $data }}
<div class="row timeline-sm timeline-{{ $item.color }} timeline-dot g-0">
{{ partial "inline/timeline-icon.html" (dict "icon" $item.icon "direction" "end" "col" 3) }}
{{ partial "inline/timeline-panel.html" (dict "page" $page "content" $item.content "color" $item.color "title" $item.title "badge" $item.badge "date" $item.date "url" $item.url "direction" "end" "col" 9) }}
</div>
<div class="row timeline-sm g-0 p-3"> </div>
{{ end }}
</div>
{{ if not $error }}
{{ partial "assets/timeline.html" (dict "page" $page "data" $args.data "background" $args.background) }}
{{ end }}