diff --git a/content/about/_index.md b/content/about/_index.md index a719bdf9fa83..50050f230bc8 100644 --- a/content/about/_index.md +++ b/content/about/_index.md @@ -18,9 +18,7 @@ sections: anchor: community - label: History anchor: history - - label: Awards - anchor: awards - - label: Press & News + - label: Newsroom anchor: newsroom - label: Join us anchor: join-us diff --git a/content/about/newsroom.md b/content/about/newsroom.md index 868c67449e27..7a4eacf14bb7 100644 --- a/content/about/newsroom.md +++ b/content/about/newsroom.md @@ -1,6 +1,9 @@ --- -title: Press and News -meta_desc: Browse Pulumi's recent news and press releases here. +title: Newsroom +meta_desc: Browse Pulumi's recent press releases, news coverage, and industry awards. type: page layout: newsroom +aliases: +- /awards/ +- /awards --- diff --git a/content/awards/_index.md b/content/awards/_index.md deleted file mode 100644 index f0c09b423cd3..000000000000 --- a/content/awards/_index.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: Awards and Recognitions -meta_desc: Read about the awards and recognitions Pulumi has received from various organizations in the software industry. -type: page -layout: awards ---- diff --git a/data/awards.toml b/data/awards.toml index 31705fc65602..1466dc564a94 100644 --- a/data/awards.toml +++ b/data/awards.toml @@ -1,144 +1,169 @@ [[awards]] title = "Technology Fast 500, 2024" featured = true +date = "13th November 2024" img = "/logos/press/awards/fast-500-2024.png" url = "https://www2.deloitte.com/us/en/pages/technology-media-and-telecommunications/articles/fast500-winners.html" [[awards]] title = "Coolest Cloud Computing Startup Companies of 2024" featured = true +date = "20th November 2024" img = "/logos/press/crn.png" url = "https://www.crn.com/news/cloud/2024/the-10-coolest-cloud-computing-startup-companies-of-2024" [[awards]] title = "Intellyx Digital Innovator Award, 2024" featured = true +date = "28th May 2024" img = "/logos/press/awards/intellyx-2024.png" url = "https://intellyx.com/2024/05/28/2024-intellyx-digital-innovator-award-winners-announced/" [[awards]] title = "Impower.AI Top Tech Tool" featured = true +date = "29th December 2023" img = "/logos/press/awards/impower-ai.png" url = "https://www.impowerconsulting.ai/insight/top-12-tech-tools-of-the-year-our-essential-picks-for-2024" [[awards]] title = "Futuriom 50, 2024" featured = true +date = "1st January 2024" img = "/logos/press/awards/futuriom-50-2024.png" url = "https://www.futuriom.com/articles/news/the-2024-futuriom-50-is-here/2024/01" [[awards]] title = "Fastest-Growing Companies in America" featured = true +date = "15th August 2023" img = "/logos/press/awards/inc-5000.png" url = "https://www.inc.com/inc5000/2023" [[awards]] title = "Redpoint InfraRed 100, 2023" featured = true +date = "19th January 2023" img = "/logos/press/awards/infrared-100.png" url = "https://www.redpoint.com/infrared/100/" [[awards]] title = "Top Open Source Startups, 2023" featured = true +date = "1st December 2023" img = "/logos/press/awards/traxcn-logo.png" [[awards]] title = "Best Innovation in Coding Tools, 2022" featured = true +date = "7th April 2022" img = "/logos/press/awards/devies-2022.png" [[awards]] title = "Top Open Source Tech Startups 2021" featured = false +date = "1st December 2021" img = "/logos/press/awards/tracxn-emerging-startups.png" [[awards]] title = "Coolest Open-Source Tools Of 2021" featured = false +date = "2nd July 2021" img = "/logos/press/crn.png" url = "https://www.crn.com/slide-shows/applications-os/the-10-coolest-open-source-software-tools-of-2021-so-far-/8" [[awards]] title = "21 Companies to Watch in 2021" featured = false +date = "22nd April 2021" img = "/logos/press/awards/builtin-seattle.png" url = "https://www.builtinseattle.com/2021/04/22/21-seattle-companies-to-watch-2021" [[awards]] title = "Startups to Watch in 2021" featured = false +date = "22nd December 2020" img = "/logos/press/businessinsider.png" url = "https://www.businessinsider.com/vcs-name-the-startups-that-will-boom-in-2021-2020-12" [[awards]] title = "EMA Best of 2020" featured = false +date = "23rd December 2020" img = "/logos/press/awards/ema.png" url = "https://torstenvolk.medium.com/ema-best-of-2020-top-3-acquisitions-vc-rounds-and-open-source-projects-34fa7a8d29fe" [[awards]] title = "Top 20 Edge Cloud Companies" featured = false +date = "1st July 2021" img = "/logos/press/ngpcap.png" url = "https://web.archive.org/web/20210731161324/https://www.ngpcap.com/news/edge-cloud-a-gold-lining-on-the-horizon-1" [[awards]] title = "10 Hottest Kubernetes Startups Of 2020" featured = false +date = "15th December 2020" img = "/logos/press/crn.png" url = "https://www.crn.com/slide-shows/cloud/the-10-hottest-kubernetes-startups-of-2020/7" [[awards]] title = "Gartner Cool Vendor 2020" featured = true +date = "28th May 2020" img = "/logos/press/awards/gartner-cool-vendor.png" [[awards]] title = "IDC Innovator 2020" featured = true +date = "28th May 2020" img = "/logos/press/awards/idc-innovator.png" url = "https://info.pulumi.com/press-release/gartner-cool-vendor-5_28_2020?_gl=1*vmx058*_ga*MTMwODkyMzA0MS4xNjgxNTgwNjkx*_ga_FQHG5CVY2D*MTY4Mjk1OTczMy4xNS4wLjE2ODI5NTk3MzMuNjAuMC4w" [[awards]] title = "Top Startups of 2019" featured = true +date = "22nd December 2019" img = "/logos/press/businessinsider.png" url = "https://www.businessinsider.com/18-hottest-enterprise-startups-from-seattles-booming-tech-scene-2019-12" [[awards]] title = "Company of the Year, Computer Software" featured = true +date = "14th June 2019" img = "/logos/press/awards/stevie-2019.png" url = "https://stevieawards.com/aba/company-organization-awards-1" [[awards]] title = "BIG Innovation Award 2019" featured = true +date = "5th February 2019" img = "/logos/press/awards/big-2019.png" url = "https://www.bintelligence.com/blog/2019/2/5/74-companies-products-and-executives-who-are-leading-in-innovation" [[awards]] title = "Companies to Watch 2019" featured = false +date = "1st November 2018" img = "/logos/press/sdtimes.png" url = "https://sdtimes.com/softwaredev/companies-to-watch-in-2019" [[awards]] title = "DevOps Company of the Year Nominee" featured = false +date = "4th April 2019" img = "/logos/press/awards/computing-devops-2019.png" [[awards]] title = "Best open source software of 2019" featured = true +date = "7th October 2019" img = "/logos/press/awards/bossie-2019.png" url = "https://www.infoworld.com/article/3444198/the-best-open-source-software-of-2019.html?upd=1570549053159#slide9" [[awards]] title = "10 Coolest Startups of 2019" featured = true +date = "15th August 2019" img = "/logos/press/crn.png" url = "https://www.crn.com/slide-shows/applications-os/the-10-coolest-devops-startups-of-2019-so-far-/9?itc=refresh" diff --git a/layouts/page/about.html b/layouts/page/about.html index 656c899fe817..653bc74b5c21 100644 --- a/layouts/page/about.html +++ b/layouts/page/about.html @@ -183,65 +183,33 @@

