feat: add contact form and about page accordion feature

This commit is contained in:
Derek L. Seitz 2025-08-15 21:47:21 -05:00
parent ec151db8aa
commit 145e5f0a3f
4 changed files with 249 additions and 155 deletions

View File

@ -1,5 +1,8 @@
{ {
"cSpell.words": [ "cSpell.words": [
"wireframing" "wireframing"
],
"cSpell.ignoreWords": [
"Westfield"
] ]
} }

View File

@ -3,47 +3,35 @@ layout: base.njk
title: "About Derek" title: "About Derek"
stylesheet: /styles/about.css stylesheet: /styles/about.css
isLandingPage: false isLandingPage: false
pageScripts: "/scripts/contact-form.js" pageScripts:
- "/scripts/contact-form.js"
- "/scripts/accordion.js"
--- ---
<!-- TODO
FUTURE IMPROVEMENT: Convert the three headered paragraphs in this About section
into interactive accordion-style cards.
- Only the headers of each card will be visible initially.
- When a user clicks or taps a header (supporting both desktop and mobile),
the corresponding paragraph content will expand below that header.
- This interaction will align with the style established on the landing page,
where similar cards reveal content on hover (desktop) or tap (mobile).
- Add an introductory line at the end of the main paragraphs that says something
like: "Click on the cards below to learn more about what makes me who I am."
- This approach enhances consistency across the site, demonstrating the value of
interactive UI components and accessibility-focused design.
- Additionally, it subtly showcases a feature potential clients might want for
their own sites, reinforcing my development approach and attention to detail.
-->
<section class="about-section module" id="bio" role="region" aria-labelledby="about-heading"> <section class="about-section module" id="bio" role="region" aria-labelledby="about-heading">
<h1 id="about-heading">About Derek L. Seitz</h1> <h1 id="about-heading">Who <span class="i-am">I</span> Am</h1>
<p>Im a freelance developer dedicated to building clean, functional, and accessible web experiences. But beyond the code, Im someone driven by a deep sense of purpose and a commitment to creating digital solutions that <strong>genuinely</strong> serve people.</p> <p>Im a freelance developer dedicated to building clean, functional, and accessible web experiences. But beyond the code, Im someone driven by a deep sense of purpose and a commitment to creating digital solutions that <strong>genuinely</strong> serve people.</p>
<p>My approach is simple: solve real problems and build with integrity. I believe great websites dont just look good—they respect users time, adapt to diverse needs, and are built on a foundation of honesty and transparency. Thats why I communicate openly with clients, build trust through consistency, and deliver work that is both technically sound and thoughtfully designed.</p> <p>My approach is simple: solve real problems and build with integrity. I believe great websites dont just look good—they respect users time, adapt to diverse needs, and are built on a foundation of honesty and transparency. Thats why I communicate openly with clients, build trust through consistency, and deliver work that is both technically sound and thoughtfully designed.</p>
<p class="click">Click on the cards below to learn more about what makes me who I am.</p>
<div class="accessibility-value module"> <div class="accordion">
<h2>Accessibility is a Core Value</h2> <div class="accordion-item">
<h2 class="accordion-header">Accessibility is a Core Value</h2>
<p>Accessibility isn't just a buzzword for me—its a core value. From the start of any project, its built into my development process. I aim to align my work with the <a href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener">Web Content Accessibility Guidelines (WCAG) 2.1 Level AA</a>, and I continuously review my practices to improve usability. By championing accessibility-first development, I ensure my work reflects my values of inclusivity and mutual respect.</p> <div class="accordion-content">
</div> <p>Accessibility isn't just a buzzword for me—its a core value. From the start of any project, its built into my development process. I aim to align my work with the <a class="w3-acag21" href="https://www.w3.org/WAI/WCAG21/quickref/" target="_blank" rel="noopener">Web Content Accessibility Guidelines (WCAG) 2.1 Level AA</a>, and I continuously review my practices to improve usability. By championing accessibility-first development, I ensure my work reflects my values of inclusivity and mutual respect.</p>
<div class="drive module"> </div>
<h2>Driven by Curiosity and Empathy</h2> </div>
<div class="accordion-item">
<p>What truly drives me is an insatiable curiosity. I'm a critical thinker with a passion for understanding the world—whether through my work or my personal interests. From earning a recent Bachelors degree in Information Technology to conducting research for a masters program, Im always looking to grow. I believe this analytical mindset, paired with a strong sense of empathy, helps me not just understand a clients vision, but also the people and purpose behind it.</p> <h2 class="accordion-header">Driven by Curiosity and Empathy</h2>
</div> <div class="accordion-content">
<div class="partner module"> <p>What truly drives me is an insatiable curiosity. I'm a critical thinker with a passion for understanding the world—whether through my work or my personal interests. From earning a recent Bachelors degree in Information Technology to conducting research for a masters program, Im always looking to grow. I believe this analytical mindset, paired with a strong sense of empathy, helps me not just understand a clients vision, but also the people and purpose behind it.</p>
<h2>A Real Partner, Not an Agency</h2> </div>
</div>
<p>Im not a faceless agency. Instead, think of me as a collaborative partner. My work is built on shared success and the belief that transparency, empathy, and high standards can coexist. When you work with me, youre not just hiring a developer. Youre gaining a partner committed to bringing your unique vision to life: <strong>ethically</strong>, <strong>effectively</strong>, and <strong>accessibly</strong>.</p> <div class="accordion-item">
<h2 class="accordion-header">A Real Partner, Not an Agency</h2>
<div class="accordion-content">
<p>Im not a faceless agency. Instead, think of me as a collaborative partner. My work is built on shared success and the belief that transparency, empathy, and high standards can coexist. When you work with me, youre not just hiring a developer. Youre gaining a partner committed to bringing your unique vision to life: <strong>ethically</strong>, <strong>effectively</strong>, and <strong>accessibly</strong>.</p>
</div>
</div>
</div> </div>
</section> </section>
@ -56,38 +44,66 @@ pageScripts: "/scripts/contact-form.js"
--> -->
<section id="contact" class="contact-section module" role="region" aria-labelledby="contact-heading"> <section id="contact" class="contact-section module" role="region" aria-labelledby="contact-heading">
<h2 id="contact-heading">Don't Hesitate to Reach Out!</h2> <h2 id="contact-heading">Don't Hesitate to Reach Out!</h2>
<p>A website is often the most powerful marketing tool a business has, so it's normal to have questions. I'm here to answer those questions so you can have peace of mind in enhancing your web presence.</p> <p>A website is often the most powerful marketing tool a business has, so it's normal to have questions about the next steps! I'm here to answer those questions so you can have peace of mind in enhancing your web presence.</p>
<div class="contact-module module"> <div class="contact-module module">
<form id="contact-form" aria-labelledby="contact-form-heading"> <form id="contact-form" aria-labelledby="contact-form-heading">
<fieldset>
<legend id="contact-form-heading">Contact Me</legend>
<label for="name">Name:</label> <div class="form-sections">
<input type="text" id="name" name="name" placeholder="Your Name" required> <div class="contact-fields">
<fieldset class="name-field">
<legend>Contact Info</legend>
<div class="first-name">
<label for="first-name">First Name:<span class="req-ask">*</span></label>
<input type="text" id="first-name" name="first-name" placeholder="Ex. Sally" required>
</div>
<label for="email">Email:</label> <div class="last-name">
<input type="email" id="email" name="email" placeholder="you@example.com" required> <label for="last-name">Last Name:<span class="req-ask">*</span></label>
<input type="text" id="last-name" name="last-name" placeholder="Ex. Westfield" required>
</div>
<label for="phone">Phone Number:</label> <div class="organization">
<input type="tel" id="phone" name="phone" placeholder="(123) 456-7890" aria-describedby="phone-help"> <label for="organization">Organization:</label>
<small id="phone-help">Optional. Format: (123) 456-7890</small> <input type="text" id="organization" name="organization" placeholder="Optional">
</div>
<fieldset> <div class="email">
<legend>Preferred Contact Method:</legend> <label for="email">Email:<span class="req-ask">*</span></label>
<div> <input type="email" id="email" name="email" placeholder="Ex. user@domain.com" required>
<input type="radio" id="contact-email" name="contact-method" value="email" checked> </div>
<label for="contact-email">Email</label>
<input type="radio" id="contact-phone" name="contact-method" value="phone"> <div class="phone">
<label for="contact-phone">Phone</label> <label for="phone">Phone:<span class="req-ask">*</span></label>
</div> <input type="tel" id="phone" name="phone" placeholder="Ex. 111-333-4444" pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}" required>
</fieldset> </div>
<label for="message">Message:</label> <div class="preferred-method">
<textarea id="message" name="message" rows="5" placeholder="Your Message" required></textarea> <h3>Preferred Contact Method</h3>
<div class="radio-group">
<div class="email-radio">
<input type="radio" id="contact-email" name="contact-method" value="email" checked required>
<label for="contact-email">Email</label>
</div>
<div class="phone-radio">
<input type="radio" id="contact-phone" name="contact-method" value="phone" required>
<label for="contact-phone">Phone</label>
</div>
</div>
</div>
</fieldset>
</div>
<div class="message-submit">
<fieldset class="message-field">
<legend>Message</legend>
<label for="message">Questions or Feedback</label>
<textarea id="message" name="message" rows="15" placeholder="What questions or feedback do you have for me?" required></textarea>
</fieldset>
<button type="submit">Send Message</button>
</div>
</div>
<p class="form-note">* Required fields</p>
<button type="submit">Send Message</button>
</fieldset>
</form> </form>
</div> </div>
</section> </section>

