Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
682 changes: 350 additions & 332 deletions bun.lock

Large diffs are not rendered by default.

14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
"preview": "astro preview"
},
"dependencies": {
"@astrojs/sitemap": "^3.7.0",
"@lucide/astro": "^0.561.0",
"@tailwindcss/vite": "^4.1.18",
"astro": "^5.16.10",
"@astrojs/sitemap": "^3.7.3",
"@fortawesome/free-brands-svg-icons": "^7.2.0",
"@lucide/astro": "^1.21.0",
"@tailwindcss/vite": "^4.3.1",
"astro": "^5.18.2",
"astro-sst": "3.1.4",
"sst": "3.17.25",
"tailwindcss": "^4.1.18"
"simple-icons": "^16.23.0",
"sst": "4.15.2",
"tailwindcss": "^4.3.1"
}
}
11 changes: 6 additions & 5 deletions src/components/Footer.astro
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
---
import { Github, Linkedin, Twitter } from "@lucide/astro/icons"; // Changed X to Twitter
import SocialIcon from "./SocialIcon.astro";

const socialLinks = [
{
href: "https://github.com/joshymcd", // Replace with your GitHub URL
label: "GitHub",
icon: Github,
icon: "github",
},
{
href: "https://linkedin.com/in/joshmcdonald92", // Replace with your LinkedIn URL
label: "LinkedIn",
icon: Linkedin,
icon: "linkedin",
},
{
href: "https://x.com/joshymcd92", // Replace with your X/Twitter URL
label: "Twitter", // Changed label
icon: Twitter, // Changed icon from X to Twitter
icon: "twitter",
},
];
Comment on lines 4 to 20

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using as const on the socialLinks array ensures that the icon property is inferred as the literal types "github" | "linkedin" | "twitter" instead of a generic string. This prevents TypeScript type mismatch errors when passing link.icon to the typed SocialIcon component.

const socialLinks = [
  {
    href: "https://github.com/joshymcd", // Replace with your GitHub URL
    label: "GitHub",
    icon: "github",
  },
  {
    href: "https://linkedin.com/in/joshmcdonald92", // Replace with your LinkedIn URL
    label: "LinkedIn",
    icon: "linkedin",
  },
  {
    href: "https://x.com/joshymcd92", // Replace with your X/Twitter URL
    label: "Twitter", // Changed label
    icon: "twitter",
  },
] as const;


Expand All @@ -36,7 +36,8 @@ const pathname = Astro.url.pathname;
aria-label={link.label}
class="transition-colors hover:text-link-hover"
>
<link.icon
<SocialIcon
name={link.icon}
size={24}
transition:name={`social-${link.label.toLowerCase()}`}
/>
Expand Down
46 changes: 46 additions & 0 deletions src/components/SocialIcon.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
import { faLinkedin } from "@fortawesome/free-brands-svg-icons";
import { siGithub, siX } from "simple-icons";

const { name, size = 24, class: className, ...attrs } = Astro.props;
Comment on lines +1 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding a Props interface to the SocialIcon component improves type safety and provides autocomplete in editors. It also prevents potential TypeScript compilation errors when indexing the icons object with a dynamic name string.

---
interface Props {
  name: "github" | "linkedin" | "twitter";
  size?: number;
  class?: string;
  [key: string]: any;
}

const { name, size = 24, class: className, ...attrs } = Astro.props;


const [linkedinWidth, linkedinHeight, , , linkedinPath] = faLinkedin.icon;

const icons = {
github: {
label: siGithub.title,
path: siGithub.path,
viewBox: "0 0 24 24",
},
linkedin: {
label: "LinkedIn",
path: linkedinPath,
viewBox: `0 0 ${linkedinWidth} ${linkedinHeight}`,
},
twitter: {
label: siX.title,
path: siX.path,
viewBox: "0 0 24 24",
},
};

const icon = icons[name];
---

{
icon && (
<svg
xmlns="http://www.w3.org/2000/svg"
width={size}
height={size}
viewBox={icon.viewBox}
fill="currentColor"
role="img"
aria-label={icon.label}
class={className}
{...attrs}
>
<path d={icon.path} />
</svg>
)
}
13 changes: 6 additions & 7 deletions src/pages/find-me.astro
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
---
import Layout from "../layouts/Layout.astro";
import Github from "@lucide/astro/icons/github";
import Linkedin from "@lucide/astro/icons/linkedin";
import Twitter from "@lucide/astro/icons/twitter"; // Or use 'X' if available and preferred
import Contact from "@lucide/astro/icons/contact"; // Icon for the page title
import PageTitle from "../components/PageTitle.astro"; // Import the new component
import SocialIcon from "../components/SocialIcon.astro";

// TODO: Replace placeholder URLs with your actual social media profile links
const socialLinks = [
{
href: "https://github.com/joshymcd",
icon: Github,
icon: "github",
label: "GitHub",
badgeText: "code",
},
{
href: "https://linkedin.com/in/joshmcdonald92",
icon: Linkedin,
icon: "linkedin",
label: "LinkedIn",
badgeText: "work",
},
{
href: "https://x.com/joshymcd92",
icon: Twitter, // Or potentially an 'X' icon if Lucide adds one
icon: "twitter",
label: "Twitter",
badgeText: "memes",
},
Expand All @@ -47,7 +45,8 @@ const socialLinks = [
class="block rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-background transition-all duration-200 hover:scale-105"
>
<div class="flex flex-col items-center p-6 w-32 h-40 border border-border bg-bg-muted rounded-md text-text-base hover:border-primary hover:bg-bg-gradient-end">
<link.icon
<SocialIcon
name={link.icon}
size={48}
transition:name={`social-${link.label.toLowerCase()}`}
class="mb-2"
Expand Down
4 changes: 4 additions & 0 deletions sst.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export default $config({
) {
return { stage: "production" };
}

if (event.type === "pull_request" && event.base === "main") {
return { stage: `pr-${event.number}` };
}
},
},
},
Expand Down