Merge pull request #19 from mearashadowfax/add-reusable-faq

Code refactor and new features
This commit is contained in:
Emil Gulamov 2024-03-22 04:51:30 +04:00 committed by GitHub
commit 6b12875acb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 559 additions and 406 deletions

View file

@ -1,49 +1,27 @@
---
// Import the necessary AccordionItem component
// Import the necessary AccordionItem component and JSON data
import AccordionItem from "../ui/blocks/AccordionItem.astro";
// Define the string variable `subTitle` to provide additional information.
const subTitle: string =
"Ask us anything about our brand and products, and get factual responses.";
// Define props from Astro
const { title, faqs } = Astro.props;
// Define TypeScript interface for props
interface Faq {
question: string;
answer: string;
}
interface FaqGroup {
subTitle?: string;
faqs: Faq[];
}
interface Props {
title: string;
faqs: FaqGroup;
}
// Define a helper function to generate ids dynamically.
const makeId = (base: any, index: any) => `${base}${index + 1}`;
// Define an array `faqs` that holds the content for the Frequently Asked Questions.
const faqs = [
// Content of each FAQ item goes here
{
heading: "What types of tools are included in the Starter Kit?",
content:
"The Starter Kit features essential hand and power tools for diverse DIY projects, including hammers, drills, screwdrivers, and a variety of fasteners. It's a curated selection to help beginners and experienced DIYers alike tackle most home improvement tasks.",
},
{
heading: "Can I upgrade from the Starter Kit to the Professional Toolbox?",
content:
"Absolutely! You can upgrade to the Professional Toolbox at any time to access a wider range of high-quality tools, enjoy priority customer support, and receive exclusive content. Contact our support team for a seamless transition.",
},
{
heading:
"What discounts are available for bulk orders through the Professional Toolbox plan?",
content:
"Professional Toolbox members are entitled to exclusive discounts on bulk orders, the percentage of which may vary depending on the order volume. Get in touch with us to discuss your needs, and we'll provide a tailored discount structure.",
},
{
heading: "What kind of customer support can I expect?",
content:
"All our customers receive dedicated email support. With the Starter Kit, you'll receive our standard support, while the Professional Toolbox plan upgrades you to priority support, meaning faster response times and specialized assistance.",
},
{
heading: "How current are the online resources and tutorials?",
content:
"We regularly update our online resources and tutorials to reflect the latest trends in DIY and construction, as well as introductions to new tools and techniques. Our material aims to be comprehensive and user-friendly for all skill levels.",
},
{
heading:
"Does ScrewFast offer services for large-scale construction projects?",
content:
"Yes, our Enterprise Solutions are designed for larger companies requiring comprehensive services. We provide consultation, planning, and supply of high-grade tools and materials, as well as staffing solutions for substantial construction needs. Contact us for a customized quote.",
},
];
---
<!-- Main container that holds all content. Customized for different viewport sizes. -->
@ -56,10 +34,10 @@ const faqs = [
<h2
class="text-2xl font-bold text-neutral-800 dark:text-neutral-200 md:text-4xl md:leading-tight"
>
Frequently<br />asked questions
<Fragment set:html={title} />
</h2>
<p class="mt-1 hidden text-neutral-600 dark:text-neutral-400 md:block">
{subTitle}
{faqs.subTitle}
</p>
</div>
</div>
@ -69,15 +47,15 @@ const faqs = [
class="hs-accordion-group divide-y divide-neutral-200 dark:divide-neutral-700"
>
{
faqs.map((question, i) => {
faqs.faqs.map((question, i) => {
// Generate ids dynamically for each FAQ accordion item.
let id = makeId(
"hs-basic-with-title-and-arrow-stretched-heading-",
i,
i
);
let collapseId = makeId(
"hs-basic-with-title-and-arrow-stretched-collapse",
i,
i
);
return (

View file

@ -1,13 +1,24 @@
---
// Import the necessary dependencies
import { Image } from "astro:assets";
import featureImage from "../../../images/features-image.avif";
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
const title: string = "Meeting Industry Demands";
const subTitle: 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.";
interface Feature {
heading: string;
content: string;
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
@ -15,14 +26,18 @@ const subTitle: string =
>
<!-- Block to display the feature image -->
<div class="relative mb-6 overflow-hidden md:mb-8">
<Image
src={featureImage}
alt="ScrewFast products in floating boxes"
class="h-full w-full object-cover object-center"
draggable={"false"}
format={"avif"}
loading={"eager"}
/>
{
src && alt && (
<Image
src={src}
alt={alt}
class="h-full w-full object-cover object-center"
draggable={"false"}
format={"avif"}
loading={"eager"}
/>
)
}
</div>
<!-- Displaying the main content consisting of title, subtitle, and several `IconBlock` components -->
@ -36,12 +51,12 @@ const subTitle: string =
{title}
</h2>
<!-- Rendering subtitle -->
{subTitle &&
<p
class="mt-2 text-pretty text-neutral-600 dark:text-neutral-400 md:mt-4"
>
{subTitle}
</p>
{
subTitle && (
<p class="mt-2 text-pretty text-neutral-600 dark:text-neutral-400 md:mt-4">
{subTitle}
</p>
)
}
</div>
@ -49,69 +64,13 @@ const subTitle: string =
<div class="lg:col-span-2">
<div class="grid gap-8 sm:grid-cols-2 md:gap-12">
<!-- Injecting IconBlock components with different properties -->
<!-- IconBlock #1 -->
<IconBlock
heading="Dedicated Teams"
content="Benefit from our committed teams who ensure your success is personal. Count on expert guidance and exceptional results throughout your project journey."
>
<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>
{ features &&
features.map((feature) => (
<IconBlock heading={feature.heading} content={feature.content}>
<Icon name={feature.svg} />
</IconBlock>
))
}
</div>
</div>
</div>

View file

@ -2,12 +2,27 @@
// Import the necessary dependencies
import TabNav from "../../ui/blocks/TabNav.astro";
import TabContent from "../../ui/blocks/TabContent.astro";
import construction from "../../../images/construction-image.avif";
import tools from "../../../images/automated-tools.avif";
import dashboard from "../../../images/dashboard-image.avif";
import Icon from "../../ui/icons/Icon.astro";
// Define the variable for the section's heading
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.`;
// Define props from Astro
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
@ -27,64 +42,20 @@ const title: string = `Customize <span class="text-yellow-500 dark:text-yellow-4
</h2>
<!-- 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">
<TabNav
id="tabs-with-card-item-1"
dataTab="#tabs-with-card-1"
aria="tabs-with-card-1"
heading="Cutting-Edge Tools"
content="Empower your projects with ScrewFast's cutting-edge tools. Experience enhanced efficiency in construction management with our sophisticated automated solutions."
first={true}
>
<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="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>
{
tabs.map((tab, index) => (
<TabNav
id={`tabs-with-card-item-${index + 1}`}
dataTab={`#tabs-with-card-${index + 1}`}
aria={`tabs-with-card-${index + 1}`}
heading={tab.heading}
content={tab.content}
first={tab.first}
>
<Icon name={tab.svg} />
</TabNav>
))
}
</nav>
</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="relative">
<div>
<TabContent
id="tabs-with-card-1"
aria="tabs-with-card-item-1"
src={tools}
alt="Yellow and black heavy equipment on brown grass field"
first={true}
/>
<TabContent
id="tabs-with-card-2"
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"
/>
{
tabs.map((tab, index) => (
<TabContent
id={`tabs-with-card-${index + 1}`}
aria={`tabs-with-card-item-${index + 1}`}
src={tab.src}
alt={tab.alt}
first={tab.first}
second={tab.second}
/>
))
}
</div>
</div>
</div>

View file

@ -1,6 +1,7 @@
---
// Import SecondaryCTA component for use in this module
import SecondaryCTA from "../../ui/buttons/SecondaryCTA.astro";
import Icon from "../../ui/icons/Icon.astro";
// Set heading and sub-heading for the pricing section
const title: string = "Simple, Transparent Pricing";
@ -94,17 +95,7 @@ const professionalToolbox: Product = {
{
starterKit.features.map((feature) => (
<li class="flex items-center gap-1.5">
<svg
class="h-5 w-5 shrink-0"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clip-rule="evenodd"
/>
</svg>
<Icon name="checkCircle" />
<span>{feature}</span>
</li>
@ -154,17 +145,7 @@ const professionalToolbox: Product = {
{
professionalToolbox.features.map((feature) => (
<li class="flex items-center gap-1.5">
<svg
class="h-5 w-5 shrink-0"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fill-rule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clip-rule="evenodd"
/>
</svg>
<Icon name="checkCircle" />
<span>{feature}</span>
</li>

View file

@ -1,12 +1,13 @@
---
import Icon from "../icons/Icon.astro";
// Define props from Astro
const { id, collapseId, heading, content, first } = Astro.props;
const { id, collapseId, question, answer, first } = Astro.props;
// Define TypeScript interface for props
interface Props {
id: string;
collapseId: string;
heading: string;
content: string;
question: string;
answer: string;
first?: boolean;
}
// Define class names for the accordion and its content
@ -27,32 +28,12 @@ function getAccordionClass(first: boolean = false) {
class="hs-accordion-toggle group inline-flex w-full items-center justify-between gap-x-3 text-balance rounded-lg pb-3 text-start font-bold text-neutral-800 outline-none ring-zinc-500 transition hover:text-neutral-500 focus-visible:ring dark:text-neutral-200 dark:ring-zinc-200 dark:hover:text-neutral-400 dark:focus:outline-none md:text-lg"
aria-controls={collapseId}
>
{heading}
{question}
<!-- SVG Icon that is shown when the accordion is NOT active -->
<svg
class="block h-5 w-5 flex-shrink-0 text-neutral-600 group-hover:text-neutral-500 hs-accordion-active:hidden dark:text-neutral-400"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"><path d="m6 9 6 6 6-6"></path></svg
>
<Icon name="accordionNotActive" />
<!-- SVG Icon that is shown when the accordion is active -->
<svg
class="hidden h-5 w-5 flex-shrink-0 text-neutral-600 group-hover:text-neutral-500 hs-accordion-active:block dark:text-neutral-400"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"><path d="m18 15-6-6-6 6"></path></svg
>
<Icon name="accordionActive" />
</button>
<!-- The collapsible content of the accordion -->
<div
@ -62,7 +43,7 @@ function getAccordionClass(first: boolean = false) {
>
<!-- The content paragraph -->
<p class="text-pretty text-neutral-600 dark:text-neutral-400">
{content}
{answer}
</p>
</div>
</div>

View file

@ -1,4 +1,6 @@
---
import Icon from "../icons/Icon.astro";
const { count, description, index } = Astro.props;
interface Props {
@ -12,24 +14,7 @@ interface Props {
<div
class="mb-2 flex items-end gap-x-2 text-3xl font-bold text-neutral-800 dark:text-neutral-200 sm:text-5xl"
>
{
index === 1 || index === 2 ? (
<svg
class="h-5 w-5 flex-shrink-0 text-[#fa5a15] dark:text-[#fb713b]"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m5 12 7-7 7 7" />
<path d="M12 19V5" />
</svg>
) : null
}
{index === 1 || index === 2 ? <Icon name="arrowUp" /> : null}
{count}
</div>
<p class="text-sm text-neutral-600 dark:text-neutral-400 sm:text-base">

View file

@ -1,22 +1,13 @@
---
import Icon from "../icons/Icon.astro";
---
<button
type="button"
class="focus-visible:ring-secondary group inline-flex items-center rounded-lg p-2.5 text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 focus:outline-none focus-visible:outline-none focus-visible:ring-1 dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700"
data-bookmark-button="bookmark-button"
>
<svg
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-6 w-6 fill-none transition duration-300"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
class="fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400"
d="M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z"
></path>
</svg>
<Icon name="bookmark" />
</button>
<script>

View file

@ -1,4 +1,5 @@
---
import Icon from "../icons/Icon.astro";
// Destructure the properties from Astro.props
const { title, id, noArrow } = Astro.props;
// Define TypeScript interface for the properties
@ -16,20 +17,6 @@ const bgColorClasses =
const disableClasses = "disabled:pointer-events-none disabled:opacity-50";
const fontSizeClasses = "2xl:text-base";
const ringClasses = "dark:ring-zinc-200";
// SVG for an arrow icon
const arrowSVG = `<svg
class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m9 18 6-6-6-6"></path>
</svg>`;
---
<!-- Button with dynamic title, id, and optional arrow -->
@ -38,7 +25,6 @@ const arrowSVG = `<svg
id={id}
>
{title}
<!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments -->
<!-- Display the arrow based on the 'noArrow' property -->
{noArrow ? null : <Fragment set:html={arrowSVG} />}
{noArrow ? null : <Icon name="arrowRight" />}
</button>

View file

@ -1,4 +1,5 @@
---
import Icon from "../icons/Icon.astro";
const { title = "Continue with Github", url } = Astro.props;
interface Props {
@ -13,18 +14,6 @@ const bgColorClasses = "bg-yellow-400 dark:focus:outline-none";
const hoverClasses = "hover:shadow-2xl hover:shadow-yellow-500";
const fontSizeClasses = "2xl:text-base";
const ringClasses = "dark:ring-zinc-200";
const githubSVG = `<svg
class="w-4.5 h-4.5 tarnsition flex-shrink-0 text-neutral-700 duration-300 group-hover:-translate-y-1"
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
fill="currentColor"
viewBox="0 0 16 16"
>
<path
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z"
></path>
</svg>`;
---
<a
@ -33,8 +22,6 @@ const githubSVG = `<svg
target="_blank"
rel="noopener noreferrer"
>
<!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments -->
<Fragment set:html={githubSVG} />
<Icon name="github" />
{title}
</a>

View file

@ -1,4 +1,5 @@
---
import Icon from "../icons/Icon.astro";
// Destructure the properties from Astro.props
const { title, url, noArrow } = Astro.props;
// Define TypeScript interface for the properties
@ -16,20 +17,6 @@ const bgColorClasses =
const disableClasses = "disabled:pointer-events-none disabled:opacity-50";
const fontSizeClasses = "2xl:text-base";
const ringClasses = "dark:ring-zinc-200";
// SVG for an arrow icon
const arrowSVG = `<svg
class="h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m9 18 6-6-6-6"></path>
</svg>`;
---
<!-- Link styled as a button, with dynamic title, URL, and optional arrow -->
@ -39,7 +26,6 @@ const arrowSVG = `<svg
>
{title}
<!-- Display the arrow based on the 'noArrow' property -->
<!-- About Fragment: https://docs.astro.build/en/basics/astro-syntax/#fragments -->
{noArrow ? null : <Fragment set:html={arrowSVG} />}
{noArrow ? null : <Icon name="arrowRight" />}
</a>

View file

@ -1,4 +1,5 @@
---
import Icon from "../icons/Icon.astro";
// Destructure the properties from Astro.props
const { pageTitle } = Astro.props;
@ -17,41 +18,17 @@ const socialPlatforms: SocialPlatform[] = [
{
name: "Facebook",
url: `https://www.facebook.com/share.php?u=${Astro.url}&title=${pageTitle}`,
svg: `<svg
role="img"
viewBox="0 0 24 24"
stroke="currentColor"
class="size-4 flex-shrink-0 fill-current"
><title>Facebook</title><path
d="M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z"
></path></svg
>`,
svg: "facebook",
},
{
name: "X",
url: `https://twitter.com/home/?status=${pageTitle}${Astro.url}`,
svg: `<svg
role="img"
viewBox="0 0 24 24"
stroke="currentColor"
class="size-4 flex-shrink-0 fill-current"
><title>X</title><path
d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"
></path></svg
>`,
svg: "x",
},
{
name: "LinkedIn",
url: `https://www.linkedin.com/shareArticle?mini=true&url=${Astro.url}&title=${pageTitle}`,
svg: `<svg
role="img"
viewBox="0 0 24 24"
stroke="currentColor"
class="size-4 flex-shrink-0 fill-current"
><title>LinkedIn</title><path
d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"
></path></svg
>`,
svg: "linkedIn",
},
];
---
@ -64,19 +41,7 @@ const socialPlatforms: SocialPlatform[] = [
type="button"
class="hs-dropdown-toggle inline-flex items-center gap-x-2 rounded-lg px-4 py-3 text-sm font-medium text-neutral-600 outline-none ring-zinc-500 transition duration-300 hover:bg-neutral-100 hover:text-neutral-700 focus-visible:ring dark:text-neutral-400 dark:ring-zinc-200 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:outline-none"
>
<svg
fill="none"
viewBox="0 0 24 24"
stroke-width="1.5"
stroke="currentColor"
class="h-4 w-4 group-hover:text-neutral-700"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z"
></path>
</svg>
<Icon name="share" />
Share
</button>
@ -92,7 +57,7 @@ const socialPlatforms: SocialPlatform[] = [
class="flex items-center gap-x-3.5 rounded-lg px-3 py-2 text-sm text-neutral-700 hover:bg-neutral-200 focus:bg-neutral-100 focus:outline-none dark:text-neutral-300 dark:hover:bg-neutral-700 dark:hover:text-neutral-300 dark:focus:bg-neutral-700 "
href={platform.url}
>
<Fragment set:html={platform.svg} />
<Icon name={platform.svg} />
Share on {platform.name}
</a>
))

View file

@ -1,6 +1,7 @@
---
// Import necessary modules and utilities
import { Image } from "astro:assets";
import Icon from "../icons/Icon.astro";
import type { CollectionEntry } from "astro:content";
const { insightEntry } = Astro.props;
@ -42,18 +43,7 @@ interface Props {
class="mt-5 inline-flex items-center gap-x-1 font-medium text-[#fa5a15] decoration-2 group-hover:underline dark:text-[#fb713b]"
>
Read more
<svg
class="size-4 flex-shrink-0"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"><path d="m9 18 6-6-6-6"></path></svg
>
<Icon name="arrowRightStatic" />
</p>
</div>
</a>

View file

@ -1,6 +1,7 @@
---
// Import necessary modules and utilities
import { Image } from "astro:assets";
import Icon from "../icons/Icon.astro";
import type { CollectionEntry } from "astro:content";
const { product } = Astro.props;
@ -11,11 +12,6 @@ interface Props {
// Define classes to be used with the Image component
const imageClass =
"absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110";
// AnchorSVG - an SVG icon to be added next to the product's subtitle
const AnchorSVG = `
<svg fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" />
</svg>`;
---
<!-- A clickable card that leads to the details of the product-->
@ -40,6 +36,6 @@ const AnchorSVG = `
<!-- The product's subtitle and the anchor SVG icon-->
<span
class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg"
>{product.data.main.subTitle} <Fragment set:html={AnchorSVG} />
>{product.data.main.subTitle} <Icon name="openInNew" />
</span>
</a>

View file

@ -1,6 +1,7 @@
---
// Import necessary modules and utilities
import { Image } from "astro:assets";
import Icon from "../icons/Icon.astro";
import type { CollectionEntry } from "astro:content";
const { product } = Astro.props;
@ -11,11 +12,6 @@ interface Props {
// Define classes to be used with the Image component
const imageClass =
"absolute inset-0 h-full w-full object-cover object-center transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110";
// AnchorSVG - an SVG icon to be added next to the product's subtitle
const AnchorSVG = `
<svg fill="none" viewBox="0 0 24 24" stroke-width="3" stroke="currentColor" class="ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25" />
</svg>`;
---
<!-- The anchor tag is the main container for the product card. When clicked, this leads to the details of the product. -->
@ -40,6 +36,6 @@ const AnchorSVG = `
<!-- This container includes product's subtitle and an SVG icon-->
<span
class="relative mb-3 ml-4 inline-block text-sm font-bold text-neutral-50 transition duration-[600ms] ease-[cubic-bezier(0.45,0,0.55,1)] group-hover:scale-110 md:ml-5 md:text-lg"
>{product.data.main.subTitle} <Fragment set:html={AnchorSVG} /></span
>{product.data.main.subTitle} <Icon name="openInNew" /></span
>
</a>

View file

@ -0,0 +1,38 @@
---
import { Icons } from "./icons.ts";
interface Path {
d: string;
class?: string;
}
const { name } = Astro.props;
let icon = (Icons as any)[name] || {};
let paths: Path[] = icon.paths || [];
---
{
icon ? (
<svg
class={icon.class}
height={icon.height}
viewBox={icon.viewBox}
width={icon.width}
fill={icon.fill}
clip-rule={icon.clipRule}
fill-rule={icon.fillRule}
stroke={icon.stroke}
stroke-width={icon.strokeWidth}
stroke-linecap={icon.strokeLinecap}
stroke-linejoin={icon.strokeLinejoin}
>
{paths.map((path: Path) => (
<path d={path.d} class={path.class || ""} />
))}
</svg>
) : (
"Icon not found"
)
}

View file

@ -0,0 +1,278 @@
export const Icons = {
groups: {
paths: [
{
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",
},
],
class: "mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
books: {
paths: [
{
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",
},
],
class: "mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
verified: {
paths: [
{
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",
},
],
class: "mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
frame: {
paths: [
{
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",
},
],
class: "mt-1 h-8 w-8 flex-shrink-0 fill-[#fa5a15] dark:fill-[#fb713b]",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
tools: {
paths: [
{
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",
},
],
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",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
dashboard: {
paths: [
{
d: "M510-570v-270h330v270H510ZM120-450v-390h330v390H120Zm390 330v-390h330v390H510Zm-390 0v-270h330v270H120Zm60-390h210v-270H180v270Zm390 330h210v-270H570v270Zm0-450h210v-150H570v150ZM180-180h210v-150H180v150Zm210-330Zm180-120Zm0 180ZM390-330Z",
},
],
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",
width: 48,
height: 48,
viewBox: "0 -960 960 960",
},
house: {
paths: [
{
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",
},
],
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",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
arrowUp: {
paths: [
{
d: "m5 12 7-7 7 7",
},
{
d: "M12 19V5",
},
],
class: "h-5 w-5 flex-shrink-0 text-[#fa5a15] dark:text-[#fb713b]",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
checkCircle: {
paths: [
{
d: "M10 18a8 8 0 100-16 8 8 0 000 16zM13.707 8.293a1 1 0 00-1.414-1.414L9 10.586l-1.293-1.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",
},
],
class: "h-5 w-5 shrink-0",
viewBox: "0 0 20 20",
fill: "currentColor",
fillRule: "evenodd",
clipRule: "evenodd",
},
bookmark: {
paths: [
{
d: "M21 8.25c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 3.75 3 5.765 3 8.25c0 7.22 9 12 9 12s9-4.78 9-12Z",
class:
"fill-current text-neutral-500 transition duration-300 group-hover:text-red-400 group-hover:dark:text-red-400",
},
],
class: "h-6 w-6 fill-none transition duration-300",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
arrowRight: {
paths: [
{
d: "m9 18 6-6-6-6",
},
],
class:
"h-4 w-4 flex-shrink-0 transition duration-300 group-hover:translate-x-1",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
facebook: {
paths: [
{
d: "M9.101 23.691v-7.98H6.627v-3.667h2.474v-1.58c0-4.085 1.848-5.978 5.858-5.978.401 0 .955.042 1.468.103a8.68 8.68 0 0 1 1.141.195v3.325a8.623 8.623 0 0 0-.653-.036 26.805 26.805 0 0 0-.733-.009c-.707 0-1.259.096-1.675.309a1.686 1.686 0 0 0-.679.622c-.258.42-.374.995-.374 1.752v1.297h3.919l-.386 2.103-.287 1.564h-3.246v8.245C19.396 23.238 24 18.179 24 12.044c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.628 3.874 10.35 9.101 11.647Z",
},
],
class: "size-4 flex-shrink-0 fill-current",
viewBox: "0 0 24 24",
stroke: "currentColor",
},
x: {
paths: [
{
d: "M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z",
},
],
class: "size-4 flex-shrink-0 fill-current",
viewBox: "0 0 24 24",
stroke: "currentColor",
},
linkedIn: {
paths: [
{
d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z",
},
],
class: "size-4 flex-shrink-0 fill-current",
viewBox: "0 0 24 24",
stroke: "currentColor",
},
share: {
paths: [
{
d: "M7.217 10.907a2.25 2.25 0 1 0 0 2.186m0-2.186c.18.324.283.696.283 1.093s-.103.77-.283 1.093m0-2.186 9.566-5.314m-9.566 7.5 9.566 5.314m0 0a2.25 2.25 0 1 0 3.935 2.186 2.25 2.25 0 0 0-3.935-2.186Zm0-12.814a2.25 2.25 0 1 0 3.933-2.185 2.25 2.25 0 0 0-3.933 2.185Z",
},
],
class: "h-4 w-4 group-hover:text-neutral-700",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "1.5",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
github: {
paths: [
{
d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z",
},
],
class:
"w-4.5 h-4.5 tarnsition flex-shrink-0 text-neutral-700 duration-300 group-hover:-translate-y-1",
width: 16,
height: 16,
viewBox: "0 0 16 16",
fill: "currentColor",
},
arrowRightStatic: {
paths: [
{
d: "m9 18 6-6-6-6",
},
],
class: "size-4 flex-shrink-0",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
openInNew: {
paths: [
{
d: "m4.5 19.5 15-15m0 0H8.25m11.25 0v11.25",
},
],
class: "ml-0.5 w-3 h-3 md:w-4 md:h-4 inline pb-0.5",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "3",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
accordionNotActive: {
paths: [
{
d: "m6 9 6 6 6-6",
},
],
class:
"block h-5 w-5 flex-shrink-0 text-neutral-600 group-hover:text-neutral-500 hs-accordion-active:hidden dark:text-neutral-400",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
accordionActive: {
paths: [
{
d: "m18 15-6-6-6 6",
},
],
class:
"hidden h-5 w-5 flex-shrink-0 text-neutral-600 group-hover:text-neutral-500 hs-accordion-active:block dark:text-neutral-400",
width: 24,
height: 24,
viewBox: "0 0 24 24",
fill: "none",
strokeWidth: "2",
strokeLinecap: "round",
strokeLinejoin: "round",
stroke: "currentColor",
},
};

29
src/data_files/faqs.json Normal file
View file

@ -0,0 +1,29 @@
{
"subTitle": "Ask us anything about our brand and products, and get factual responses.",
"faqs": [
{
"question": "What types of tools are included in the Starter Kit?",
"answer": "The Starter Kit features essential hand and power tools for diverse DIY projects, including hammers, drills, screwdrivers, and a variety of fasteners. It's a curated selection to help beginners and experienced DIYers alike tackle most home improvement tasks."
},
{
"question": "Can I upgrade from the Starter Kit to the Professional Toolbox?",
"answer": "Absolutely! You can upgrade to the Professional Toolbox at any time to access a wider range of high-quality tools, enjoy priority customer support, and receive exclusive content. Contact our support team for a seamless transition."
},
{
"question": "What discounts are available for bulk orders through the Professional Toolbox plan?",
"answer": "Professional Toolbox members are entitled to exclusive discounts on bulk orders, the percentage of which may vary depending on the order volume. Get in touch with us to discuss your needs, and we'll provide a tailored discount structure."
},
{
"question": "What kind of customer support can I expect?",
"answer": "All our customers receive dedicated email support. With the Starter Kit, you'll receive our standard support, while the Professional Toolbox plan upgrades you to priority support, meaning faster response times and specialized assistance."
},
{
"question": "How current are the online resources and tutorials?",
"answer": "We regularly update our online resources and tutorials to reflect the latest trends in DIY and construction, as well as introductions to new tools and techniques. Our material aims to be comprehensive and user-friendly for all skill levels."
},
{
"question": "Does ScrewFast offer services for large-scale construction projects?",
"answer": "Yes, our Enterprise Solutions are designed for larger companies requiring comprehensive services. We provide consultation, planning, and supply of high-grade tools and materials, as well as staffing solutions for substantial construction needs. Contact us for a customized quote."
}
]
}

View file

@ -0,0 +1,22 @@
[
{
"heading": "Dedicated Teams",
"content": "Benefit from our committed teams who ensure your success is personal. Count on expert guidance and exceptional results throughout your project journey.",
"svg": "groups"
},
{
"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": "verified"
},
{
"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": "books"
},
{
"heading": "User-Centric Design",
"content": "Experience the difference with ScrewFast's user-focused design — where functionality meets practicality for an enhanced work experience.",
"svg": "frame"
}
]

View file

@ -11,6 +11,12 @@ import PricingSection from "../components/sections/pricing/PricingSection.astro"
import FAQ from "../components/sections/FAQ.astro";
import AnnouncementBanner from "../components/ui/banners/AnnouncementBanner.astro";
import heroImage from "../images/hero-image.avif";
import faqs from "../data_files/faqs.json";
import features from "../data_files/features.json";
import featureImage from "../images/features-image.avif";
import construction from "../images/construction-image.avif";
import tools from "../images/automated-tools.avif";
import dashboard from "../images/dashboard-image.avif";
const avatarSrcs: Array<string> = [
"https://images.unsplash.com/photo-1568602471122-7832951cc4c5?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=2&w=300&h=300&q=80",
@ -49,9 +55,45 @@ const avatarSrcs: Array<string> = [
subTitle="Experience the reliability chosen by industry giants."
/>
<FeaturesGeneral />
<FeaturesGeneral
title="Meeting Industry Demands"
subTitle="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."
src={featureImage}
alt="ScrewFast products in floating boxes"
features={features}
/>
<FeaturesNavs />
<FeaturesNavs
title=`Customize <span class="text-yellow-500 dark:text-yellow-400">ScrewFast</span>'s offerings to perfectly suit your hardware and construction needs.`
tabs={[
{
heading: "Cutting-Edge Tools",
content:
"Empower your projects with ScrewFast's cutting-edge tools. Experience enhanced efficiency in construction management with our sophisticated automated solutions.",
svg: "tools",
src: tools,
alt: "Yellow and black heavy equipment on brown grass field",
first: true,
},
{
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: "dashboard",
src: dashboard,
alt: "A screenshot or graphic representation of the intuitive dashboard",
second: true,
},
{
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: "house",
src: construction,
alt: "Gray metal building frame near tower crane during daytime",
},
]}
/>
<TestimonialsSection
title="Fast-Track Your Projects"
@ -92,7 +134,7 @@ const avatarSrcs: Array<string> = [
<PricingSection />
<FAQ />
<FAQ title="Frequently<br />asked questions" faqs={faqs} />
<HeroSectionAlt
title="Let's Build Together"