mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-05 10:13:39 +00:00
feat(blocks): add columns footer block
This commit is contained in:
1 parent
bf41049de2
commit
ab44db81d7
9 files changed
+245
-8
No files matched your search
@@ -18,8 +18,8 @@ function FeatureItem({ item, iconSvg }) {
|
||||
return (
|
||||
<div>
|
||||
{iconSvg && (
|
||||
<div class="flex justify-center items-center mb-4 w-10 h-10 rounded-full bg-primary-100 lg:h-12 lg:w-12 dark:bg-primary-900 text-primary-600 dark:text-primary-300">
|
||||
<Icon svg={iconSvg} attributes={{ class: "w-5 h-5 lg:w-6 lg:h-6" }} />
|
||||
<div class="flex justify-center items-center mb-4 w-12 h-12 rounded-full bg-primary-100 lg:h-14 lg:w-14 dark:bg-primary-900 text-primary-600 dark:text-primary-300">
|
||||
<Icon svg={iconSvg} attributes={{ class: "flex items-center justify-center w-6 h-6 lg:w-8 lg:h-8" }} />
|
||||
</div>
|
||||
)}
|
||||
{item.name && (
|
||||
|
||||
@@ -5,6 +5,13 @@ import { h } from "preact";
|
||||
* Icon component
|
||||
* Renders an SVG icon from a raw SVG string passed from Hugo.
|
||||
* Decodes JSON-escaped sequences (\u003c) and HTML entities (<, ", ").
|
||||
*
|
||||
* SVG sizing strategy:
|
||||
* - By default, icons size to 1em (matching current font size) — works universally
|
||||
* for inline icons in buttons, text, lists, etc.
|
||||
* - If the caller provides explicit height via style attribute (e.g. style="height: 36px"),
|
||||
* the SVG fills that container with height:100%;width:auto instead.
|
||||
* - If the caller provides explicit w-/h- Tailwind classes, those take precedence.
|
||||
*/
|
||||
export const Icon = ({ svg, attributes }) => {
|
||||
if (!svg) return null;
|
||||
@@ -24,9 +31,19 @@ export const Icon = ({ svg, attributes }) => {
|
||||
const hasWrapper = /<svg[\s>]/i.test(decoded);
|
||||
|
||||
if (hasWrapper) {
|
||||
// Determine SVG sizing: if caller provides explicit height (via style attr),
|
||||
// use 100% to fill the container; otherwise default to 1em for self-sizing.
|
||||
const callerStyle = attributes?.style || "";
|
||||
const hasExplicitHeight = /height\s*:/i.test(String(callerStyle));
|
||||
const svgStyle = hasExplicitHeight
|
||||
? "height:100%;width:auto"
|
||||
: "height:1em;width:auto";
|
||||
|
||||
decoded = decoded.replace(/^(<svg\b)/i, `$1 style="${svgStyle}"`);
|
||||
|
||||
const wrapperProps = {
|
||||
...attributes,
|
||||
class: `flex items-center justify-center ${attributes?.class || ""}`.trim(),
|
||||
class: attributes?.class || "",
|
||||
};
|
||||
|
||||
// eslint-disable-next-line lint/security/noDangerouslySetInnerHtml
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
{{ $branding := partialCached "functions/get_branding" . "branding" }}
|
||||
{{- $logo_height := site.Params.hugoblox.footer.logo_height | default 36 -}}
|
||||
{{ $logo := partialCached "functions/get_logo" (dict "constraint" "max_height" "size" $logo_height) "footer_logo" }}
|
||||
{{- $show_logo := site.Params.hugoblox.footer.show_logo | default true -}}
|
||||
{{- $show_title := site.Params.hugoblox.footer.show_title | default true -}}
|
||||
{{- $show_tagline := site.Params.hugoblox.footer.show_tagline | default true -}}
|
||||
{{- $footer_title := site.Params.hugoblox.footer.title | default $branding.name -}}
|
||||
<footer aria-labelledby="footer-heading">
|
||||
<span id="footer-heading" class="sr-only">Footer</span>
|
||||
|
||||
<div class="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-16">
|
||||
<div class="xl:grid xl:grid-cols-3 xl:gap-8 xl:items-start">
|
||||
<div class="xl:col-span-1">
|
||||
{{ if $show_logo }}
|
||||
{{ with $logo.resource }}
|
||||
{{ if $logo.is_svg }}
|
||||
<div class="footer-logo" style="height: {{ $logo_height }}px;">
|
||||
{{- .Content | safeHTML -}}
|
||||
</div>
|
||||
<style>.footer-logo svg { height: 100%; width: auto; }</style>
|
||||
{{ else }}
|
||||
<img
|
||||
decoding="async"
|
||||
width="{{ .Width }}"
|
||||
height="{{ .Height }}"
|
||||
src="{{ .RelPermalink }}"
|
||||
alt="{{ $branding.name }}" />
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ if $show_title }}
|
||||
<a class="text-lg font-bold tracking-tighter text-primary-600 transition duration-500 ease-in-out lg:pr-8 dark:text-primary-200" href="{{site.Home.RelPermalink}}">
|
||||
{{ $footer_title }}
|
||||
</a>
|
||||
{{ end }}
|
||||
{{ if $show_tagline }}
|
||||
<p class="mt-2 w-1/2 text-sm text-gray-500 dark:text-gray-300">{{ site.Params.hugoblox.identity.tagline | default "" }}</p>
|
||||
{{ end }}
|
||||
{{- $show_social := site.Params.hugoblox.footer.show_social | default true -}}
|
||||
{{ if $show_social }}
|
||||
{{ with site.Params.hugoblox.identity.social.links }}
|
||||
<div class="mt-4 text-xl">
|
||||
{{ partial "social_links" (dict "Params" (dict "profiles" .)) }}
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="mt-12 grid grid-cols-1 gap-8 xl:col-span-2 xl:mt-0 md:grid-cols-{{ len .Site.Menus.footer }}">
|
||||
|
||||
{{ $menu := .Site.Menus.footer }}
|
||||
{{ range $index, $menuItem := $menu }}
|
||||
<div>
|
||||
<h3 class="text-sm font-bold tracking-wider text-primary-500 uppercase dark:text-primary-300">{{ $menuItem.Name }}</h3>
|
||||
<ul role="list" class="mt-4 space-y-2">
|
||||
{{ range $childIndex, $childMenuItem := $menuItem.Children }}
|
||||
{{ $url := .URL | relLangURL }}
|
||||
<li>
|
||||
<a href="{{ $url }}"
|
||||
class="text-base font-normal text-gray-500 hover:text-primary-600 dark:text-gray-300 dark:hover:text-primary-300"
|
||||
{{ if findRE `^http` .URL }}
|
||||
target="_blank" rel="noopener"
|
||||
{{ end }}
|
||||
>
|
||||
{{ $childMenuItem.Name }}
|
||||
</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-16">
|
||||
<div class="flex flex-wrap items-baseline">
|
||||
<span class="mt-2 text-sm font-light text-gray-500 dark:text-gray-300">
|
||||
{{/* Display copyright license. */}}
|
||||
{{ partial "site_footer_license" . }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
@@ -6,7 +6,9 @@
|
||||
{{- $block_id := "" -}}
|
||||
{{- $using_legacy := false -}}
|
||||
|
||||
{{- if $config.block -}}
|
||||
{{- if $config.style -}}
|
||||
{{- $block_id = $config.style -}}
|
||||
{{- else if $config.block -}}
|
||||
{{- $block_id = $config.block -}}
|
||||
{{- else if $config.blox -}}
|
||||
{{- $block_id = $config.blox -}}
|
||||
|
||||
@@ -12,9 +12,83 @@ main:
|
||||
- name: Solutions
|
||||
url: /#solutions
|
||||
weight: 30
|
||||
- name: Changelog
|
||||
url: /changelog/
|
||||
weight: 35
|
||||
- name: Resources
|
||||
weight: 40
|
||||
hasChildren: true
|
||||
- parent: Resources
|
||||
name: Blog
|
||||
url: blog/
|
||||
|
||||
# Footer links (4-column layout)
|
||||
# Top-level items become column headings, children become links.
|
||||
footer:
|
||||
- name: Product
|
||||
weight: 10
|
||||
- parent: Product
|
||||
name: Features
|
||||
url: /#features
|
||||
weight: 10
|
||||
- parent: Product
|
||||
name: Solutions
|
||||
url: /#solutions
|
||||
weight: 20
|
||||
- parent: Product
|
||||
name: Pricing
|
||||
url: "#"
|
||||
weight: 30
|
||||
- parent: Product
|
||||
name: Changelog
|
||||
url: /changelog/
|
||||
weight: 40
|
||||
|
||||
- name: Company
|
||||
weight: 20
|
||||
- parent: Company
|
||||
name: About
|
||||
url: "#"
|
||||
weight: 10
|
||||
- parent: Company
|
||||
name: Blog
|
||||
url: /blog/
|
||||
weight: 20
|
||||
- parent: Company
|
||||
name: Careers
|
||||
url: "#"
|
||||
weight: 30
|
||||
- parent: Company
|
||||
name: Contact
|
||||
url: "#"
|
||||
weight: 40
|
||||
|
||||
- name: Resources
|
||||
weight: 30
|
||||
- parent: Resources
|
||||
name: Documentation
|
||||
url: "#"
|
||||
weight: 10
|
||||
- parent: Resources
|
||||
name: Help Center
|
||||
url: "#"
|
||||
weight: 20
|
||||
- parent: Resources
|
||||
name: Community
|
||||
url: "#"
|
||||
weight: 30
|
||||
- parent: Resources
|
||||
name: Status
|
||||
url: "#"
|
||||
weight: 40
|
||||
|
||||
- name: Legal
|
||||
weight: 40
|
||||
- parent: Legal
|
||||
name: Privacy Policy
|
||||
url: /privacy/
|
||||
weight: 10
|
||||
- parent: Legal
|
||||
name: Terms of Service
|
||||
url: /terms/
|
||||
weight: 20
|
||||
@@ -19,12 +19,22 @@ hugoblox:
|
||||
# Schema.org type for structured data
|
||||
type: organization # person | organization | local_business
|
||||
# Short tagline displayed on your site
|
||||
tagline: ""
|
||||
tagline: "The framework for Hugo."
|
||||
# Site meta description for search engines and social sharing
|
||||
description: "The highly-customizable Hugo Academic theme powered by HugoBlox Kit. Easily create your personal academic website."
|
||||
# Social accounts (used for meta tags like Twitter Cards)
|
||||
social:
|
||||
twitter: "MakeOwnable" # Twitter/X handle for Twitter Cards (without @)
|
||||
# Site-wide social links (rendered in footer, etc.)
|
||||
links:
|
||||
- icon: brands/x
|
||||
url: https://x.com/MakeOwnable
|
||||
- icon: brands/github
|
||||
url: https://github.com/HugoBlox/kit
|
||||
- icon: brands/discord
|
||||
url: https://discord.gg/z8wNYzb
|
||||
- icon: brands/linkedin
|
||||
url: https://linkedin.com/company/example
|
||||
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
# THEME
|
||||
@@ -111,8 +121,15 @@ hugoblox:
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
footer:
|
||||
# Footer style variant
|
||||
style: minimal # minimal | columns | centered
|
||||
style: columns # minimal | columns | centered
|
||||
show_logo: true
|
||||
show_title: true
|
||||
show_tagline: true
|
||||
# Override footer title (defaults to identity.name)
|
||||
title: ""
|
||||
language_switcher: true
|
||||
# Show social icons from identity.social.links
|
||||
show_social: true
|
||||
# Custom footer text (HTML supported)
|
||||
text: ""
|
||||
|
||||
@@ -122,9 +139,9 @@ hugoblox:
|
||||
# ────────────────────────────────────────────────────────────────────────────
|
||||
copyright:
|
||||
# Copyright notice - supports {year}, {name}, {license} placeholders
|
||||
notice: "© {year} {name}. This work is licensed under {license}"
|
||||
notice: "© {year} {name}."
|
||||
license:
|
||||
type: cc # cc | custom
|
||||
type: custom # cc | custom
|
||||
allow_derivatives: false
|
||||
share_alike: true
|
||||
allow_commercial: false
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Changelog
|
||||
view: date-title-summary
|
||||
---
|
||||
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "v1.0 — Initial Release"
|
||||
date: 2026-01-15
|
||||
summary: "The first stable release of our platform, featuring the page builder, block system, and Tailwind 4 integration."
|
||||
version: "1.0.0"
|
||||
---
|
||||
|
||||
## What's New
|
||||
|
||||
- **Page Builder** — Build landing pages with drag-and-drop blocks
|
||||
- **Block System** — Hero, Features, CTA, Testimonials, Stats, and more
|
||||
- **Tailwind CSS 4** — Modern utility-first styling with dark mode support
|
||||
- **Preact Components** — Fast, lightweight client-side interactivity
|
||||
- **SEO Optimized** — Automatic sitemaps, RSS feeds, and structured data
|
||||
- **Multi-language** — 35+ language packs out of the box
|
||||
|
||||
## Getting Started
|
||||
|
||||
Check out the [documentation](https://docs.hugoblox.com/) to get started with your first site.
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: "v1.1 — Footer & Icon Improvements"
|
||||
date: 2026-02-18
|
||||
summary: "Multi-column footer with social icons, improved icon rendering, and changelog section."
|
||||
version: "1.1.0"
|
||||
---
|
||||
|
||||
## What's New
|
||||
|
||||
- **Multi-column Footer** — New `columns` footer style with logo, tagline, and navigation
|
||||
- **Social Icons** — Site-wide social links rendered in the footer via `identity.social.links`
|
||||
- **Icon Rendering** — Robust SVG sizing strategy with `1em` default for inline icons
|
||||
|
||||
## Improvements
|
||||
|
||||
- Icons now self-size to `1em` by default, eliminating 0px collapse bugs
|
||||
- Footer branding supports configurable logo height and SVG scaling
|
||||
- Feature block icons bumped to larger size for better visual presence
|
||||
|
||||
## Content
|
||||
|
||||
- **Changelog Section** — New standalone section at `/changelog/` using the `date-title-summary` view
|
||||
Reference in new issue
Block a user