Our journey

-
-
-
-
-
-
-
+
+
+
+
+

In the Newsroom

+

Recent press, news coverage, and awards.

+
+ View the Newsroom →
-
-
-

Our awards & recognition

-
    - {{ range first 4 (where site.Data.awards.awards "featured" true) }} -
  • - - - + +
      + {{ with index site.Data.newsroom.releases 0 }} +
    • + {{ partial "newsroom/card.html" (dict "type" "news" "title" .title "summary" .summary "url" .url "date" .date) }} +
    • + {{ end }} + {{ with index site.Data.newsroom.coverage 0 }} +
    • + {{ partial "newsroom/card.html" (dict "type" "press" "title" .title "img" .img "url" .url "date" .date) }} +
    • + {{ end }} + {{ with index (where site.Data.awards.awards "featured" true) 0 }} +
    • + {{ partial "newsroom/card.html" (dict "type" "awards" "title" .title "img" .img "url" .url "date" .date) }}
    • {{ end }}
    - -
-
- -
-
-
- -
-
-
-

Press Releases

-
    - {{ range first 2 site.Data.newsroom.releases }} -
  • -
    {{ .date }}
    -
    {{ .title }}
    - Read more → -
  • - {{ end }} -
- View all press releases -
-
-

Recent News

-
    - {{ range first 2 site.Data.newsroom.coverage }} -
  • -
    {{ .date }}
    - -
    {{ .title }}
    - Read more → -
  • - {{ end }} -
