refactor(button): consolidate button styles into Button.astro

Extends Button.astro with a center prop, native <button> element support
(type, disabled, aria-describedby), harmonised padding (.65rem), and
transition. Removes global .button, .button-small, .button-light, and
.button-center rules from components.css, layout.css, and typography.css.
Converts all inline class="button" usages across Header, HomeHero,
HomeFinancialHelp, HomeServicesIntro, FormShell, TeamPage, CareersPage,
and FaqPage to the <Button> component. Updates three scoped style
selectors to :global() to reach the child component's elements.
This commit is contained in:
2026-06-25 20:59:02 -07:00
parent a3f666c974
commit c6202d2ac6
12 changed files with 56 additions and 30 deletions
+34 -11
View File
@@ -1,10 +1,14 @@
--- ---
interface Props { interface Props {
href: string; href?: string;
variant?: 'filled' | 'outlined' | 'light'; variant?: 'filled' | 'outlined' | 'light';
size?: 'default' | 'small'; size?: 'default' | 'small';
center?: boolean;
target?: '_blank' | '_self'; target?: '_blank' | '_self';
rel?: string; rel?: string;
type?: 'submit' | 'button' | 'reset';
disabled?: boolean;
'aria-describedby'?: string;
class?: string; class?: string;
} }
@@ -12,20 +16,28 @@ const {
href, href,
variant = 'filled', variant = 'filled',
size = 'default', size = 'default',
center = false,
target, target,
rel = target === '_blank' ? 'noopener noreferrer' : undefined, rel = target === '_blank' ? 'noopener noreferrer' : undefined,
type,
disabled,
'aria-describedby': ariaDescribedby,
class: className class: className
} = Astro.props; } = Astro.props;
const classes = [
'content-button',
`content-button--${variant}`,
{ 'content-button--small': size === 'small', 'content-button--center': center },
className
];
--- ---
<a {href ? (
class:list={['content-button', `content-button--${variant}`, { 'content-button--small': size === 'small' }, className]} <a class:list={classes} href={href} target={target} rel={rel}><slot /></a>
href={href} ) : (
target={target} <button class:list={classes} type={type} disabled={disabled} aria-describedby={ariaDescribedby}><slot /></button>
rel={rel} )}
>
<slot />
</a>
<style> <style>
.content-button { .content-button {
@@ -36,8 +48,9 @@ const {
display: inline-block; display: inline-block;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
padding: .8rem 1.2rem; padding: .65rem 1.2rem;
text-decoration: none; text-decoration: none;
transition: .3s linear all;
} }
.content-button:hover, .content-button:hover,
@@ -65,6 +78,16 @@ const {
.content-button--small { .content-button--small {
font-size: .9rem; font-size: .9rem;
padding: .5rem 1rem; }
.content-button--center {
margin-block: 2.5rem;
margin-inline-start: 50%;
translate: -50%;
}
button.content-button {
cursor: pointer;
font: inherit;
} }
</style> </style>
+2 -1
View File
@@ -1,4 +1,5 @@
--- ---
import Button from './Button.astro';
const { title = 'Schedule Your Free Consultation', showBackground = false } = Astro.props; const { title = 'Schedule Your Free Consultation', showBackground = false } = Astro.props;
--- ---
<section class:list={['form-section', { 'form-section-background': showBackground }]} aria-labelledby="form-title"> <section class:list={['form-section', { 'form-section-background': showBackground }]} aria-labelledby="form-title">
@@ -12,7 +13,7 @@ const { title = 'Schedule Your Free Consultation', showBackground = false } = As
<label>Phone<input type="tel" name="phone" autocomplete="tel" /></label> <label>Phone<input type="tel" name="phone" autocomplete="tel" /></label>
<label>Service of interest<select name="service"><option>ABA Therapy</option><option>Autism Evaluation</option><option>Learner Social Club</option><option>Other</option></select></label> <label>Service of interest<select name="service"><option>ABA Therapy</option><option>Autism Evaluation</option><option>Learner Social Club</option><option>Other</option></select></label>
<label>How can we help?<textarea name="message" rows="5"></textarea></label> <label>How can we help?<textarea name="message" rows="5"></textarea></label>
<button class="button" type="submit" disabled aria-describedby="form-note">Submit</button> <Button type="submit" disabled aria-describedby="form-note">Submit</Button>
<p id="form-note" class="form-note">Online submission is not yet connected. Please call (480) 687-7099.</p> <p id="form-note" class="form-note">Online submission is not yet connected. Please call (480) 687-7099.</p>
</form> </form>
</div> </div>
+3 -2
View File
@@ -1,4 +1,5 @@
--- ---
import Button from './Button.astro';
import LanguageSwitcher from './LanguageSwitcher.astro'; import LanguageSwitcher from './LanguageSwitcher.astro';
import MainNav from './MainNav.astro'; import MainNav from './MainNav.astro';
import MobileNav from './MobileNav.astro'; import MobileNav from './MobileNav.astro';
@@ -21,7 +22,7 @@ const utility = lang === 'es'
<MainNav lang={lang} /> <MainNav lang={lang} />
<MobileNav lang={lang} /> <MobileNav lang={lang} />
<LanguageSwitcher /> <LanguageSwitcher />
<a class="button button-small" href="/tour">Tour AIA</a> <Button href="/tour" size="small">Tour AIA</Button>
</div> </div>
</header> </header>
@@ -33,7 +34,7 @@ const utility = lang === 'es'
.header-inner { align-items: center; display: flex; gap: 1.4rem; min-height: 110px; } .header-inner { align-items: center; display: flex; gap: 1.4rem; min-height: 110px; }
.brand img { width: 150px; } .brand img { width: 150px; }
@media (max-width: 950px) { @media (max-width: 950px) {
.header-inner > .button { display: none; } .header-inner > :global(.content-button) { display: none; }
} }
@media (max-width: 760px) { @media (max-width: 760px) {
.utility-inner { justify-content: center; } .utility-inner { justify-content: center; }
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
import type { FinancialHelpSection } from '../../types/home-sections'; import type { FinancialHelpSection } from '../../types/home-sections';
interface Props { section: FinancialHelpSection } interface Props { section: FinancialHelpSection }
const { section } = Astro.props; const { section } = Astro.props;
@@ -7,6 +8,6 @@ const { section } = Astro.props;
<div class="container"> <div class="container">
<h2>{section.heading}</h2> <h2>{section.heading}</h2>
<p>{section.body}</p> <p>{section.body}</p>
<a class="button" href={section.cta.href}>{section.cta.label}</a> <Button href={section.cta.href}>{section.cta.label}</Button>
</div> </div>
</section> </section>
+2 -1
View File
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
import type { HeroSection } from '../../types/home-sections'; import type { HeroSection } from '../../types/home-sections';
interface Props { section: HeroSection } interface Props { section: HeroSection }
const { section } = Astro.props; const { section } = Astro.props;
@@ -9,7 +10,7 @@ const { section } = Astro.props;
<p class="eyebrow">{section.eyebrow}</p> <p class="eyebrow">{section.eyebrow}</p>
<h1 set:html={section.heading} /> <h1 set:html={section.heading} />
<p>{section.body}</p> <p>{section.body}</p>
<a class="button" href={section.cta.href}>{section.cta.label}</a> <Button href={section.cta.href}>{section.cta.label}</Button>
</div> </div>
<img src={`/assets/images/${section.image}`} alt={section.imageAlt} loading="eager" /> <img src={`/assets/images/${section.image}`} alt={section.imageAlt} loading="eager" />
</div> </div>
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
import type { ServicesIntroSection } from '../../types/home-sections'; import type { ServicesIntroSection } from '../../types/home-sections';
interface Props { section: ServicesIntroSection } interface Props { section: ServicesIntroSection }
const { section } = Astro.props; const { section } = Astro.props;
@@ -31,7 +32,7 @@ const { section } = Astro.props;
<div> <div>
<h2 class="no-balance">{section.commitmentsHeading}</h2> <h2 class="no-balance">{section.commitmentsHeading}</h2>
<ul class="source-list two-column-list">{section.commitments.map((item) => <li>{item}</li>)}</ul> <ul class="source-list two-column-list">{section.commitments.map((item) => <li>{item}</li>)}</ul>
<a class="button" href={section.commitmentsCta.href}>{section.commitmentsCta.label}</a> <Button href={section.commitmentsCta.href}>{section.commitmentsCta.label}</Button>
</div> </div>
<img class="gear-photo gear-photo-right" src={`/assets/images/${section.commitmentsImage}`} alt={section.commitmentsImageAlt} /> <img class="gear-photo gear-photo-right" src={`/assets/images/${section.commitmentsImage}`} alt={section.commitmentsImageAlt} />
</div> </div>
+4 -3
View File
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
const indeedUrl = 'https://www.indeed.com/cmp/Arizona-Institute-For-Autism/jobs'; const indeedUrl = 'https://www.indeed.com/cmp/Arizona-Institute-For-Autism/jobs';
const benefits = [ const benefits = [
@@ -41,7 +42,7 @@ const careerCards = [
<h2>Join the AIA Team</h2> <h2>Join the AIA Team</h2>
<p>Apply to join the Arizona Institute for Autism (AIA) team today. We are on a mission to improve special education and strengthen communities throughout Arizona.</p> <p>Apply to join the Arizona Institute for Autism (AIA) team today. We are on a mission to improve special education and strengthen communities throughout Arizona.</p>
<p>Our talented and passionate employees are a critical piece to the high-quality Autism services we provide along with our commitment to behavioral health, school solutions, and community outreach.</p> <p>Our talented and passionate employees are a critical piece to the high-quality Autism services we provide along with our commitment to behavioral health, school solutions, and community outreach.</p>
<a class="button button-center" href={indeedUrl} target="_blank" rel="noopener noreferrer">View Open Positions</a> <Button href={indeedUrl} target="_blank" center>View Open Positions</Button>
</section> </section>
<!-- Our Benefits --> <!-- Our Benefits -->
@@ -129,7 +130,7 @@ const careerCards = [
<img src="/assets/images/logo-BACB.png" alt="BACB logo" loading="lazy" /> <img src="/assets/images/logo-BACB.png" alt="BACB logo" loading="lazy" />
</div> </div>
</div> </div>
<a class="button button-center" href={indeedUrl} target="_blank" rel="noopener noreferrer">View Open Positions</a> <Button href={indeedUrl} target="_blank" center>View Open Positions</Button>
</div> </div>
</section> </section>
@@ -175,7 +176,7 @@ const careerCards = [
</div> </div>
))} ))}
</div> </div>
<a class="button button-center" href={indeedUrl} target="_blank" rel="noopener noreferrer">View Open Positions</a> <Button href={indeedUrl} target="_blank" center>View Open Positions</Button>
</div> </div>
</section> </section>
+3 -2
View File
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
--- ---
<article class="faq-page"> <article class="faq-page">
<div class="faq-source container source-page"> <div class="faq-source container source-page">
@@ -48,7 +49,7 @@
<div class="container-narrow"> <div class="container-narrow">
<h2>Need Support in Getting an Autism Diagnosis?</h2> <h2>Need Support in Getting an Autism Diagnosis?</h2>
<p>To meet diagnostic criteria for ASD, a child must have persistent deficits in each of three areas of social communication and interaction plus at least two of four types of restricted repetitive behaviors. Consult with a Client Advocate today to receive individual and family support!</p> <p>To meet diagnostic criteria for ASD, a child must have persistent deficits in each of three areas of social communication and interaction plus at least two of four types of restricted repetitive behaviors. Consult with a Client Advocate today to receive individual and family support!</p>
<a class="button button-center" href="/client-consultation">Request an Appointment</a> <Button href="/client-consultation" center>Request an Appointment</Button>
</div> </div>
</section> </section>
</article> </article>
@@ -583,7 +584,7 @@
margin-bottom: .75rem; margin-bottom: .75rem;
} }
.faq-cta-secondary .button { .faq-cta-secondary :global(.content-button) {
margin-top: 1.5rem; margin-top: 1.5rem;
} }
+3 -2
View File
@@ -1,4 +1,5 @@
--- ---
import Button from '../Button.astro';
const groups = [ const groups = [
{ {
title: 'Board Certified Behavioral Analysts & Psychologists', title: 'Board Certified Behavioral Analysts & Psychologists',
@@ -68,7 +69,7 @@ const groups = [
<h2>Employment Opportunities</h2> <h2>Employment Opportunities</h2>
<p>Apply online to join the AIA team! At the Arizona Institute for Autism (AIA) we are on a mission to improve special education and strengthen communities throughout Arizona.</p> <p>Apply online to join the AIA team! At the Arizona Institute for Autism (AIA) we are on a mission to improve special education and strengthen communities throughout Arizona.</p>
<p>Our talented and passionate employees are a critical piece to the high-quality ABA therapy we provide along with our commitment to behavioral health, school solutions, and community outreach. For questions regarding open positions, please contact us at <a href="mailto:hr@azinstitute4autism.com">hr@azinstitute4autism.com</a>.</p> <p>Our talented and passionate employees are a critical piece to the high-quality ABA therapy we provide along with our commitment to behavioral health, school solutions, and community outreach. For questions regarding open positions, please contact us at <a href="mailto:hr@azinstitute4autism.com">hr@azinstitute4autism.com</a>.</p>
<a class="button" href="/careers">View Open Positions</a> <Button href="/careers">View Open Positions</Button>
</div> </div>
</section> </section>
</article> </article>
@@ -87,7 +88,7 @@ const groups = [
.team-member h3 { font-family: var(--font-body); font-size: .8rem; margin-bottom: 0; } .team-member h3 { font-family: var(--font-body); font-size: .8rem; margin-bottom: 0; }
.team-member p { font-size: .85rem; margin: 0; } .team-member p { font-size: .85rem; margin: 0; }
.team-careers { padding-block: 5rem; } .team-careers { padding-block: 5rem; }
.team-careers .button { margin-left: 50%; margin-top: 4rem; translate: -50%; } .team-careers :global(.content-button) { margin-left: 50%; margin-top: 4rem; translate: -50%; }
@media (max-width: 950px) { @media (max-width: 950px) {
.team-member { flex-basis: min(100%, 227px); } .team-member { flex-basis: min(100%, 227px); }
} }
-4
View File
@@ -1,7 +1,3 @@
.button { background: var(--color-accent); border: 2px solid var(--color-accent); border-radius: 4px; color: var(--color-primary); display: inline-block; padding: .65rem 1.2rem; text-decoration: none; transition: .3s linear all; }
.button:hover { background: transparent; border-color: var(--color-accent-strong); color: var(--color-primary); }
.button-small { font-size: .9rem; }
.button-light { background: white; color: var(--color-primary-dark); }
.card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; } .card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-md); overflow: hidden; }
.card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; } .card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; }
.card-body { padding: var(--space-lg); } .card-body { padding: var(--space-lg); }
-1
View File
@@ -9,7 +9,6 @@ img { display: block; height: auto; max-width: 100%; }
.section-tint, .page-header { background: var(--color-tint); } .section-tint, .page-header { background: var(--color-tint); }
.section-heading { margin-bottom: var(--space-lg); max-width: 700px; } .section-heading { margin-bottom: var(--space-lg); max-width: 700px; }
.split { align-items: center; display: flex; gap: var(--space-lg); justify-content: space-between; } .split { align-items: center; display: flex; gap: var(--space-lg); justify-content: space-between; }
.button-center { margin-block: 2.5rem; margin-inline-start: 50%; translate: -50%; }
.card-grid { display: grid; gap: var(--space-lg); grid-template-columns: repeat(3, minmax(0, 1fr)); } .card-grid { display: grid; gap: var(--space-lg); grid-template-columns: repeat(3, minmax(0, 1fr)); }
.skip-link { background: white; left: 1rem; padding: .75rem; position: fixed; top: -10rem; z-index: 100; } .skip-link { background: white; left: 1rem; padding: .75rem; position: fixed; top: -10rem; z-index: 100; }
.skip-link:focus { top: 1rem; } .skip-link:focus { top: 1rem; }
+1 -1
View File
@@ -11,7 +11,7 @@ h3 { font-size: clamp(1.8rem, 3.4vw, 2rem); }
h4 { font-size: clamp(1.5rem, 3vw, 1.8rem); } h4 { font-size: clamp(1.5rem, 3vw, 1.8rem); }
a, a:visited { color: var(--color-accent-strong); text-decoration: none; } a, a:visited { color: var(--color-accent-strong); text-decoration: none; }
a:hover, a:active { color: var(--color-accent); } a:hover, a:active { color: var(--color-accent); }
a.button { color: var(--color-primary) }
.eyebrow { .eyebrow {
margin: 0; margin: 0;