diff --git a/content/_index.md b/content/_index.md index 13fef045eb41..fa5a3ed70d97 100644 --- a/content/_index.md +++ b/content/_index.md @@ -10,6 +10,10 @@ sections: layout: split cta_secondary_text: Download open source cta_secondary_link: /docs/install/ + cta_card_label: For humans + cta_agent_label: For agents + cta_agent_prompt: Fetch https://www.pulumi.com/onboard.md and follow its instructions to get me started with Pulumi. + cta_agent_prompt_label: Copy prompt badge_highlight_text: "Latest release:" badge_text: "Full support for Terraform and HCL" badge_link: /releases/terraform-state-backend-modules-hcl/ diff --git a/layouts/partials/hero-ctas.html b/layouts/partials/hero-ctas.html new file mode 100644 index 000000000000..387d23d34f68 --- /dev/null +++ b/layouts/partials/hero-ctas.html @@ -0,0 +1,70 @@ +{{/* + Hero CTA row — shared by the split and centered branches of template-hero. + + By default this renders the primary/secondary/tertiary buttons in a plain + flex row, exactly as before. Setting cta_card_label groups them into a + bordered card whose label straddles the top border, and setting + cta_agent_prompt adds a second card beside it holding a single + copy-to-clipboard button for coding agents. + + Params: + - cta_primary_text / cta_primary_link + - cta_secondary_text / cta_secondary_link + - cta_tertiary_text / cta_tertiary_link + - cta_card_label: Optional. Label for the card wrapping the buttons (e.g. "For humans"). + - cta_agent_label: Optional. Label for the agent card. Defaults to "For agents". + - cta_agent_prompt: Optional. Text the agent card's button copies to the clipboard. + - cta_agent_prompt_label: Optional short text shown on that button in place of the + full prompt. The prompt itself is still what gets copied, and still what the + tooltip shows. Defaults to the prompt. + - layout: "split" (buttons go inline at sm) or "centered" (at lg). + + Class strings below are written out in full rather than composed from + fragments so Tailwind's source scanner still sees every utility. +*/}} + +{{ $split := eq (.layout | default "centered") "split" }} +{{ $rowClass := cond $split "flex flex-col sm:flex-row flex-wrap items-start gap-4 w-full" "flex flex-col lg:flex-row flex-wrap items-center justify-center gap-4 w-full" }} +{{ $btnClass := cond $split "w-full sm:w-auto" "w-full lg:w-auto" }} +{{ $cardLabel := .cta_card_label }} +{{ $agentLabel := .cta_agent_label | default "For agents" }} +{{ $agentPrompt := .cta_agent_prompt }} +{{ $agentPromptLabel := .cta_agent_prompt_label | default $agentPrompt }} + +{{ if or .cta_primary_text .cta_secondary_text .cta_tertiary_text }} +
+
+ {{ with $cardLabel }} + {{ . }} + {{ end }} +
+ {{ with .cta_primary_text }} + + {{ . }} + {{ partial "icon.html" (dict "name" "arrow-right" "weight" "bold" "class" "size-4") }} + + {{ end }} + {{ with .cta_secondary_text }} + {{ . }} + {{ end }} + {{ with .cta_tertiary_text }} + {{ . }} + {{ end }} +
+
+ {{ with $agentPrompt }} +
+ {{ $agentLabel }} + + + {{ . }} + +
+ {{ end }} +
+{{ end }} diff --git a/layouts/partials/template-partials/template-hero.html b/layouts/partials/template-partials/template-hero.html index 350c667ed647..083bb2938bb4 100644 --- a/layouts/partials/template-partials/template-hero.html +++ b/layouts/partials/template-partials/template-hero.html @@ -48,6 +48,12 @@ - cta_tertiary_text: Optional tertiary CTA button text. - cta_tertiary_link: Optional tertiary CTA button link. + Parameters — CTA cards (see partials/hero-ctas.html): + - cta_card_label: Optional. Groups the buttons above into a bordered card labeled with this text. + - cta_agent_prompt: Optional. Adds a second card holding a button that copies this text to the clipboard. + - cta_agent_prompt_label: Optional short text shown on that button instead of the full prompt. + - cta_agent_label: Optional label for that second card. Defaults to "For agents". + Right-slot precedence: code_snippets > video_youtube_id > image. */}} @@ -62,6 +68,10 @@ {{ $ctaSecondaryLink := .cta_secondary_link | default site.Params.cta.secondary.href }} {{ $ctaTertiaryText := .cta_tertiary_text }} {{ $ctaTertiaryLink := .cta_tertiary_link }} +{{ $ctaCardLabel := .cta_card_label }} +{{ $ctaAgentLabel := .cta_agent_label }} +{{ $ctaAgentPrompt := .cta_agent_prompt }} +{{ $ctaAgentPromptLabel := .cta_agent_prompt_label }} {{ $videoYouTubeId := .video_youtube_id }} {{ $videoTitle := .video_title | default "Watch video" }} {{ $image := .image }} @@ -102,7 +112,13 @@ {{ if eq $layout "split" }}
-
+ {{/* w-full below xl: without it the column is content-sized, so a wide + nowrap child (e.g. the agent prompt) widens it past the viewport. + min-w-0 at xl: the columns' percentage bases plus the gap overflow the + line, so both shrink — and without this the column's min-content size + props it back up, making its width depend on its text. That reflows + the whole row whenever child text changes. */}} +
{{ if or $badgeText $badgeHighlightText }} {{ $badgeHighlightText }} @@ -146,25 +162,16 @@

