Compare commits

...

1 Commits

Author SHA1 Message Date
DeCentN2Madness 4a6b8a20e5 feat(library): restore live-site intro copy above post listings
- add the two live intro paragraphs between the hero and article grid
- keep the library listing cards in the live two-column layout
- restore the 4:3 cropped article thumbnails and card spacing via library-scoped selectors
- avoid leaking the card-grid overrides into unrelated pages
- add likes/views from api to library article cards
2026-06-11 19:08:48 -07:00
4 changed files with 76 additions and 30 deletions
+21 -1
View File
@@ -1,4 +1,5 @@
--- ---
import LikeViewCounter from './LikeViewCounter.astro';
const { post, prefix = '' } = Astro.props; const { post, prefix = '' } = Astro.props;
const href = `${prefix}/library/${post.data.slug}`.replace('//', '/'); const href = `${prefix}/library/${post.data.slug}`.replace('//', '/');
const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More'; const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد' }[post.data.lang] || 'Read More';
@@ -9,12 +10,31 @@ const readMore = { en: 'Read More', es: 'Leer Más', ar: 'اقرأ المزيد'
<div class="blog-card-meta"><img src="/assets/images/rula-diab-avatar.jpg" alt="" /><p>Rula Diab, Clinical Director, M.Ed, BCBA, LBA<br /><time datetime={post.data.date.toISOString()}>{post.data.date.toLocaleDateString(post.data.lang, { day: 'numeric', month: 'long', year: 'numeric' })}</time></p></div> <div class="blog-card-meta"><img src="/assets/images/rula-diab-avatar.jpg" alt="" /><p>Rula Diab, Clinical Director, M.Ed, BCBA, LBA<br /><time datetime={post.data.date.toISOString()}>{post.data.date.toLocaleDateString(post.data.lang, { day: 'numeric', month: 'long', year: 'numeric' })}</time></p></div>
<h3><a href={href}>{post.data.title}</a></h3> <h3><a href={href}>{post.data.title}</a></h3>
<p>{post.data.description}</p> <p>{post.data.description}</p>
<div class="blog-card-footer" style="align-items:center;display:flex;justify-content:space-between;gap:var(--space-lg);margin-top:auto;">
<a class="text-link" href={href}>{readMore}</a> <a class="text-link" href={href}>{readMore}</a>
<LikeViewCounter slug={post.data.slug} />
</div>
</div> </div>
</article> </article>
<style> <style>
.blog-card-meta { align-items: center; display: flex; font-size: .78rem; gap: .75rem; } .blog-card-meta { align-items: center; display: flex; font-size: .78rem; gap: .75rem; }
.blog-card-meta img { aspect-ratio: 1; border-radius: 50%; height: 42px; width: 42px; } .blog-card-meta img { aspect-ratio: 1; border-radius: 50%; height: 42px; width: 42px; }
.blog-card h3 { font-size: 1.35rem; } .blog-card { background: white; border: 0; border-radius: 4px; box-shadow: rgba(54, 48, 48, 0.28) 0 0 12px 0; display: flex; margin-bottom: 40px; overflow: hidden; }
.blog-card > a { flex: 0 0 232px; display: block; margin: .75rem; }
.blog-card > a img { aspect-ratio: auto; display: block; height: 100%; object-fit: cover; width: 100%; }
.blog-card .card-body { display: flex; flex: 1; flex-direction: column; gap: 0; padding: 20px; }
.blog-card .card-body h3 { font-family: var(--font-body); }
.blog-card-footer { align-items: center; display: flex; justify-content: space-between; gap: var(--space-lg); margin-top: auto; }
:global(.blog-card .like-view-counter) { border-top: 0; justify-content: space-between; margin-block: 0; padding-top: 0; width: auto; }
.blog-card h3 { font-size: 1.35rem; margin-bottom: 1rem; }
.blog-card p { margin-bottom: 1rem; }
.blog-card .text-link { margin: 0; }
@media (max-width: 760px) {
.blog-card { flex-direction: column; }
.blog-card > a { flex-basis: auto; }
.blog-card > a img { height: auto; aspect-ratio: 4 / 3; }
.blog-card-footer { align-items: flex-start; flex-direction: column; }
}
</style> </style>
+24 -7
View File
@@ -1,11 +1,16 @@
--- ---
const { slug } = Astro.props; const { slug } = Astro.props;
--- ---
<div class="like-view-counter likes-views" data-counter> <div class="like-view-counter" data-counter>
<span aria-label="Article views"><span class="view-count" data-views>0</span> views</span>
<span class="like-group">
<span class="like-count" data-likes>—</span>
<button class="like-button" type="button" data-like data-slug={slug} aria-label="Like this article" aria-pressed="false"> <button class="like-button" type="button" data-like data-slug={slug} aria-label="Like this article" aria-pressed="false">
<span aria-hidden="true">♡</span> <span class="like-count" data-likes>—</span> <svg aria-hidden="true" viewBox="0 0 12 10" width="20" height="20" focusable="false" class="like-icon">
<path d="m1 4.4c-1-4 2.5-5 4.5-2.5l.5 .6l.5-.6c2-2.5 6-1.5 4.5 2.5q-1 3-5 5q-4-2-5-5z"></path>
</svg>
</button> </button>
<span aria-label="Article views">Views: <span class="view-count" data-views>—</span></span> </span>
</div> </div>
<script> <script>
const apiBase = import.meta.env.PUBLIC_AIA_API_BASE || 'https://api.azinstitute4autism.com'; const apiBase = import.meta.env.PUBLIC_AIA_API_BASE || 'https://api.azinstitute4autism.com';
@@ -44,6 +49,14 @@ const { slug } = Astro.props;
const views = counter.querySelector<HTMLElement>('[data-views]'); const views = counter.querySelector<HTMLElement>('[data-views]');
if (!button || !slug) return; if (!button || !slug) return;
const isLocalhost = ['localhost', '127.0.0.1', '::1'].includes(window.location.hostname);
if (isLocalhost) {
counter.dataset.unavailable = 'true';
if (likes) likes.textContent = '0';
if (views) views.textContent = '0';
return;
}
const cookieName = `liked_${slug}`; const cookieName = `liked_${slug}`;
const renderLiked = (liked: boolean) => { const renderLiked = (liked: boolean) => {
button.classList.toggle('liked', liked); button.classList.toggle('liked', liked);
@@ -66,7 +79,7 @@ const { slug } = Astro.props;
} catch { } catch {
counter.dataset.unavailable = 'true'; counter.dataset.unavailable = 'true';
if (likes) likes.textContent = '0'; if (likes) likes.textContent = '0';
if (views) views.textContent = ''; if (views) views.textContent = '0';
} }
button.addEventListener('click', async () => { button.addEventListener('click', async () => {
@@ -98,8 +111,12 @@ const { slug } = Astro.props;
</script> </script>
<style> <style>
.like-view-counter { align-items: center; border-top: 1px solid var(--color-border); display: flex; gap: var(--space-lg); margin-block: var(--space-xl); padding-top: var(--space-md); } .like-view-counter { align-items: center; border-top: 1px solid var(--color-border); display: flex; gap: var(--space-lg); font-size: .75rem; margin-block: var(--space-xl); padding-top: var(--space-md); }
.like-view-counter button { background: white; border: 1px solid var(--color-border); border-radius: 999px; padding: .6rem 1rem; } .like-view-counter { font-size: .8rem; }
.like-view-counter button.liked { background: var(--color-primary-dark); border-color: var(--color-primary-dark); color: white; } .like-group { align-items: center; display: inline-flex; gap: .35rem; }
.like-view-counter button { align-items: center; background: white; border: none; color: inherit; display: inline-flex; gap: 0; padding: 0; }
.like-view-counter .like-count { color: var(--color-text); min-width: 1ch; }
.like-view-counter .like-icon { fill: none; flex: 0 0 auto; stroke: #d92d20; stroke-linecap: round; stroke-linejoin: round; stroke-width: 1.6; }
.like-view-counter button.liked .like-icon { fill: #d92d20; stroke: #d92d20; }
.like-view-counter button:disabled { cursor: wait; opacity: .65; } .like-view-counter button:disabled { cursor: wait; opacity: .65; }
</style> </style>
+20 -18
View File
@@ -1,33 +1,35 @@
--- ---
import BaseLayout from './BaseLayout.astro'; import BaseLayout from './BaseLayout.astro';
import PageHero from '../components/PageHero.astro'; import PageHero from '../components/PageHero.astro';
const { title, description, lang = 'en' } = Astro.props; const { title, description, intro = [], lang = 'en' } = Astro.props;
const languagePrefix = lang === 'en' ? '' : `/${lang}`; const languagePrefix = lang === 'en' ? '' : `/${lang}`;
const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`; const canonical = `https://www.azinstitute4autism.com${languagePrefix}/library`;
--- ---
<BaseLayout title={title} description={description} canonical={canonical} lang={lang}> <BaseLayout title={title} description={description} canonical={canonical} lang={lang}>
<PageHero title={title} image="/assets/images/hero-library-index.webp" eyebrow="Welcome to" constrain /> <PageHero title={title} image="/assets/images/hero-library-index.webp" eyebrow="Welcome to" constrain />
<section class="library-intro"><div class="container"><h2>Library</h2><p>{description}</p></div></section> <section class="library-intro">
<div class="container">
<h2>Library</h2>
{intro.length ? intro.map((paragraph) => <p>{paragraph}</p>) : <p>{description}</p>}
</div>
</section>
<div class="container section library-layout"><slot /></div> <div class="container section library-layout"><slot /></div>
</BaseLayout> </BaseLayout>
<style> <style>
.library-intro { background: var(--color-primary); color: white; padding-block: 3rem; } :global(.library-intro) { background: var(--color-primary); color: white; padding-block: 3rem; }
.library-intro h2 { color: white; } :global(.library-intro h2) { color: white; }
.library-layout { align-items: start; display: grid; gap: 3rem; grid-template-columns: 1fr 240px; } :global(.library-layout) { align-items: start; display: grid; gap: 3rem; grid-template-columns: 1fr 240px; }
.library-sidebar { position: sticky; top: 1rem; } :global(.library-sidebar) { position: sticky; top: 1rem; }
.library-sidebar label { display: block; font-weight: 700; margin-bottom: .4rem; } :global(.library-sidebar label) { display: block; font-weight: 700; margin-bottom: .4rem; }
.library-sidebar input { border: 1px solid var(--color-border); border-radius: 4px; font: inherit; padding: .7rem; width: 100%; } :global(.library-sidebar input) { border: 1px solid var(--color-border); border-radius: 4px; font: inherit; padding: .7rem; width: 100%; }
.library-sidebar h2 { font-size: 1.1rem; margin-top: 2rem; } :global(.library-sidebar h2) { font-size: 1.1rem; margin-top: 2rem; }
.library-sidebar ul { list-style: none; padding: 0; } :global(.library-sidebar ul) { list-style: none; padding: 0; }
.library-sidebar li { border-bottom: 1px solid var(--color-border); padding-block: .65rem; } :global(.library-sidebar li) { border-bottom: 1px solid var(--color-border); padding-block: .65rem; }
.library-sidebar a { color: var(--color-primary); font-size: .9rem; } :global(.library-sidebar a) { color: var(--color-primary); font-size: .9rem; }
.blog-list { display: grid; gap: 2rem; } :global(.blog-list) { display: block; }
.blog-list .blog-card { box-shadow: none; display: grid; grid-template-columns: 240px 1fr; }
.blog-list .blog-card > a img { aspect-ratio: 4 / 3; height: 100%; }
@media (max-width: 760px) { @media (max-width: 760px) {
.library-layout { grid-template-columns: 1fr; } :global(.library-layout) { grid-template-columns: 1fr; }
.library-sidebar { position: static; } :global(.library-sidebar) { position: static; }
.blog-list .blog-card { grid-template-columns: 1fr; }
} }
</style> </style>
+8 -1
View File
@@ -5,7 +5,14 @@ import BlogCard from '../../components/BlogCard.astro';
const posts = (await getCollection('blog', ({ data }) => data.lang === 'en' && !data.draft)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf()); const posts = (await getCollection('blog', ({ data }) => data.lang === 'en' && !data.draft)).sort((a, b) => b.data.date.valueOf() - a.data.date.valueOf());
const popular = posts.slice(0, 5); const popular = posts.slice(0, 5);
--- ---
<BlogIndexLayout title="The Library at AZ Institute for Autism" description="Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, community events, success stories, and expert guidance."> <BlogIndexLayout
title="The Library at AZ Institute for Autism"
description="Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, community events, success stories, and expert guidance."
intro={[
"Welcome to the Library at AIA, where we share valuable insights, strategies, and resources to support individuals with autism, their families, and professionals in the field. Our articles explore key topics in Applied Behavior Analysis (ABA) therapy, including teaching self-advocacy, proactive and reactive strategies, and innovative intervention techniques.",
"We also highlight community events, success stories, and expert guidance to foster understanding and empowerment. Whether you're a parent, caregiver, educator, or advocate, our goal is to provide meaningful content that helps children with autism reach their highest potential in a compassionate and supportive environment. Stay connected with us as we continue to share knowledge and celebrate progress!",
]}
>
<div class="blog-list">{posts.map((post) => <BlogCard post={post} />)}</div> <div class="blog-list">{posts.map((post) => <BlogCard post={post} />)}</div>
<aside class="library-sidebar"> <aside class="library-sidebar">
<label for="library-search">Search</label> <label for="library-search">Search</label>