From c5968f2876a04b1c1167fcd9ad46d330550852e6 Mon Sep 17 00:00:00 2001 From: ASOwnerYT Date: Fri, 4 Apr 2025 02:11:26 +0000 Subject: [PATCH] Add ContactForm component and utility functions; update Navbar styles --- components.json | 21 ++ package-lock.json | 326 +++++++++++++++++- package.json | 8 +- src/app/components/ContactForm.js | 69 ++++ .../ContactForm.module.css} | 10 +- src/app/components/Navbar.js | 79 ++++- src/app/components/Navbar.module.css | 2 +- src/app/contact/page.js | 65 +--- src/app/globals.css | 129 +++++++ src/app/page.js | 183 +++++++++- src/components/ui/accordion.jsx | 64 ++++ src/lib/utils.js | 6 + 12 files changed, 874 insertions(+), 88 deletions(-) create mode 100644 components.json create mode 100644 src/app/components/ContactForm.js rename src/app/{contact/page.module.css => components/ContactForm.module.css} (90%) create mode 100644 src/components/ui/accordion.jsx create mode 100644 src/lib/utils.js diff --git a/components.json b/components.json new file mode 100644 index 0000000..aa48b52 --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": false, + "tailwind": { + "config": "", + "css": "src/app/globals.css", + "baseColor": "slate", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 31252d9..a1b4643 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,13 +10,19 @@ "dependencies": { "@next/env": "15.2.4", "@next/third-parties": "15.2.4", + "@radix-ui/react-accordion": "^1.2.3", "@vercel/analytics": "^1.4.1", "@vercel/speed-insights": "^1.1.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.487.0", "motion": "^11.16.0", "next": "15.2.4", "react": "19.1.0", "react-dom": "19.1.0", - "sharp": "^0.33.5" + "sharp": "^0.33.5", + "tailwind-merge": "^3.1.0", + "tw-animate-css": "^1.2.5" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.1", @@ -752,6 +758,275 @@ "node": ">=12.4.0" } }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.3.tgz", + "integrity": "sha512-RIQ15mrcvqIkDARJeERSuXSry2N8uYnxkdDetpfmalT/+0ntOXLkFOsh9iwlAsCv+qcmhZjbdJogIm6WBa6c4A==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collapsible": "1.1.3", + "@radix-ui/react-collection": "1.1.2", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.3.tgz", + "integrity": "sha512-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.2.tgz", + "integrity": "sha512-9z54IEKRxIa9VityapoEYMuByaG42iSy1ZXlY2KcuLSEtq8x4987/N6m15ppoMffgZX72gER2uHe1D9Y6Unlcw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@rtsao/scc": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", @@ -2021,12 +2296,33 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -4277,6 +4573,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lucide-react": { + "version": "0.487.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.487.0.tgz", + "integrity": "sha512-aKqhOQ+YmFnwq8dWgGjOuLc8V1R9/c/yOd+zDY4+ohsR2Jo05lSGc3WsstYPIzcTpeosN7LoCkLReUUITvaIvw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -5507,6 +5812,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-merge": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.1.0.tgz", + "integrity": "sha512-aV27Oj8B7U/tAOMhJsSGdWqelfmudnGMdXIlMnk1JfsjwSjts6o8HyfN7SFH3EztzH4YH8kk6GbLTHzITJO39Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.1.tgz", @@ -5627,6 +5942,15 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, + "node_modules/tw-animate-css": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/tw-animate-css/-/tw-animate-css-1.2.5.tgz", + "integrity": "sha512-ABzjfgVo+fDbhRREGL4KQZUqqdPgvc5zVrLyeW9/6mVqvaDepXc7EvedA+pYmMnIOsUAQMwcWzNvom26J2qYvQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Wombosvideo" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", diff --git a/package.json b/package.json index fd08d22..1849548 100644 --- a/package.json +++ b/package.json @@ -11,13 +11,19 @@ "dependencies": { "@next/env": "15.2.4", "@next/third-parties": "15.2.4", + "@radix-ui/react-accordion": "^1.2.3", "@vercel/analytics": "^1.4.1", "@vercel/speed-insights": "^1.1.0", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.487.0", "motion": "^11.16.0", "next": "15.2.4", "react": "19.1.0", "react-dom": "19.1.0", - "sharp": "^0.33.5" + "sharp": "^0.33.5", + "tailwind-merge": "^3.1.0", + "tw-animate-css": "^1.2.5" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.1", diff --git a/src/app/components/ContactForm.js b/src/app/components/ContactForm.js new file mode 100644 index 0000000..d718b23 --- /dev/null +++ b/src/app/components/ContactForm.js @@ -0,0 +1,69 @@ +import styles from "./ContactForm.module.css"; + +export default function ContactForm() { + return ( +
+

Contact Us

+
+

+ + + + 021 107 7483 +

+

+ + + + + info@teatatucomputers.com + +

+
+
+ + + + + + + + + + + + +

* required

+ + +
+
+ ); +} diff --git a/src/app/contact/page.module.css b/src/app/components/ContactForm.module.css similarity index 90% rename from src/app/contact/page.module.css rename to src/app/components/ContactForm.module.css index 15efa2f..404b7e8 100644 --- a/src/app/contact/page.module.css +++ b/src/app/components/ContactForm.module.css @@ -1,7 +1,3 @@ -.form { - margin-bottom: 35em; -} - .form input[type="text"], .form input[type="email"], .form input[type="tel"], @@ -26,8 +22,8 @@ } .sm { - font-size: 0.75em; - font-style: italic; + font-size: 0.75em; + font-style: italic; } .contactDetails { @@ -42,4 +38,4 @@ .contactDetails h3 a { color: black; -} \ No newline at end of file +} diff --git a/src/app/components/Navbar.js b/src/app/components/Navbar.js index ff364af..98a6392 100644 --- a/src/app/components/Navbar.js +++ b/src/app/components/Navbar.js @@ -8,6 +8,7 @@ import logo from "../assets/logo.svg"; import menu from "../assets/menu.svg"; import close from "../assets/close.svg"; import { usePathname } from "next/navigation"; +import { ChevronDownIcon } from "lucide-react"; // import { motion } from "motion/react" export default function Navbar() { @@ -82,33 +83,87 @@ export default function Navbar() { ${styles.dropdown} ${isDropdownActive && !isActive ? styles.dropdownActive : ""} `} + onMouseEnter={() => setDropdownActive(true)} + onMouseLeave={() => setDropdownActive(false)} > - - Services - + + Services + + + -
  • +
  • + + FAQ + +
  • +
  • -
    -

    - Contact us about anything related to our company or services. -
    - We'll do our best to get back to you as soon as possible. -

    - -
    - - - - - - - - - - - - -

    * required

    - - -
    +
    +
    ); diff --git a/src/app/globals.css b/src/app/globals.css index 05fc6ff..bde90fe 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,4 +1,9 @@ @import 'tailwindcss'; +@import "tw-animate-css"; +/* + ---break--- +*/ +@custom-variant dark (&:is(.dark *)); @utility container { padding-inline: 1rem; @@ -20,4 +25,128 @@ ::file-selector-button { border-color: var(--color-gray-200, currentColor); } +} +/* + ---break--- +*/ +:root { + --radius: 0.625rem; + --background: oklch(1 0 0); + --foreground: oklch(0.129 0.042 264.695); + --card: oklch(1 0 0); + --card-foreground: oklch(0.129 0.042 264.695); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.129 0.042 264.695); + --primary: oklch(0.208 0.042 265.755); + --primary-foreground: oklch(0.984 0.003 247.858); + --secondary: oklch(0.968 0.007 247.896); + --secondary-foreground: oklch(0.208 0.042 265.755); + --muted: oklch(0.968 0.007 247.896); + --muted-foreground: oklch(0.554 0.046 257.417); + --accent: oklch(0.968 0.007 247.896); + --accent-foreground: oklch(0.208 0.042 265.755); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.929 0.013 255.508); + --input: oklch(0.929 0.013 255.508); + --ring: oklch(0.704 0.04 256.788); + --chart-1: oklch(0.646 0.222 41.116); + --chart-2: oklch(0.6 0.118 184.704); + --chart-3: oklch(0.398 0.07 227.392); + --chart-4: oklch(0.828 0.189 84.429); + --chart-5: oklch(0.769 0.188 70.08); + --sidebar: oklch(0.984 0.003 247.858); + --sidebar-foreground: oklch(0.129 0.042 264.695); + --sidebar-primary: oklch(0.208 0.042 265.755); + --sidebar-primary-foreground: oklch(0.984 0.003 247.858); + --sidebar-accent: oklch(0.968 0.007 247.896); + --sidebar-accent-foreground: oklch(0.208 0.042 265.755); + --sidebar-border: oklch(0.929 0.013 255.508); + --sidebar-ring: oklch(0.704 0.04 256.788); +} +/* + ---break--- +*/ +.dark { + --background: oklch(0.129 0.042 264.695); + --foreground: oklch(0.984 0.003 247.858); + --card: oklch(0.208 0.042 265.755); + --card-foreground: oklch(0.984 0.003 247.858); + --popover: oklch(0.208 0.042 265.755); + --popover-foreground: oklch(0.984 0.003 247.858); + --primary: oklch(0.929 0.013 255.508); + --primary-foreground: oklch(0.208 0.042 265.755); + --secondary: oklch(0.279 0.041 260.031); + --secondary-foreground: oklch(0.984 0.003 247.858); + --muted: oklch(0.279 0.041 260.031); + --muted-foreground: oklch(0.704 0.04 256.788); + --accent: oklch(0.279 0.041 260.031); + --accent-foreground: oklch(0.984 0.003 247.858); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.551 0.027 264.364); + --chart-1: oklch(0.488 0.243 264.376); + --chart-2: oklch(0.696 0.17 162.48); + --chart-3: oklch(0.769 0.188 70.08); + --chart-4: oklch(0.627 0.265 303.9); + --chart-5: oklch(0.645 0.246 16.439); + --sidebar: oklch(0.208 0.042 265.755); + --sidebar-foreground: oklch(0.984 0.003 247.858); + --sidebar-primary: oklch(0.488 0.243 264.376); + --sidebar-primary-foreground: oklch(0.984 0.003 247.858); + --sidebar-accent: oklch(0.279 0.041 260.031); + --sidebar-accent-foreground: oklch(0.984 0.003 247.858); + --sidebar-border: oklch(1 0 0 / 10%); + --sidebar-ring: oklch(0.551 0.027 264.364); +} +/* + ---break--- +*/ +@theme inline { + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); +} +/* + ---break--- +*/ +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } } \ No newline at end of file diff --git a/src/app/page.js b/src/app/page.js index 39a871a..1600825 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -4,6 +4,13 @@ import bgimage from "./assets/header-bg.jpg"; import Button from "./components/Button"; import Link from "next/link"; import { GoogleMapsEmbed } from "@next/third-parties/google"; +import ContactForm from "./components/ContactForm"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; export default function Home() { return ( @@ -61,7 +68,7 @@ export default function Home() {
    -
    +

    Services we Offer

    @@ -163,17 +170,185 @@ export default function Home() {
    -
    -
    +
    + +
    +
    +

    + Frequently Asked Questions +

    +

    + Computer Repair and IT Support +

    + + + + What types of devices do you repair? + + + We repair desktops, laptops, chromebooks and PCs. We also handle + custom-built systems and some tablets, depending on the issue. + Currently we do not repair Apple devices. + + + + + What kinds of issues can you fix? + + + We handle a wide range of problems, including (but not limited + to): +
      +
    • + Software issues (e.g. Windows errors, slow performance) +
    • +
    • Virus removal and protection
    • +
    • Data recovery and backup solutions
    • +
    • Network setup and troubleshooting
    • +
    • Hardware upgrades (e.g. RAM, SSD, graphics card)
    • +
    • Custom PC builds
    • +
    • Web development and design
    • +
    • Remote support for software issues
    • +
    • General IT support and consulting
    • +
    • Printer setup and troubleshooting
    • +
    • Software installation and configuration
    • +
    • Operating system installation and upgrades
    • +
    • Data migration from old devices to new ones
    • +
    +
    +
    + + + Do I need an appointment, or can I just walk in? + + + Currently we are operating by appointment only. Please contact + us to schedule a time that works for you. We can also arrange + remote support for certain issues. + + + + + How long will the repair take? + + + Most basic repairs are completed within 24-48 hours. Some issues + may take longer, depending on parts availability and complexity. + We’ll give you an estimated turnaround time when we diagnose the + problem. Most parts take about a week to arrive. + + +
    + +

    + Web Design and Development +

    + + + + What platforms do you build websites with? + + + We specialize in modern web development using WordPress for + content-driven sites and React/Next.js for high-performance, + custom web applications. We also offer support for almost any + website builder, whether it's Wix, Oddo, Squarespace, or + anything else. Whether you need a blog, business site, + portfolio, or a fully custom web app—we've got you covered. + + + + + + How do I choose between WordPress and React/Next.js? + + + It depends on your needs: +
      +
    • + WordPress is best for content-heavy + websites like blogs, portfolios, and marketing sites. +
    • +
    • + React/Next.js is ideal for fast, scalable, + custom web applications or interactive user interfaces. +
    • +
    + We’ll help you decide what works best based on your goals and + budget. +
    +
    + + + Do you design the website too, or just build it? + + + We do both! We offer full-service web design and development. + This includes UX/UI design, branding, responsive layouts, and + mobile-first design—all tailored to your needs. + + + + + Can you redesign or improve my existing site? + + + Absolutely. We can modernize your design, improve performance, + migrate platforms, or fully rebuild your site with a better + structure and codebase. + + + + + Do you offer SEO and performance optimization? + + + Yes! All our builds include basic SEO best practices and speed + optimization. We also offer advanced technical SEO, Core Web + Vitals tuning, and image/code optimization. + + + + + Do you provide ongoing maintenance and support? + + + Yes, we offer monthly maintenance plans for updates, backups, + security checks, and minor edits. We can also provide on-demand + support when needed. + + + + + Will my site work on mobile devices? + + + Definitely. Every site we build is fully responsive and tested + on a variety of devices to ensure it looks great and works well + on phones, tablets, and desktops. + + + + + What do you need from me to get started? + + + We’ll need some info about your goals, brand, content (text, + images, logo), and examples of sites you like. Don’t worry—we’ll + guide you through the process! + + +
    +
    ); diff --git a/src/components/ui/accordion.jsx b/src/components/ui/accordion.jsx new file mode 100644 index 0000000..f787ff1 --- /dev/null +++ b/src/components/ui/accordion.jsx @@ -0,0 +1,64 @@ +"use client" + +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDownIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function Accordion({ + ...props +}) { + return ; +} + +function AccordionItem({ + className, + ...props +}) { + return ( + + ); +} + +function AccordionTrigger({ + className, + children, + ...props +}) { + return ( + + svg]:rotate-180", + className + )} + {...props}> + {children} + + + + ); +} + +function AccordionContent({ + className, + children, + ...props +}) { + return ( + +
    {children}
    +
    + ); +} + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/lib/utils.js b/src/lib/utils.js new file mode 100644 index 0000000..b20bf01 --- /dev/null +++ b/src/lib/utils.js @@ -0,0 +1,6 @@ +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge" + +export function cn(...inputs) { + return twMerge(clsx(inputs)); +}