mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-19 12:16:13 +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 (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{iconSvg && (
|
{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">
|
<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: "w-5 h-5 lg:w-6 lg:h-6" }} />
|
<Icon svg={iconSvg} attributes={{ class: "flex items-center justify-center w-6 h-6 lg:w-8 lg:h-8" }} />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{item.name && (
|
{item.name && (
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ import { h } from "preact";
|
|||||||
* Icon component
|
* Icon component
|
||||||
* Renders an SVG icon from a raw SVG string passed from Hugo.
|
* Renders an SVG icon from a raw SVG string passed from Hugo.
|
||||||
* Decodes JSON-escaped sequences (\u003c) and HTML entities (<, ", ").
|
* 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 }) => {
|
export const Icon = ({ svg, attributes }) => {
|
||||||
if (!svg) return null;
|
if (!svg) return null;
|
||||||
@@ -24,9 +31,19 @@ export const Icon = ({ svg, attributes }) => {
|
|||||||
const hasWrapper = /<svg[\s>]/i.test(decoded);
|
const hasWrapper = /<svg[\s>]/i.test(decoded);
|
||||||
|
|
||||||
if (hasWrapper) {
|
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 = {
|
const wrapperProps = {
|
||||||
...attributes,
|
...attributes,
|
||||||
class: `flex items-center justify-center ${attributes?.class || ""}`.trim(),
|
class: attributes?.class || "",
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line lint/security/noDangerouslySetInnerHtml
|
// 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 := "" -}}
|
{{- $block_id := "" -}}
|
||||||
{{- $using_legacy := false -}}
|
{{- $using_legacy := false -}}
|
||||||
|
|
||||||
{{- if $config.block -}}
|
{{- if $config.style -}}
|
||||||
|
{{- $block_id = $config.style -}}
|
||||||
|
{{- else if $config.block -}}
|
||||||
{{- $block_id = $config.block -}}
|
{{- $block_id = $config.block -}}
|
||||||
{{- else if $config.blox -}}
|
{{- else if $config.blox -}}
|
||||||
{{- $block_id = $config.blox -}}
|
{{- $block_id = $config.blox -}}
|
||||||
|
|||||||
@@ -12,9 +12,83 @@ main:
|
|||||||
- name: Solutions
|
- name: Solutions
|
||||||
url: /#solutions
|
url: /#solutions
|
||||||
weight: 30
|
weight: 30
|
||||||
|
- name: Changelog
|
||||||
|
url: /changelog/
|
||||||
|
weight: 35
|
||||||
- name: Resources
|
- name: Resources
|
||||||
weight: 40
|
weight: 40
|
||||||
hasChildren: true
|
hasChildren: true
|
||||||
- parent: Resources
|
- parent: Resources
|
||||||
name: Blog
|
name: Blog
|
||||||
url: 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
|
# Schema.org type for structured data
|
||||||
type: organization # person | organization | local_business
|
type: organization # person | organization | local_business
|
||||||
# Short tagline displayed on your site
|
# Short tagline displayed on your site
|
||||||
tagline: ""
|
tagline: "The framework for Hugo."
|
||||||
# Site meta description for search engines and social sharing
|
# 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."
|
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 accounts (used for meta tags like Twitter Cards)
|
||||||
social:
|
social:
|
||||||
twitter: "MakeOwnable" # Twitter/X handle for Twitter Cards (without @)
|
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
|
# THEME
|
||||||
@@ -111,8 +121,15 @@ hugoblox:
|
|||||||
# ────────────────────────────────────────────────────────────────────────────
|
# ────────────────────────────────────────────────────────────────────────────
|
||||||
footer:
|
footer:
|
||||||
# Footer style variant
|
# 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
|
language_switcher: true
|
||||||
|
# Show social icons from identity.social.links
|
||||||
|
show_social: true
|
||||||
# Custom footer text (HTML supported)
|
# Custom footer text (HTML supported)
|
||||||
text: ""
|
text: ""
|
||||||
|
|
||||||
@@ -122,9 +139,9 @@ hugoblox:
|
|||||||
# ────────────────────────────────────────────────────────────────────────────
|
# ────────────────────────────────────────────────────────────────────────────
|
||||||
copyright:
|
copyright:
|
||||||
# Copyright notice - supports {year}, {name}, {license} placeholders
|
# Copyright notice - supports {year}, {name}, {license} placeholders
|
||||||
notice: "© {year} {name}. This work is licensed under {license}"
|
notice: "© {year} {name}."
|
||||||
license:
|
license:
|
||||||
type: cc # cc | custom
|
type: custom # cc | custom
|
||||||
allow_derivatives: false
|
allow_derivatives: false
|
||||||
share_alike: true
|
share_alike: true
|
||||||
allow_commercial: false
|
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