14
src/scripts/accordion.js Normal file
View File

@ -0,0 +1,14 @@
document.addEventListener('DOMContentLoaded', (event) => {
const accordionHeaders = document.querySelectorAll('.accordion-header');
accordionHeaders.forEach(header => {
header.addEventListener('click', () => {
const content = header.nextElementSibling;
if (content.style.display === 'block') {
content.style.display = 'none';
} else {
content.style.display = 'block';
}
});
});
});

View File

@ -9,20 +9,25 @@ body {
max-width: 1000px; max-width: 1000px;
margin: 30px auto; margin: 30px auto;
padding: 0 20px; padding: 0 20px;
color: #495057; color: var(--text-color);
line-height: 1.6; line-height: 1.6;
} }
.about-section h1, .about-section h1,
.about-section h2 { .about-section h2 {
color: #495057; color: var(--text-color);
margin-bottom: 20px; margin-bottom: var(--margin-medium);
}
.i-am {
color: #ea7e0b;
font-weight: bold;
} }
.about-section h1 { .about-section h1 {
font-size: 2.5rem; font-size: 2.5rem;
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: var(--margin-medium);
} }
.about-section h2 { .about-section h2 {
@ -32,11 +37,18 @@ body {
.about-section p { .about-section p {
margin-bottom: 5px; margin-bottom: 5px;
font-size: 1.05rem; font-size: 1.05rem;
text-align: left; text-align: center;
}
.click {
font-weight: bold;
color:#ea7e0b;
margin-top: 20px;
text-align: center;
} }
.about-section a { .about-section a {
color: #2e97be; color: var(--primary-color);
text-decoration: underline; text-decoration: underline;
} }
@ -44,112 +56,161 @@ body {
text-decoration: none; text-decoration: none;
} }
/*? ↓ Contact Section Styles ↓ */ .accordion {
.contact-section {
max-width: 1200px;
margin: 80px auto;
padding: 0 20px;
color: #495057;
background-color: #d3e9f1;
}
.contact-section h2 {
font-size: 2rem;
margin: 20px 0px;
text-align: center;
}
.contact-section p {
text-align: center;
margin-bottom: 40px;
font-size: 1.1rem;
line-height: 1.5;
}
/*? ↓ Contact Form Styles ↓ */
#contact-form {
background-color: #ffffff;
border: 1px solid #dee2e6;
border-radius: 10px;
padding: 30px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
}
#contact-form fieldset {
border: none;
padding: 0;
}
#contact-form legend {
font-size: 1.5rem;
font-weight: 600;
margin-bottom: 25px;
color: #2e97be;
text-align: center;
}
#contact-form label {
display: block;
margin-bottom: 8px;
margin-top: 20px; margin-top: 20px;
}
.accordion-item {
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
overflow: hidden;
}
.accordion-header {
background-color: #f7f7f7;
padding: 15px;
cursor: pointer;
border-bottom: 1px solid #ddd;
}
.accordion-content {
display: none; /* Hide content by default */
padding: 15px;
background-color: #fff;
}
.w3-acag21 {
color: #ea7e0b;
}
/*? ↓ Contact Section Styles ↓ */
/* Base styles */
.contact-module {
max-width: 1000px;
margin: 2rem auto;
padding: 2rem;
background-color: #f9f9f9;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.05);
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #333;
}
form {
display: flex;
flex-direction: column;
}
/* Flex layout for side-by-side fields */
.form-sections {
display: flex;
gap: 2rem;
flex-wrap: wrap;
align-items: flex-start;
}
.contact-fields,
.message-submit {
flex: 1;
min-width: 320px;
}
/* Fieldset styling */
fieldset {
border: 1px solid #ccc;
border-radius: 6px;
padding: 1.5rem;
margin-bottom: 1.5rem;
}
legend {
padding: 0 0.5rem;
font-weight: bold;
font-size: 1.1rem;
}
/* Input groups */
.contact-fields > div,
.message-field {
margin-bottom: 1rem;
}
label {
display: block;
margin-bottom: 0.4rem;
font-weight: 500; font-weight: 500;
} }
#contact-form input, input[type="text"],
#contact-form textarea { input[type="email"],
input[type="tel"],
textarea {
width: 100%; width: 100%;
padding: 12px; padding: 0.6rem;
margin-top: 5px; border: 1px solid #ccc;
border: 1px solid #dee2e6; border-radius: 4px;
border-radius: 8px; font-size: 0.95rem;
box-sizing: border-box; transition: border-color 0.3s ease;
font-size: 1rem;
background-color: #f8f9fa;
} }
#contact-form input:focus, input:focus,
#contact-form textarea:focus { textarea:focus {
border-color: #2e97be; border-color: #007acc;
outline: none; outline: none;
background-color: #fff;
box-shadow: 0 0 0 3px rgba(46, 151, 190, 0.2);
} }
#contact-form small { /* Required asterisk */
display: block; .req-ask {
margin-top: 5px; color: red;
color: #868e96; margin-left: 0.2rem;
font-size: 0.875rem;
} }
#contact-form .radio-group { /* Preferred method section */
.preferred-method {
margin-top: 1rem;
text-align: center;
}
.radio-group {
display: flex; display: flex;
gap: 20px; justify-content: center;
margin-top: 10px; gap: 1.5rem;
margin-top: 0.5rem;
} }
#contact-form .radio-group label { .radio-group label {
display: inline-block;
margin-top: 0;
font-weight: normal; font-weight: normal;
} }
#contact-form button[type="submit"] { /* Button */
margin-top: 30px; button[type="submit"] {
padding: 12px 25px; margin:20px 0px 20px 0px;
padding: 8px 25px;
background-color: #ea7e0b; background-color: #ea7e0b;
color: #fff; color: white;
border: none; border: none;
border-radius: 50px; border-radius: 50px;
font-weight: 600;
cursor: pointer;
transition: background-color 0.3s ease, box-shadow 0.3s ease;
font-size: 1rem; font-size: 1rem;
cursor: pointer;
transition: background-color 0.3s ease;
} }
#contact-form button[type="submit"]:hover { button[type="submit"]:hover {
background-color: #2781a5; background-color: #2e97be;
box-shadow: 0 4px 8px rgba(46, 151, 190, 0.2); }
/* Responsive tweaks */
@media (max-width: 768px) {
.form-sections {
flex-direction: column;
margin-left: auto;
margin-right: auto;
}
}
.form-note {
color: red;
font-size: 0.9rem;
text-align: left;
} }