- View all recent news -
diff --git a/layouts/page/awards.html b/layouts/page/awards.html deleted file mode 100644 index 025f101aef08..000000000000 --- a/layouts/page/awards.html +++ /dev/null @@ -1,43 +0,0 @@ -{{ define "hero" }} - {{ partial "hero.html" (dict "title" .Title) }} -{{ end }} - -{{ define "main" }} -
-
-
    - {{ range site.Data.awards.awards }} -
  • -
    -
    - {{ if .url }} - - - - {{ else }} - - {{ end }} -
    -
    -
    - {{ if .url }} - {{ .title }} - {{ else }} - {{ .title }} - {{ end }} -
    - {{ if .url }} - Read more → - {{ end }} -
    -
    -
  • - {{ end }} -
-
-
- - {{ partial "learnmore-contactus.html" . }} - - {{ partial "newsletter.html" . }} -{{ end }} diff --git a/layouts/page/newsroom.html b/layouts/page/newsroom.html index 13b80535885d..043d855f75de 100644 --- a/layouts/page/newsroom.html +++ b/layouts/page/newsroom.html @@ -1,37 +1,93 @@ {{ define "hero" }} - {{ partial "hero" (dict "title" .Params.title ) }} + {{ partial "hero" (dict "title" .Title) }} {{ end }} {{ define "main" }} -
-
-
-

Press Releases

-
    - {{ range site.Data.newsroom.releases }} -
  • -
    {{ .date }}
    -
    {{ .title }}
    - Read more → -
  • - {{ end }} -
-
-
-

Recent News

-
    - {{ range site.Data.newsroom.coverage }} -
  • -
    {{ .date }}
    - -
    {{ .title }}
    - {{ if .url }} - Read more → + {{/* Build a unified, date-sorted feed of press releases, news coverage, and awards. */}} + {{ $items := slice }} + + {{/* Press releases (company-authored) → "News" tab. */}} + {{ range site.Data.newsroom.releases }} + {{ $sortKey := partial "newsroom/sort-key.html" .date }} + {{ $items = $items | append (dict "type" "news" "title" .title "summary" .summary "url" .url "date" .date "sortKey" $sortKey) }} + {{ end }} + + {{/* Media coverage (external) → "Press" tab. */}} + {{ range site.Data.newsroom.coverage }} + {{ $sortKey := partial "newsroom/sort-key.html" .date }} + {{ $items = $items | append (dict "type" "press" "title" .title "img" .img "url" .url "date" .date "sortKey" $sortKey) }} + {{ end }} + + {{ range site.Data.awards.awards }} + {{ $sortKey := partial "newsroom/sort-key.html" .date }} + {{ $items = $items | append (dict "type" "awards" "title" .title "img" .img "url" .url "date" .date "sortKey" $sortKey) }} + {{ end }} + + {{ $items = sort $items "sortKey" "desc" }} + + {{/* Filters drive both the tab bar and the per-filter pane render. */}} + {{ $filters := slice + (dict "key" "all" "label" "All" "items" $items) + (dict "key" "news" "label" "News" "items" (where $items "type" "news")) + (dict "key" "press" "label" "Press" "items" (where $items "type" "press")) + (dict "key" "awards" "label" "Awards" "items" (where $items "type" "awards")) + }} + + {{ $featuredCount := 9 }} + +
    + {{ range $filters }} + + {{ end }} + +
    + +
    + + {{ range $filters }} + {{ $key := .key }} + {{ $feed := .items }} + {{ $featured := first $featuredCount $feed }} + {{ $archive := after $featuredCount $feed }} + +
    + {{ if $featured }} +
