Refactor features section to use flexible data and Icon components

Refactored the features section of the website to use externally-defined data alongside reusable Icon components. Now, tabs and feature blocks' content is dictated by passed-in props, improving the modularity and adaptability of the code. Individual SVG icons are also now handled by a single Icon component, simplifying the codebase and enhancing maintainability.
This commit is contained in:
Emil Gulamov 2024-03-22 04:43:19 +04:00
parent 2d8e7a38e6
commit 7821ef382a
2 changed files with 87 additions and 165 deletions

View file

@ -1,13 +1,24 @@
--- ---
// Import the necessary dependencies // Import the necessary dependencies
import { Image } from "astro:assets"; import { Image } from "astro:assets";
import featureImage from "../../../images/features-image.avif";
import IconBlock from "../../ui/blocks/IconBlock.astro"; import IconBlock from "../../ui/blocks/IconBlock.astro";
import Icon from "../../ui/icons/Icon.astro";
// Define the string variables `title` and `subTitle` for the main heading and sub-heading text interface Feature {
const title: string = "Meeting Industry Demands"; heading: string;
const subTitle: string = content: string;
"At ScrewFast, we tackle the unique challenges encountered in the hardware and construction sectors. From cutting-edge tools to expert services, we're dedicated to helping you overcome obstacles and achieve your goals."; svg: string;
}
interface Props {
title?: string;
subTitle?: string;
features?: Feature[];
src?: any;
alt?: string;
}
// Define props from Astro
const { title, subTitle, src, alt, features } = Astro.props;
--- ---
<section <section
@ -15,14 +26,18 @@ const subTitle: string =
> >
<!-- Block to display the feature image --> <!-- Block to display the feature image -->
<div class="relative mb-6 overflow-hidden md:mb-8"> <div class="relative mb-6 overflow-hidden md:mb-8">
<Image {
src={featureImage} src && alt && (
alt="ScrewFast products in floating boxes" <Image
class="h-full w-full object-cover object-center" src={src}
draggable={"false"} alt={alt}
format={"avif"} class="h-full w-full object-cover object-center"
loading={"eager"} draggable={"false"}
/> format={"avif"}
loading={"eager"}
/>
)
}
</div> </div>
<!-- Displaying the main content consisting of title, subtitle, and several `IconBlock` components --> <!-- Displaying the main content consisting of title, subtitle, and several `IconBlock` components -->
@ -36,12 +51,12 @@ const subTitle: string =
{title} {title}
</h2> </h2>
<!-- Rendering subtitle --> <!-- Rendering subtitle -->
{subTitle && {
<p subTitle && (
class="mt-2 text-pretty text-neutral-600 dark:text-neutral-400 md:mt-4" <p class="mt-2 text-pretty text-neutral-600 dark:text-neutral-400 md:mt-4">
> {subTitle}
{subTitle} </p>
</p> )
} }
</div> </div>
@ -49,69 +64,13 @@ const subTitle: string =
<div class="lg:col-span-2"> <div class="lg:col-span-2">
<div class="grid gap-8 sm:grid-cols-2 md:gap-12"> <div class="grid gap-8 sm:grid-cols-2 md:gap-12">
<!-- Injecting IconBlock components with different properties --> <!-- Injecting IconBlock components with different properties -->
<!-- IconBlock #1 --> { features &&
<IconBlock features.map((feature) => (
heading="Dedicated Teams" <IconBlock heading={feature.heading} content={feature.content}>
content="Benefit from our committed teams who ensure your success is personal. Count on expert guidance and exceptional results throughout your project journey." <Icon name={feature.svg} />
> </IconBlock>
<svg ))
class="mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]" }
height="48"
viewBox="0 -960 960 960"
width="48"
><path
d="m150-400 82-80-82-82-80 82 80 80Zm573-10 87-140 88 140H723Zm-243-70q-50 0-85-35t-35-85q0-51 35-85.5t85-34.5q51 0 85.5 34.5T600-600q0 50-34.5 85T480-480Zm.351-180Q455-660 437.5-642.851t-17.5 42.5Q420-575 437.351-557.5t43 17.5Q506-540 523-557.351t17-43Q540-626 522.851-643t-42.5-17ZM480-600ZM0-240v-53q0-39.464 42-63.232T150.398-380q12.158 0 23.38.5T196-377.273q-8 17.273-12 34.842-4 17.57-4 37.431v65H0Zm240 0v-65q0-65 66.5-105T480-450q108 0 174 40t66 105v65H240Zm570-140q67.5 0 108.75 23.768T960-293v53H780v-65q0-19.861-3.5-37.431Q773-360 765-377.273q11-1.727 22.171-2.227 11.172-.5 22.829-.5Zm-330.2-10Q400-390 350-366q-50 24-50 61v5h360v-6q0-36-49.5-60t-130.7-24Zm.2 90Z"
></path></svg
>
</IconBlock>
<!-- IconBlock #2 -->
<IconBlock
heading="Simplicity and Affordability"
content="Find easy-to-use, affordable solutions with ScrewFast's line of tools and equipment. Our products make procurement simple and keep projects within budget."
>
<svg
class="mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]"
height="48"
viewBox="0 -960 960 960"
width="48"
><path
d="m346-60-76-130-151-31 17-147-96-112 96-111-17-147 151-31 76-131 134 62 134-62 77 131 150 31-17 147 96 111-96 112 17 147-150 31-77 130-134-62-134 62Zm27-79 107-45 110 45 67-100 117-30-12-119 81-92-81-94 12-119-117-28-69-100-108 45-110-45-67 100-117 28 12 119-81 94 81 92-12 121 117 28 70 100Zm107-341Zm-43 133 227-225-45-41-182 180-95-99-46 45 141 140Z"
></path></svg
>
</IconBlock>
<!-- IconBlock #3 -->
<IconBlock
heading="Comprehensive Documentation"
content="Integrate with ease using ScrewFast's exhaustive guides and libraries. Achieve seamless product adoption with our full suite of documentation designed for your success."
>
<svg
class="mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]"
height="48"
viewBox="0 -960 960 960"
width="48"
><path
d="M343-420h225v-60H343v60Zm0-90h395v-60H343v60Zm0-90h395v-60H343v60Zm-83 400q-24 0-42-18t-18-42v-560q0-24 18-42t42-18h560q24 0 42 18t18 42v560q0 24-18 42t-42 18H260Zm0-60h560v-560H260v560ZM140-80q-24 0-42-18t-18-42v-620h60v620h620v60H140Zm120-740v560-560Z"
></path></svg
>
</IconBlock>
<!-- IconBlock #4 -->
<IconBlock
heading="User-Centric Design"
content="Experience the difference with ScrewFast's user-focused design — where functionality meets practicality for an enhanced work experience."
>
<svg
class="mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]"
height="48"
viewBox="0 -960 960 960"
width="48"
><path
d="M480-480q-51 0-85.5-34.5T360-600q0-50 34.5-85t85.5-35q50 0 85 35t35 85q0 51-35 85.5T480-480Zm-.351-60Q505-540 522.5-557.149t17.5-42.5Q540-625 522.649-642.5t-43-17.5Q454-660 437-642.649t-17 43Q420-574 437.149-557t42.5 17ZM240-240v-76q0-27 17.5-47.5T300-397q42-22 86.943-32.5 44.942-10.5 93-10.5Q528-440 573-429.5t87 32.5q25 13 42.5 33.5T720-316v76H240Zm240-140q-47.546 0-92.773 13T300-328v28h360v-28q-42-26-87.227-39-45.227-13-92.773-13Zm0-220Zm0 300h180-360 180ZM140-80q-24 0-42-18t-18-42v-172h60v172h172v60H140ZM80-648v-172q0-24 18-42t42-18h172v60H140v172H80ZM648-80v-60h172v-172h60v172q0 24-18 42t-42 18H648Zm172-568v-172H648v-60h172q24 0 42 18t18 42v172h-60Z"
></path></svg
>
</IconBlock>
</div> </div>
</div> </div>
</div> </div>

