diff --git a/.eleventy.js b/.eleventy.js index 9b45e65cc5..637a69c875 100644 --- a/.eleventy.js +++ b/.eleventy.js @@ -107,7 +107,7 @@ module.exports = function(eleventyConfig) { }); // Add a global data variable for the current date - eleventyConfig.addGlobalData("currentDateISO", new Date().toISOString()); + eleventyConfig.addGlobalData("currentDateISO", new Date().toISOString()); // Make filters globally accessible global.isFuturePost = eleventyConfig.getFilter('isFuturePost'); @@ -226,6 +226,13 @@ module.exports = function(eleventyConfig) { eleventyConfig.addFilter("limit", (arr, limit) => arr.slice(0, limit )); + // Marketing image for a nav highlight card: the linked page's image front matter + eleventyConfig.addFilter("pageImageForUrl", (collection, url) => { + const normalized = url && !url.endsWith("/") ? `${url}/` : url; + const match = (collection || []).find((p) => p.url === normalized); + return (match && match.data && match.data.image) || null; + }); + eleventyConfig.addFilter('console', function (value) { const str = util.inspect(value, { showHidden: false, depth: null }); return `
${unescape(str)}
;` @@ -973,11 +980,11 @@ module.exports = function(eleventyConfig) { if (content) { const chevronDown = loadSVG('chevron-down') - return `
  • ${iconSvg}${label}${chevronDown}${content}
  • ` + return `
  • ${iconSvg}${label}${chevronDown}${content}
  • ` } else if (link) { - return `
  • ${iconSvg}${label}
  • ` + return `
  • ${iconSvg}${label}
  • ` } else { - return `
  • ${iconSvg}${label}
  • ` + return `
  • ${iconSvg}${label}
  • ` } }); diff --git a/nuxt/components/AppFooter.vue b/nuxt/components/AppFooter.vue index 5ea34b2370..6165e17966 100644 --- a/nuxt/components/AppFooter.vue +++ b/nuxt/components/AppFooter.vue @@ -1,11 +1,128 @@ diff --git a/nuxt/components/AppHeader.vue b/nuxt/components/AppHeader.vue index 890543e9df..e642e87b33 100644 --- a/nuxt/components/AppHeader.vue +++ b/nuxt/components/AppHeader.vue @@ -1,5 +1,11 @@ + + diff --git a/nuxt/layouts/default.vue b/nuxt/layouts/default.vue index 328839dea7..43602ed01d 100644 --- a/nuxt/layouts/default.vue +++ b/nuxt/layouts/default.vue @@ -3,6 +3,7 @@ Skip to main content
    +
    diff --git a/src/_data/navHighlights.json b/src/_data/navHighlights.json new file mode 100644 index 0000000000..7e64a99026 --- /dev/null +++ b/src/_data/navHighlights.json @@ -0,0 +1,23 @@ +{ + "_comment": "Nav highlight cards, one per top-nav dropdown. Marketing owns this file: each entry is the promo card shown at the left of the corresponding mega dropdown on xl+ screens. Swap an entry to feature a campaign, webinar, customer story or launch. Each card renders as the image plus the title (which also serves as the link's accessible name); keep titles short (2 lines max). Set image to a site-absolute path to override, otherwise the card uses the linked page's front-matter image, falling back to /images/og-blog.jpg. Consumed by Eleventy (base.njk) and by Nuxt (nuxt/components/AppHeader.vue).", + "platform": { + "title": "Industrial AI, governed and built in", + "link": "/ai/", + "image": "/images/ai/ai-hero.png" + }, + "solutions": { + "title": "Scale automotive operations", + "link": "/industries/automotive/", + "image": "/images/industries/automotive.jpg" + }, + "resources": { + "title": "Free Node-RED training", + "link": "https://node-red-academy.learnworlds.com/", + "image": "/images/education/education_hero.jpg" + }, + "company": { + "title": "See how teams ship with FlowFuse", + "link": "/customer-stories/", + "image": "/images/stories/arch_systems.jpeg" + } +} diff --git a/src/_includes/base.js b/src/_includes/base.js index d0536fc383..3f6872809d 100644 --- a/src/_includes/base.js +++ b/src/_includes/base.js @@ -164,3 +164,17 @@ function ffCreateHubSpotForm (config) { } window.ffCreateHubSpotForm = ffCreateHubSpotForm + +// Mobile nav: dropdown sections expand on tap, not hover +document.addEventListener('DOMContentLoaded', function () { + document.querySelectorAll('header .ff-nav-dropdown > span').forEach(function (trigger) { + trigger.addEventListener('click', function (e) { + if (window.innerWidth < 768) { + e.preventDefault() + e.stopPropagation() + // Toggle this section on its own; other open sections stay open + trigger.parentElement.classList.toggle('mobile-expanded') + } + }) + }) +}) diff --git a/src/_includes/components/events-banner.njk b/src/_includes/components/events-banner.njk deleted file mode 100644 index 0829f60ffa..0000000000 --- a/src/_includes/components/events-banner.njk +++ /dev/null @@ -1,76 +0,0 @@ -{% set colors = ["bg-indigo-700 hover:bg-indigo-600", "bg-indigo-800 hover:bg-indigo-700", "bg-indigo-900 hover:bg-indigo-800"] %} -{% set hasFutureEvents = false %} - -{% for event in events %} - {% if event.expire | isFutureDate %} - {% set hasFutureEvents = true %} - {% endif %} -{% endfor %} - -{% if hasFutureEvents %} - -{% endif %} - - diff --git a/src/_includes/components/flowfuse-square.svg b/src/_includes/components/flowfuse-square.svg index f117e04e8b..7ce1777f2d 100644 --- a/src/_includes/components/flowfuse-square.svg +++ b/src/_includes/components/flowfuse-square.svg @@ -1,2 +1,2 @@ - + \ No newline at end of file diff --git a/src/_includes/components/flowfuse-wordmark-footer.njk b/src/_includes/components/flowfuse-wordmark-footer.njk new file mode 100644 index 0000000000..38ebde749b --- /dev/null +++ b/src/_includes/components/flowfuse-wordmark-footer.njk @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/_includes/components/flowfuse-wordmark.njk b/src/_includes/components/flowfuse-wordmark.njk index cc886a85cb..6dba8f8275 100644 --- a/src/_includes/components/flowfuse-wordmark.njk +++ b/src/_includes/components/flowfuse-wordmark.njk @@ -1,4 +1,13 @@ + + + + + + + + + @@ -10,37 +19,37 @@ + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> + fill="url(#ffWaveWordmark)" /> diff --git a/src/_includes/components/icons/wind-turbine.svg b/src/_includes/components/icons/wind-turbine.svg index 4a4e3104f9..8a83fd49ad 100644 --- a/src/_includes/components/icons/wind-turbine.svg +++ b/src/_includes/components/icons/wind-turbine.svg @@ -1,4 +1,4 @@ - + diff --git a/src/_includes/components/nav-highlight.njk b/src/_includes/components/nav-highlight.njk new file mode 100644 index 0000000000..c66dca9bd0 --- /dev/null +++ b/src/_includes/components/nav-highlight.njk @@ -0,0 +1,13 @@ +{# Mega-dropdown highlight card: the linked page's marketing image with a + short title underneath. Expects `hl` set by the caller: + {% set hl = navHighlights.platform %}{% include "components/nav-highlight.njk" %} + Content is configured in src/_data/navHighlights.js (marketing-owned). + Card image: hl.image override, else the linked page's `image:` front + matter (its marketing image), else the generic og-blog fallback. #} +{% set hlImage = hl.image or (collections.all | pageImageForUrl(hl.link)) or "/images/og-blog.jpg" %} +
  • + + {{ hl.title }} + + +
  • diff --git a/src/_includes/components/top-utility-bar.njk b/src/_includes/components/top-utility-bar.njk new file mode 100644 index 0000000000..572a0921b6 --- /dev/null +++ b/src/_includes/components/top-utility-bar.njk @@ -0,0 +1,78 @@ +{# Slim top utility bar: rotating announcements (left) + quick links (right). + Pattern adapted from tailscale.com's slim top bar. The announcement slot + rotates through any live events (same behaviour as the old events-banner) + plus the standing promos below. Implements the intent of website PR #5067. #} + + + diff --git a/src/_includes/layouts/base.njk b/src/_includes/layouts/base.njk index a6da57aa43..346fada9ae 100644 --- a/src/_includes/layouts/base.njk +++ b/src/_includes/layouts/base.njk @@ -163,20 +163,23 @@ eleventyComputed: Skip to main content -
    -
    - - {% include "../components/events-banner.njk" %} - -
    + + {% include "../components/top-utility-bar.njk" %} + +
    + +
    +
    {{ content | safe }} @@ -286,66 +365,181 @@ eleventyComputed: {% include "components/hm-promo-banner.njk" %}