+
+ {{ end }} + + {{ if $archive }} +
+

Archive

+
    + {{ range $archive }} +
  • + {{ partial "newsroom/archive-row.html" . }} +
  • + {{ end }} +
+
+

+ +
+
+ {{ end }}
-
+ {{ end }} + +
{{ end }} diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index 7f22a5ae296c..c425c74c8342 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -33,7 +33,7 @@
  • About Us
  • Community
  • Careers
  • -
  • Awards & Recognitions
  • +
  • Newsroom
  • Brand Resources
  • Your Website Preferences
  • diff --git a/layouts/partials/header.html b/layouts/partials/header.html index 600e5e9627d3..6a6db4d52123 100644 --- a/layouts/partials/header.html +++ b/layouts/partials/header.html @@ -333,16 +333,7 @@ Newsroom -
    Pulumi in the news
    -
    - - -
  • -
    - - - Awards -
    Recognition from press and analysts
    +
    News, press, and awards
  • @@ -494,9 +485,6 @@
  • Newsroom
  • -
  • - Awards -

  • diff --git a/layouts/partials/newsroom/archive-row.html b/layouts/partials/newsroom/archive-row.html new file mode 100644 index 000000000000..bac617ea93ba --- /dev/null +++ b/layouts/partials/newsroom/archive-row.html @@ -0,0 +1,47 @@ +{{/* + Newsroom archive row partial. + + Renders a single compact row in the archive list, with a leading title and + trailing type pill + date. Whole row is a link when a URL is present; + otherwise renders as a non-interactive div. + + Expected context (dict): + type: "news" | "press" | "awards" + title: item title (required) + url: optional destination URL + date: optional date string +*/}} + +{{ $type := .type }} +{{ $title := .title }} +{{ $url := .url }} +{{ $date := .date }} + +{{ $meta := partial "newsroom/type-meta.html" . }} +{{ $typeLabel := $meta.label }} +{{ $typeBadgeClass := $meta.badgeClass }} +{{ $trackName := $meta.trackName }} +{{ $external := $meta.external }} + +{{ $rowClass := "newsroom-archive-row flex items-center justify-between gap-4 py-3 px-2 no-underline transition-colors" }} + +{{ if $url }} + +{{ else }} +
    +{{ end }} + {{ $title }} + + {{ $typeLabel }} + {{ if $date }}{{ $date }}{{ end }} + +{{ if $url }} + +{{ else }} +
    +{{ end }} diff --git a/layouts/partials/newsroom/card.html b/layouts/partials/newsroom/card.html new file mode 100644 index 000000000000..d2abe05500b8 --- /dev/null +++ b/layouts/partials/newsroom/card.html @@ -0,0 +1,60 @@ +{{/* + Newsroom card partial. + + Renders a uniform card for press releases, news coverage, and awards. + Uses the "stretched link" pattern so the whole card is clickable when a URL is present. + + Expected context (dict): + type: "press" | "news" | "awards" + title: item title (required) + summary: optional summary text (press) + img: optional image URL (news, awards) + url: optional destination URL + date: optional date string (press, news) +*/}} + +{{ $type := .type }} +{{ $title := .title }} +{{ $summary := .summary }} +{{ $img := .img }} +{{ $url := .url }} +{{ $date := .date }} + +{{ $meta := partial "newsroom/type-meta.html" . }} +{{ $typeLabel := $meta.label }} +{{ $typeBadgeClass := $meta.badgeClass }} +{{ $trackName := $meta.trackName }} +{{ $external := $meta.external }} + +
    +
    + {{ if eq $type "news" }} + + {{ else }} + + {{ end }} +
    + +
    +
    + {{ if $date }} + {{ $date }} + {{ end }} + {{ $typeLabel }} +
    +
    {{ $title }}
    + {{ if $summary }} +

    {{ $summary }}

    + {{ end }} +
    + + {{ if $url }} + + {{ end }} +
    diff --git a/layouts/partials/newsroom/sort-key.html b/layouts/partials/newsroom/sort-key.html new file mode 100644 index 000000000000..9a11f9856d0d --- /dev/null +++ b/layouts/partials/newsroom/sort-key.html @@ -0,0 +1,39 @@ +{{/* + Newsroom sort-key partial. + + Parses a human-readable date string from data/newsroom.toml or + data/awards.toml (e.g. "5th November 2025", "20 November 2024", + "12th Nov 2019") and returns a "YYYY-MM-DD" string suitable for + lexicographic sorting. Returns an empty string when the input is empty. + + Expected context: a date string. + + Usage: + {{ $sortKey := partial "newsroom/sort-key.html" .date }} +*/}} + +{{ $months := dict + "January" 1 "Jan" 1 + "February" 2 "Feb" 2 + "March" 3 "Mar" 3 + "April" 4 "Apr" 4 + "May" 5 + "June" 6 "Jun" 6 + "July" 7 "Jul" 7 + "August" 8 "Aug" 8 + "September" 9 "Sep" 9 "Sept" 9 + "October" 10 "Oct" 10 + "November" 11 "Nov" 11 + "December" 12 "Dec" 12 +}} + +{{ $sortKey := "" }} +{{ if . }} + {{ $clean := replaceRE `(\d+)(st|nd|rd|th)` `$1` . }} + {{ $parts := split $clean " " }} + {{ $day := int (index $parts 0) }} + {{ $month := index $months (index $parts 1) }} + {{ $year := int (index $parts 2) }} + {{ $sortKey = printf "%04d-%02d-%02d" $year $month $day }} +{{ end }} +{{ return $sortKey }} diff --git a/layouts/partials/newsroom/type-meta.html b/layouts/partials/newsroom/type-meta.html new file mode 100644 index 000000000000..a4e930bc401a --- /dev/null +++ b/layouts/partials/newsroom/type-meta.html @@ -0,0 +1,47 @@ +{{/* + Newsroom type-meta partial. + + Maps a newsroom item's type to its display label, badge color classes, + analytics track name, and external-link flag. Used by both the card and + archive-row partials so the mapping has one source of truth. + + Type semantics: + "news" — company-authored press releases (the "News" tab). + "press" — external media coverage (the "Press" tab). + "awards" — industry awards. + + Expected context (dict): + type: "news" | "press" | "awards" + url: optional — used for the news/award track name + title: optional — used for the award track name slug + + Returns: + dict { label, badgeClass, trackName, external } +*/}} + +{{ $type := .type }} +{{ $url := .url }} +{{ $title := .title }} + +{{ $label := "" }} +{{ $badgeClass := "" }} +{{ $trackName := "" }} +{{ $external := false }} + +{{ if eq $type "news" }} + {{ $label = "News" }} + {{ $badgeClass = "bg-violet-100 text-violet-700" }} + {{ $trackName = "press-release" }} +{{ else if eq $type "press" }} + {{ $label = "Press" }} + {{ $badgeClass = "bg-blue-100 text-blue-700" }} + {{ $trackName = printf "press-%s" ($url | urlize) }} + {{ $external = true }} +{{ else if eq $type "awards" }} + {{ $label = "Award" }} + {{ $badgeClass = "bg-yellow-100 text-yellow-800" }} + {{ $trackName = printf "award-%s" ($title | urlize) }} + {{ $external = true }} +{{ end }} + +{{ return dict "label" $label "badgeClass" $badgeClass "trackName" $trackName "external" $external }} diff --git a/theme/src/scss/_about.scss b/theme/src/scss/_about.scss index 6c70283730c5..590d874c1e04 100644 --- a/theme/src/scss/_about.scss +++ b/theme/src/scss/_about.scss @@ -51,26 +51,6 @@ border-image-source: linear-gradient(90deg, #f7bf2a 0%, #f26e7e 18.23%, #be5188 38.02%, #8a3391 53.65%, #805ac3 74.48%, #7682f4 100%); } -#awards { - .award { - height: 230px; - width: 230px; - border-radius: 14px; - background: linear-gradient(90deg, #f7bf2a 0%, #f26e7e 18.23%, #be5188 38.02%, #8a3391 53.65%, #805ac3 74.48%, #7682f4 100%); - - a { - height: 226px; - width: 226px; - border-radius: 12px; - background-color: white; - - img { - width: 180px; - } - } - } -} - #we-are-pulumi { @apply relative w-full; @@ -109,7 +89,7 @@ } } -#we-are-pulumi, #who-we-are, #what-we-believe, #community, #history, #awards, #newsroom, #join-us { +#we-are-pulumi, #who-we-are, #what-we-believe, #community, #history, #newsroom, #join-us { scroll-margin-top: 75px; } diff --git a/theme/src/scss/_awards.scss b/theme/src/scss/_awards.scss deleted file mode 100644 index a74375b0e3e7..000000000000 --- a/theme/src/scss/_awards.scss +++ /dev/null @@ -1,11 +0,0 @@ -@media (min-width: 0px) { - .medium-auto-height { - height: 13rem; - } -} - -@media (min-width: 768px) { - .medium-auto-height { - height: auto; - } -} \ No newline at end of file diff --git a/theme/src/scss/_newsroom.scss b/theme/src/scss/_newsroom.scss new file mode 100644 index 000000000000..7823c7bc4402 --- /dev/null +++ b/theme/src/scss/_newsroom.scss @@ -0,0 +1,121 @@ +.pulumi-newsroom-list-container { + + #newsroom-filter-nav { + @apply flex font-body text-base py-0; + + list-style: none !important; + + li { + @apply border-solid border-b-2 border-transparent; + margin-bottom: -1px; + + > a { + @apply block py-3 px-4 font-normal text-base text-center text-gray-700 no-underline whitespace-nowrap; + + @include screen-lg { + @apply py-4 text-lg; + } + + // Reserve width for the bold (active) state so toggling weight + // doesn't shift surrounding tabs. The ghost copy is sized at + // font-weight 600 but has zero height, so it only contributes + // to width measurement. + > span { + display: inline-block; + + &::after { + content: attr(data-text); + display: block; + height: 0; + overflow: hidden; + visibility: hidden; + font-weight: 600; + } + } + } + + &:hover { + @apply border-gray-600; + + > a { + @apply text-black; + } + } + } + + // On initial load without a hash, the "All" tab should be active. + li[data-filter-name="all"] { + @include gradient-border; + + > a { + @apply font-semibold text-black; + } + } + } +} + +// Active tab styling driven by the URL hash, mirroring the events list pattern. +@each $filter-name in "all" "news" "press" "awards" { + ##{$filter-name}:target { + // Reset the default "all" tab styling when any other hash is set. + ~ .newsroom-filter li[data-filter-name="all"] { + @apply border-solid border-b-2 border-transparent; + border-image-source: none; + + > a { + @apply font-normal text-gray-600; + } + + &:hover { + @apply border-gray-600; + + > a { + @apply text-black; + } + } + } + + // Highlight the active tab. + ~ .newsroom-filter li[data-filter-name="#{$filter-name}"] { + @include gradient-border; + + > a { + @apply font-semibold text-black; + } + } + } +} + +.newsroom-card { + .newsroom-card-image img { + max-width: 70%; + } +} + +.newsroom-archive-list { + .newsroom-archive-row { + color: inherit; + + &:hover { + @apply bg-gray-50; + + .archive-title { + @apply text-violet-700; + } + } + } +} + +// On a single-type pane (News, Press, Awards), the type chip on cards and +// archive rows is redundant — every item already matches the active filter. +// +// The !important is intentional: this file is loaded inside @layer components, +// while Tailwind's display utilities (e.g. .inline-block) live in @layer +// utilities, which always wins on cascade order — !important is the cleanest +// way to override them without restructuring the layer setup. +[data-filter-section]:not([data-filter-section="all"]) { + .archive-type-pill, + .newsroom-card-type-pill { + display: none !important; + } +} diff --git a/theme/src/scss/main.scss b/theme/src/scss/main.scss index 659c204ac3ce..a808d0e6861a 100644 --- a/theme/src/scss/main.scss +++ b/theme/src/scss/main.scss @@ -218,7 +218,6 @@ $sitenav-offset: calc($sitenav-height + 16px); @import "api-nodejs"; @import "api-python"; @import "api-symbol"; - @import "awards"; @import "marketing/automation-api"; @import "badges"; @import "benefits"; @@ -254,6 +253,7 @@ $sitenav-offset: calc($sitenav-height + 16px); @import "notes"; @import "github-card"; @import "neo-card"; + @import "newsroom"; @import "docs/packages"; @import "pagination"; @import "marketing/pricing"; diff --git a/theme/src/scss/marketing/_shape-backgrounds.scss b/theme/src/scss/marketing/_shape-backgrounds.scss index 29a6c58ebfe0..57c5f7e393fb 100644 --- a/theme/src/scss/marketing/_shape-backgrounds.scss +++ b/theme/src/scss/marketing/_shape-backgrounds.scss @@ -15,40 +15,6 @@ max-width: 1680px; } - &.about-awards-section { - .circle-top-left { - @apply rounded-full absolute bg-yellow-600; - width: 17rem; - height: 17rem; - left: -8.25rem; - top: -8.5rem; - } - - .circle-top-right { - @apply rounded-full absolute bg-orange-500; - width: 12rem; - height: 12rem; - right: 4.5rem; - bottom: 14rem; - } - - .circle-bottom-left { - @apply rounded-full absolute bg-purple-600; - width: 12rem; - height: 12rem; - left: 0rem; - top: 23rem; - } - - .circle-bottom-right { - @apply rounded-full absolute bg-salmon-600; - width: 5.5rem; - height: 5.5rem; - right: -1.5rem; - bottom: -1rem; - } - } - &.about-what-we-believe { .circle-top-left { @apply rounded-full absolute bg-fuchsia-600; diff --git a/theme/src/ts/main.ts b/theme/src/ts/main.ts index 03a17135af46..a8bd59e5a8f6 100644 --- a/theme/src/ts/main.ts +++ b/theme/src/ts/main.ts @@ -15,6 +15,7 @@ import "./copybutton"; import "./code-tabbed"; import "./code-snippets-dropdown"; import "./resources"; +import "./newsroom"; import "./packages"; import "./pricing-trial"; import "./pulumi-cloud"; diff --git a/theme/src/ts/misc.ts b/theme/src/ts/misc.ts index 39263899f735..a1334f0a5972 100644 --- a/theme/src/ts/misc.ts +++ b/theme/src/ts/misc.ts @@ -242,7 +242,7 @@ export function generateOnThisPage() { this.classList.add(activeClassName); const activeLink = (this as HTMLElement).dataset.filterName; - const allLinks = ["who-we-are", "what-we-believe", "community", "history", "awards", "newsroom", "join-us"]; + const allLinks = ["who-we-are", "what-we-believe", "community", "history", "newsroom", "join-us"]; const inactiveLinks = allLinks.filter(link => link !== activeLink); inactiveLinks.forEach(link => { diff --git a/theme/src/ts/newsroom.ts b/theme/src/ts/newsroom.ts new file mode 100644 index 000000000000..3a4fc10f83e4 --- /dev/null +++ b/theme/src/ts/newsroom.ts @@ -0,0 +1,110 @@ +declare global { + interface Window { + analytics?: { + track: (event: string, properties?: Record) => void; + }; + } +} + +const VALID_FILTERS = ["all", "news", "press", "awards"] as const; +type Filter = (typeof VALID_FILTERS)[number]; + +const ARCHIVE_PAGE_SIZE = 20; + +const isValidFilter = (value: string): value is Filter => + (VALID_FILTERS as readonly string[]).includes(value); + +const filterFromHash = (): Filter => { + const hash = location.hash.slice(1); + return isValidFilter(hash) ? hash : "all"; +}; + +const trackEvent = (event: string, properties: Record) => { + window.analytics?.track(event, properties); +}; + +// Pagination state per filter pane. +const archiveVisible: Record = { + all: ARCHIVE_PAGE_SIZE, + news: ARCHIVE_PAGE_SIZE, + press: ARCHIVE_PAGE_SIZE, + awards: ARCHIVE_PAGE_SIZE, +}; + +const state = { + filter: filterFromHash(), +}; + +const updatePaneVisibility = () => { + document.querySelectorAll("[data-filter-section]").forEach(pane => { + pane.classList.toggle("hidden", pane.dataset.filterSection !== state.filter); + }); +}; + +const updateArchive = (filter: Filter) => { + const pane = document.querySelector(`[data-filter-section="${filter}"]`); + if (!pane) return; + + const items = Array.from(pane.querySelectorAll(".newsroom-archive-list li[data-archive-item]")); + const visibleCount = Math.min(archiveVisible[filter], items.length); + + items.forEach((item, i) => { + item.style.display = i < visibleCount ? "" : "none"; + }); + + const loadMoreBtn = pane.querySelector(".newsroom-load-more"); + loadMoreBtn?.classList.toggle("hidden", visibleCount >= items.length); + + const countEl = pane.querySelector(".newsroom-count"); + if (countEl) { + countEl.textContent = items.length === 0 + ? "" + : `Showing ${visibleCount} of ${items.length} archived items`; + } +}; + +const updateView = () => { + updatePaneVisibility(); + updateArchive(state.filter); + + // Empty-state message: shown if the active pane has neither a featured grid nor an archive list. + const pane = document.querySelector(`[data-filter-section="${state.filter}"]`); + const noResults = document.querySelector(".pulumi-newsroom-list-container .no-results"); + const hasContent = !!pane?.querySelector(".newsroom-featured-section, .newsroom-archive-section"); + noResults?.classList.toggle("hidden", hasContent); +}; + +const onHashChange = () => { + const next = filterFromHash(); + if (next === state.filter) return; + state.filter = next; + archiveVisible[next] = ARCHIVE_PAGE_SIZE; // Reset to first page when filter changes. + updateView(); + trackEvent("newsroom-filter", { filter: next }); +}; + +const wireUpLoadMore = () => { + document.querySelectorAll(".newsroom-load-more").forEach(button => { + const pane = button.closest("[data-filter-section]"); + const filter = pane?.dataset.filterSection as Filter | undefined; + if (!filter || !isValidFilter(filter)) return; + + button.addEventListener("click", () => { + archiveVisible[filter] += ARCHIVE_PAGE_SIZE; + updateArchive(filter); + trackEvent("newsroom-load-more", { + filter, + visible: archiveVisible[filter], + }); + if (!button.classList.contains("hidden")) { + button.focus(); + } + }); + }); +}; + +if (document.querySelector(".pulumi-newsroom-list-container")) { + updateView(); + wireUpLoadMore(); + window.addEventListener("hashchange", onHashChange); +}