View file

@ -2,12 +2,27 @@
// Import the necessary dependencies // Import the necessary dependencies
import TabNav from "../../ui/blocks/TabNav.astro"; import TabNav from "../../ui/blocks/TabNav.astro";
import TabContent from "../../ui/blocks/TabContent.astro"; import TabContent from "../../ui/blocks/TabContent.astro";
import construction from "../../../images/construction-image.avif"; import Icon from "../../ui/icons/Icon.astro";
import tools from "../../../images/automated-tools.avif";
import dashboard from "../../../images/dashboard-image.avif";
// Define the variable for the section's heading // Define props from Astro
const title: string = `Customize <span class="text-yellow-500 dark:text-yellow-400">ScrewFast</span>'s offerings to perfectly suit your hardware and construction needs.`; const { title, tabs } = Astro.props;
// Define TypeScript interface for tab object
interface Tab {
heading: string;
content: string;
svg: string;
src: any;
alt: string;
first?: boolean;
second?: boolean;
}
// Define TypeScript interface for props
interface Props {
title?: string;
tabs: Tab[];
}
--- ---
<section <section
@ -27,64 +42,20 @@ const title: string = `Customize <span class="text-yellow-500 dark:text-yellow-4
</h2> </h2>
<!-- Tab navigation - use the attribute 'first' in the first TabNav for the component to work --> <!-- Tab navigation - use the attribute 'first' in the first TabNav for the component to work -->
<nav class="mt-5 grid gap-4 md:mt-10" aria-label="Tabs" role="tablist"> <nav class="mt-5 grid gap-4 md:mt-10" aria-label="Tabs" role="tablist">
<TabNav {
id="tabs-with-card-item-1" tabs.map((tab, index) => (
dataTab="#tabs-with-card-1" <TabNav
aria="tabs-with-card-1" id={`tabs-with-card-item-${index + 1}`}
heading="Cutting-Edge Tools" dataTab={`#tabs-with-card-${index + 1}`}
content="Empower your projects with ScrewFast's cutting-edge tools. Experience enhanced efficiency in construction management with our sophisticated automated solutions." aria={`tabs-with-card-${index + 1}`}
first={true} heading={tab.heading}
> content={tab.content}
<svg first={tab.first}
class="mt-2 h-6 w-6 flex-shrink-0 fill-neutral-700 hs-tab-active:fill-[#fa5a15] dark:fill-neutral-300 dark:hs-tab-active:fill-[#fb713b] md:h-7 md:w-7" >
height="48" <Icon name={tab.svg} />
viewBox="0 -960 960 960" </TabNav>
width="48" ))
><path }
d="M764-80q-6 0-11-2t-10-7L501-331q-5-5-7-10t-2-11q0-6 2-11t7-10l85-85q5-5 10-7t11-2q6 0 11 2t10 7l242 242q5 5 7 10t2 11q0 6-2 11t-7 10l-85 85q-5 5-10 7t-11 2Zm0-72 43-43-200-200-43 43 200 200ZM195-80q-6 0-11.5-2T173-89l-84-84q-5-5-7-10.5T80-195q0-6 2-11t7-10l225-225h85l38-38-175-175h-57L80-779l99-99 125 125v57l175 175 130-130-67-67 56-56H485l-18-18 128-128 18 18v113l56-56 169 169q15 15 23.5 34.5T870-600q0 20-6.5 38.5T845-528l-85-85-56 56-52-52-211 211v84L216-89q-5 5-10 7t-11 2Zm0-72 200-200v-43h-43L152-195l43 43Zm0 0-43-43 22 21 21 22Zm569 0 43-43-43 43Z"
></path></svg
>
</TabNav>
<TabNav
id="tabs-with-card-item-2"
dataTab="#tabs-with-card-2"
aria="tabs-with-card-2"
heading="Intuitive Dashboards"
content="Navigate with ease using ScrewFast's intuitive dashboards. Set up and oversee your projects seamlessly, with user-friendly interfaces designed for quick and effective workflow management."
>
<svg
class="mt-2 h-6 w-6 flex-shrink-0 fill-neutral-700 hs-tab-active:fill-[#fa5a15] dark:fill-neutral-300 dark:hs-tab-active:fill-[#fb713b] md:h-7 md:w-7"
height="48"
viewBox="0 -960 960 960"
width="48"
><path
d="M510-570v-270h330v270H510ZM120-450v-390h330v390H120Zm390 330v-390h330v390H510Zm-390 0v-270h330v270H120Zm60-390h210v-270H180v270Zm390 330h210v-270H570v270Zm0-450h210v-150H570v150ZM180-180h210v-150H180v150Zm210-330Zm180-120Zm0 180ZM390-330Z"
></path></svg
>
</TabNav>
<TabNav
id="tabs-with-card-item-3"
dataTab="#tabs-with-card-3"
aria="tabs-with-card-3"
heading="Robust Features"
content="Minimize complexity, maximize productivity. ScrewFast's robust features are engineered to streamline your construction process, delivering results that stand out for their excellence."
>
<svg
class="h-6 w-6 flex-shrink-0 text-neutral-700 hs-tab-active:text-[#fa5a15] dark:text-neutral-300 dark:hs-tab-active:text-[#fb713b] md:h-7 md:w-7"
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M8.25 21v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21m0 0h4.5V3.545M12.75 21h7.5V10.75M2.25 21h1.5m18 0h-18M2.25 9l4.5-1.636M18.75 3l-1.5.545m0 6.205 3 1m1.5.5-1.5-.5M6.75 7.364V3h-3v18m3-13.636 10.5-3.819"
></path>
</svg>
</TabNav>
</nav> </nav>
</div> </div>
@ -92,26 +63,18 @@ const title: string = `Customize <span class="text-yellow-500 dark:text-yellow-4
<div class="lg:col-span-6"> <div class="lg:col-span-6">
<div class="relative"> <div class="relative">
<div> <div>
<TabContent {
id="tabs-with-card-1" tabs.map((tab, index) => (
aria="tabs-with-card-item-1" <TabContent
src={tools} id={`tabs-with-card-${index + 1}`}
alt="Yellow and black heavy equipment on brown grass field" aria={`tabs-with-card-item-${index + 1}`}
first={true} src={tab.src}
/> alt={tab.alt}
<TabContent first={tab.first}
id="tabs-with-card-2" second={tab.second}
aria="tabs-with-card-item-2" />
src={dashboard} ))
alt="A screenshot or graphic representation of the intuitive dashboard" }
second={true}
/>
<TabContent
id="tabs-with-card-3"
aria="tabs-with-card-item-3"
src={construction}
alt="Gray metal building frame near tower crane during daytime"
/>
</div> </div>
</div> </div>
</div> </div>