mirror of
https://github.com/tiennm99/HugoBlox-kit.git
synced 2026-10-13 04:14:41 +00:00
feat(css): co-locate block CSS with auto-discovery via Tailwind pipeline
Move block-specific CSS from centralized assets/css/blox/ to co-located style.css files within each block directory. The css.html partial now auto-discovers style.css files from bundled and community blocks and concatenates them into the Tailwind entry via resources.Concat, enabling full @apply support while avoiding VFS path resolution issues. Shared biography styles (avatar, ruby) are extracted to blox/shared/css/ and auto-included before per-block styles. Navbar CSS moves to components/ as it's a framework-level concern. The separate community CSS pipeline in site_head.html is removed — all block CSS now flows through a single Tailwind entry point.
This commit is contained in:
1 parent
13dde12ae0
commit
4fa40b91e2
10 files changed
+206
-318
No files matched your search
@@ -1,3 +0,0 @@
|
||||
@import "biography.css";
|
||||
@import "skills.css";
|
||||
@import "navbar.css";
|
||||
@@ -1,281 +0,0 @@
|
||||
.resume-biography {
|
||||
#profile {
|
||||
text-align: center;
|
||||
padding: 30px 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Custom avatar size on homepage - size controlled by template params */
|
||||
.avatar {
|
||||
width: auto;
|
||||
height: auto;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.network-icon {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#profile .network-icon {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.network-icon li {
|
||||
margin-right: 10px;
|
||||
|
||||
@media (max-width: 640px) {
|
||||
/* Min 48px Lighthouse tap targets on mobile */
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.network-icon li:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.network-icon li:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.big-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.ul-interests li {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.ul-edu li .description p.course {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.ul-edu li .description p.institution {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.network-icon .big-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
.bio-text {
|
||||
max-width: 680px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modern Biography Block Enhancements */
|
||||
.resume-biography-modern {
|
||||
/* Ensure proper stacking context for gradients and effects */
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* Ruby pronunciation styling - 2026+ modern design */
|
||||
.hb-ruby-name {
|
||||
ruby-position: over;
|
||||
display: ruby;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hb-ruby-name rt {
|
||||
/* Elegant, subdued annotation text */
|
||||
font-size: 0.45em;
|
||||
font-weight: var(--hb-font-weight-body-bold, 600);
|
||||
letter-spacing: 0.08em;
|
||||
line-height: 1.2;
|
||||
|
||||
/* Subtle gradient text for premium feel */
|
||||
background: linear-gradient(135deg, var(--color-gray-500) 0%, var(--color-gray-400) 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
|
||||
/* Smooth reveal animation */
|
||||
opacity: 0.85;
|
||||
transition:
|
||||
opacity 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dark .hb-ruby-name rt {
|
||||
background: linear-gradient(135deg, var(--color-gray-400) 0%, var(--color-gray-300) 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* Hover enhancement - subtle lift */
|
||||
.hb-ruby-name:hover rt {
|
||||
opacity: 1;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* CJK-optimized variant - larger annotation for CJK characters over Latin */
|
||||
.hb-ruby-name--cjk rt {
|
||||
font-size: 0.5em;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
/* Latin-optimized variant - smaller annotation for romanization over CJK */
|
||||
.hb-ruby-name--latin rt {
|
||||
font-size: 0.4em;
|
||||
font-weight: var(--hb-font-weight-body-bold, 600);
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
/* Accessibility: respect reduced motion */
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hb-ruby-name rt {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.hb-ruby-name:hover rt {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fallback styling for browsers without ruby support */
|
||||
@supports not (display: ruby) {
|
||||
.hb-ruby-name {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hb-ruby-name rt {
|
||||
display: block;
|
||||
font-size: 0.6em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Legacy class support */
|
||||
.ruby-modern {
|
||||
ruby-position: over;
|
||||
}
|
||||
|
||||
.ruby-modern rt {
|
||||
font-size: 0.7em;
|
||||
opacity: 0.8;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
/* Enhanced backdrop blur support */
|
||||
@supports (backdrop-filter: blur(10px)) {
|
||||
.resume-biography-modern [class*="backdrop-blur"] {
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
}
|
||||
|
||||
/* Smooth animations for all interactive elements */
|
||||
.resume-biography-modern * {
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
/* Enhanced focus states for accessibility */
|
||||
.resume-biography-modern a:focus-visible {
|
||||
outline: 2px solid var(--color-primary-500);
|
||||
outline-offset: 2px;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
/* Improved text selection styling */
|
||||
.resume-biography-modern ::selection {
|
||||
background-color: color-mix(in oklch, var(--color-primary-200) 30%, transparent);
|
||||
color: var(--color-primary-900);
|
||||
}
|
||||
|
||||
.dark .resume-biography-modern ::selection {
|
||||
background-color: color-mix(in oklch, var(--color-primary-800) 30%, transparent);
|
||||
color: var(--color-primary-100);
|
||||
}
|
||||
|
||||
/* Enhanced gradient text support */
|
||||
.resume-biography-modern .bg-clip-text {
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
/* Ensure text remains readable on fallback */
|
||||
@supports not (background-clip: text) {
|
||||
.resume-biography-modern .bg-clip-text {
|
||||
color: var(--color-neutral-900);
|
||||
}
|
||||
|
||||
.dark .resume-biography-modern .bg-clip-text {
|
||||
color: var(--color-neutral-100);
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
/* width and height controlled by template params */
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.avatar-emoji {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
/* override parent alpha */
|
||||
box-shadow:
|
||||
0 10px 20px rgb(0 0 0 / 4%),
|
||||
0 2px 6px rgb(0 0 0 / 4%),
|
||||
0 0 1px rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
||||
.dark .avatar-emoji {
|
||||
background-color: #000;
|
||||
box-shadow:
|
||||
0 10px 20px rgb(0 0 0 / 4%),
|
||||
0 2px 6px rgb(0 0 0 / 4%),
|
||||
0 0 1px rgb(255 255 255 / 96%);
|
||||
}
|
||||
|
||||
/* Biography Block */
|
||||
|
||||
.hbx-bg-gradient {
|
||||
position: relative;
|
||||
isolation: isolate;
|
||||
}
|
||||
|
||||
.hbx-bg-gradient::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
background-attachment: fixed;
|
||||
transition: opacity 0.5s ease-in-out;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
/* Light Mode Gradient */
|
||||
.hbx-bg-gradient::before {
|
||||
background-image:
|
||||
radial-gradient(at 20% 25%, hsla(212, 80%, 95%, 1) 0px, transparent 50%), radial-gradient(at 75% 30%, hsla(160, 80%, 95%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 25% 80%, hsla(280, 80%, 95%, 1) 0px, transparent 50%), radial-gradient(at 75% 85%, hsla(30, 80%, 95%, 1) 0px, transparent 50%);
|
||||
}
|
||||
|
||||
/* Dark Mode Gradient */
|
||||
.dark .hbx-bg-gradient::before {
|
||||
background-image:
|
||||
radial-gradient(at 20% 25%, hsla(212, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 30%, hsla(160, 35%, 15%, 1) 0px, transparent 50%),
|
||||
radial-gradient(at 25% 80%, hsla(280, 35%, 15%, 1) 0px, transparent 50%), radial-gradient(at 75% 85%, hsla(30, 35%, 15%, 1) 0px, transparent 50%);
|
||||
}
|
||||
@@ -10,3 +10,4 @@
|
||||
@import "author-notes.css";
|
||||
@import "glassmorphism.css";
|
||||
@import "cover.css";
|
||||
@import "navbar.css";
|
||||
File renamed without changes.
@@ -34,8 +34,10 @@
|
||||
|
||||
/* Hugo Blox module components */
|
||||
@import "components/all.css";
|
||||
@import "blox/all.css";
|
||||
@import "views/all.css";
|
||||
|
||||
/* Block-specific CSS is auto-discovered from co-located style.css files */
|
||||
/* See css.html partial for the discovery mechanism */
|
||||
@import "chroma.css";
|
||||
|
||||
/* Hugo Blox Search */
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
.resume-biography {
|
||||
#profile {
|
||||
text-align: center;
|
||||
padding: 30px 10px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.avatar {
|
||||
width: auto;
|
||||
height: auto;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.network-icon {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#profile .network-icon {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.network-icon li {
|
||||
margin-right: 10px;
|
||||
|
||||
@media (max-width: 640px) {
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.network-icon li:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.network-icon li:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
.big-icon {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.ul-interests li {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.ul-edu li .description p.course {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.ul-edu li .description p.institution {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.network-icon .big-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +1,14 @@
|
||||
/*************************************************
|
||||
* Hugo Blox: Skills
|
||||
**************************************************/
|
||||
|
||||
/* MOVED TO HTML */
|
||||
/* .skill-group-title { */
|
||||
/* display: inline-block; */
|
||||
/* margin-bottom: 15px; */
|
||||
/* padding-bottom: 5px; */
|
||||
/* border-bottom: 2px solid #c7c7c7; */
|
||||
/* font-size: 1rem; */
|
||||
/* line-height: 30px; */
|
||||
/* font-weight: 600; */
|
||||
/* text-transform: uppercase; */
|
||||
/* letter-spacing: 1px; */
|
||||
/* } */
|
||||
|
||||
.skills-content {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.skills-name {
|
||||
margin-bottom: 6px;
|
||||
/* color: #888; */ /* Inaccessible */
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* .dark .skills-name { */
|
||||
/* color: #eee; */
|
||||
/* } */
|
||||
|
||||
.skills-description {
|
||||
margin-bottom: 6px;
|
||||
font-size: 0.7rem;
|
||||
@@ -0,0 +1,122 @@
|
||||
/* Shared styles for biography-family blocks (resume-biography, resume-biography-3) */
|
||||
|
||||
.avatar-wrapper {
|
||||
position: relative;
|
||||
/* width and height controlled by template params */
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.avatar-emoji {
|
||||
position: absolute;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border-radius: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
font-size: 20px;
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
/* override parent alpha */
|
||||
box-shadow:
|
||||
0 10px 20px rgb(0 0 0 / 4%),
|
||||
0 2px 6px rgb(0 0 0 / 4%),
|
||||
0 0 1px rgb(0 0 0 / 4%);
|
||||
}
|
||||
|
||||
.dark .avatar-emoji {
|
||||
background-color: #000;
|
||||
box-shadow:
|
||||
0 10px 20px rgb(0 0 0 / 4%),
|
||||
0 2px 6px rgb(0 0 0 / 4%),
|
||||
0 0 1px rgb(255 255 255 / 96%);
|
||||
}
|
||||
|
||||
/* Ruby pronunciation styling */
|
||||
.hb-ruby-name {
|
||||
ruby-position: over;
|
||||
display: ruby;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.hb-ruby-name rt {
|
||||
font-size: 0.45em;
|
||||
font-weight: var(--hb-font-weight-body-bold, 600);
|
||||
letter-spacing: 0.08em;
|
||||
line-height: 1.2;
|
||||
|
||||
background: linear-gradient(135deg, var(--color-gray-500) 0%, var(--color-gray-400) 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
|
||||
opacity: 0.85;
|
||||
transition:
|
||||
opacity 0.3s ease,
|
||||
transform 0.3s ease;
|
||||
}
|
||||
|
||||
.dark .hb-ruby-name rt {
|
||||
background: linear-gradient(135deg, var(--color-gray-400) 0%, var(--color-gray-300) 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
.hb-ruby-name:hover rt {
|
||||
opacity: 1;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* CJK-optimized variant */
|
||||
.hb-ruby-name--cjk rt {
|
||||
font-size: 0.5em;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.12em;
|
||||
}
|
||||
|
||||
/* Latin-optimized variant */
|
||||
.hb-ruby-name--latin rt {
|
||||
font-size: 0.4em;
|
||||
font-weight: var(--hb-font-weight-body-bold, 600);
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.hb-ruby-name rt {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.hb-ruby-name:hover rt {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
@supports not (display: ruby) {
|
||||
.hb-ruby-name {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.hb-ruby-name rt {
|
||||
display: block;
|
||||
font-size: 0.6em;
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
}
|
||||
|
||||
/* Legacy class support */
|
||||
.ruby-modern {
|
||||
ruby-position: over;
|
||||
}
|
||||
|
||||
.ruby-modern rt {
|
||||
font-size: 0.7em;
|
||||
opacity: 0.8;
|
||||
letter-spacing: 0.05em;
|
||||
}
|
||||
|
||||
.bio-text {
|
||||
max-width: 680px;
|
||||
}
|
||||
@@ -3,8 +3,24 @@
|
||||
{{/* Build dynamic @source list and prepend it before main.css */}}
|
||||
{{ $dynamic_sources_str := partial "tailwind_sources.html" . }}
|
||||
{{ $dynamic_sources_res := resources.FromString "css/_dynamic_sources.css" $dynamic_sources_str }}
|
||||
|
||||
{{ $main_css := . }}
|
||||
{{ $entry := slice $dynamic_sources_res $main_css | resources.Concat "css/_entry.css" }}
|
||||
{{ $entry_parts := slice $dynamic_sources_res $main_css }}
|
||||
|
||||
{{/* Auto-discover co-located block CSS: shared utilities first, then per-block styles */}}
|
||||
{{ range resources.Match "css/hbx/blocks/shared/**/*.css" }}
|
||||
{{ $entry_parts = $entry_parts | append . }}
|
||||
{{ end }}
|
||||
{{ range resources.Match "css/hbx/blocks/**/style.css" }}
|
||||
{{ $entry_parts = $entry_parts | append . }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Community block CSS (mounted by templates into dist/community/blox/) */}}
|
||||
{{ range resources.Match "dist/community/blox/**/*.css" }}
|
||||
{{ $entry_parts = $entry_parts | append . }}
|
||||
{{ end }}
|
||||
|
||||
{{ $entry := $entry_parts | resources.Concat "css/_entry.css" }}
|
||||
{{ $opts := dict "minify" (not hugo.IsDevelopment) }}
|
||||
{{ with $entry | css.TailwindCSS $opts }}
|
||||
{{ if hugo.IsDevelopment }}
|
||||
|
||||
@@ -70,16 +70,6 @@
|
||||
{{ partial "css.html" . }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Load community blox styles */}}
|
||||
{{ $hb_community_styles := resources.Match "dist/community/blox/**.css" }}
|
||||
{{ with $hb_community_styles }}
|
||||
{{ $hb_community_styles = $hb_community_styles | resources.Concat "css/community-hugo-blox.css" }}
|
||||
{{- if hugo.IsProduction -}}
|
||||
{{- $hb_community_styles = $hb_community_styles | minify | fingerprint "sha256" -}}
|
||||
{{- end -}}
|
||||
<link href="{{ $hb_community_styles.RelPermalink }}" rel="stylesheet" />
|
||||
{{ end }}
|
||||
|
||||
{{ if fileExists "assets/css/custom.css" }}
|
||||
{{ $styles := resources.Get "css/custom.css" | minify | fingerprint "sha256" }}
|
||||
<link href="{{ $styles.RelPermalink }}" rel="stylesheet" />
|
||||
|
||||
Reference in new issue
Block a user