{{ if $description }}

{{ $description | markdownify }}

{{ end }} - {{ if or $ctaPrimaryText $ctaSecondaryText $ctaTertiaryText }} -
- {{ end }} + {{ partial "hero-ctas.html" (dict + "layout" "split" + "cta_primary_text" $ctaPrimaryText "cta_primary_link" $ctaPrimaryLink + "cta_secondary_text" $ctaSecondaryText "cta_secondary_link" $ctaSecondaryLink + "cta_tertiary_text" $ctaTertiaryText "cta_tertiary_link" $ctaTertiaryLink + "cta_card_label" $ctaCardLabel "cta_agent_label" $ctaAgentLabel "cta_agent_prompt" $ctaAgentPrompt + "cta_agent_prompt_label" $ctaAgentPromptLabel) }}

{{ if $codeSnippets }} -
+
{{ if or $codeAspectRatio $overlayImage }}
@@ -232,22 +239,13 @@

{{ if $description }}

{{ $description | markdownify }}

{{ end }} - {{ if or $ctaPrimaryText $ctaSecondaryText $ctaTertiaryText }} -
- {{ if $ctaPrimaryText }} - - {{ $ctaPrimaryText }} - {{ partial "icon.html" (dict "name" "arrow-right" "weight" "bold" "class" "size-4") }} - - {{ end }} - {{ if $ctaSecondaryText }} - {{ $ctaSecondaryText }} - {{ end }} - {{ if $ctaTertiaryText }} - {{ $ctaTertiaryText }} - {{ end }} -
- {{ end }} + {{ partial "hero-ctas.html" (dict + "layout" "centered" + "cta_primary_text" $ctaPrimaryText "cta_primary_link" $ctaPrimaryLink + "cta_secondary_text" $ctaSecondaryText "cta_secondary_link" $ctaSecondaryLink + "cta_tertiary_text" $ctaTertiaryText "cta_tertiary_link" $ctaTertiaryLink + "cta_card_label" $ctaCardLabel "cta_agent_label" $ctaAgentLabel "cta_agent_prompt" $ctaAgentPrompt + "cta_agent_prompt_label" $ctaAgentPromptLabel) }}

{{ if $codeSnippets }}
diff --git a/theme/src/scss/_templates.scss b/theme/src/scss/_templates.scss index d8f23612c3ad..9ed59df5094d 100644 --- a/theme/src/scss/_templates.scss +++ b/theme/src/scss/_templates.scss @@ -123,7 +123,7 @@ } .product-hero-title-secondary { - @apply block text-black; + @apply block text-black max-w-lg; } .product-hero-title { @@ -138,6 +138,86 @@ .product-hero-visual { @apply w-full; } + + // CTA row (partials/hero-ctas.html). Plain full-width wrapper by default; + // --split sets the "for humans" and "for agents" cards side by side above + // mobile. The humans card keeps its natural width so its buttons never wrap; + // the agents card takes whatever is left and truncates its prompt into it. + .hero-ctas { + @apply w-full; + + &--split { + @apply flex flex-col gap-4; + + // sm → md: the cards have stacked but the buttons are already in a + // row, so the humans card spans the full width while its buttons hug + // their text. Stretch them to fill it. Below sm they are w-full + // already; from md the card is shrink-0 and sized to them. + @media (min-width: 640px) and (max-width: 767.98px) { + > .hero-cta-group:first-child .btn { + @apply flex-1; + } + } + + @include screen-md { + @apply flex-row items-stretch; + + > .hero-cta-group:first-child { + @apply shrink-0; + } + + // The agents card hugs its button too, rather than growing into + // the leftover space — the button holds a short label now. + > .hero-cta-group:last-child { + @apply shrink-0; + } + } + } + } + + // Bordered card with its label straddling the top border. The label's own + // white background is what breaks the border line on either side of it, so + // this only reads correctly on a white section background. + .hero-cta-card { + @apply relative rounded-lg border border-violet-300 p-3; + } + + .hero-cta-card-label { + @apply font-overline-sm absolute -top-2 left-4 px-2 bg-white text-violet-primary; + } + + // The agent prompt button: copy icon plus a short label. The prompt itself + // lives in the tooltip and the clipboard, not here. + // + // The min-width holds the button steady when the label swaps to the copied + // state, which is otherwise narrower; sized just past the wider of the two + // (10.25rem) so neither reflows. Revisit it if either label changes. + .hero-cta-copy { + @apply w-full min-w-[10.5rem]; + } + + // pulumi-tooltip is inline by default; the trigger here is a full-width + // button, so stretch both to the card. The bubble holds the whole prompt, so + // it gets a fixed width wider than both the button and the component's own + // w-48 default, and wraps rather than truncating. + .hero-cta-copy-tooltip { + @apply block w-full; + + .tooltip-target { + @apply block w-full; + } + + .tooltip-content { + @apply w-72 text-left break-words font-mono; + } + } + + // Safety net for a long cta_agent_prompt_label: min-w-0 lets the span shrink + // below its max-content width so the ellipsis renders rather than the text + // being flatly clipped by the button. + .hero-cta-copy-text { + @apply truncate min-w-0; + } } .template-logo-banner {