Skip to content

Commit

Permalink
chore: updated neura-launch-blog
Browse files Browse the repository at this point in the history
  • Loading branch information
TarunTomar122 authored Sep 15, 2023
1 parent 1bb006c commit 3f16da5
Show file tree
Hide file tree
Showing 13 changed files with 735 additions and 0 deletions.
60 changes: 60 additions & 0 deletions components/Breadcrumbs.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
---
// Remove current url path and remove trailing slash if exists
const currentUrlPath = Astro.url.pathname.replace(/\/+$/, "");
// Get url array from path
// eg: /tags/tailwindcss => ['tags', 'tailwindcss']
const breadcrumbList = currentUrlPath.split("/").slice(1);
// if breadcrumb is Home > Posts > 1 <etc>
// replace Posts with Posts (page number)
breadcrumbList[0] === "posts" &&
breadcrumbList.splice(0, 2, `Posts (page ${breadcrumbList[1] || 1})`);
---

<nav class="breadcrumb" aria-label="breadcrumb">
<ul>
<li>
<a href="/">Home</a>
<span aria-hidden="true">&#62;</span>
</li>
{
breadcrumbList.map((breadcrumb, index) =>
index + 1 === breadcrumbList.length ? (
<li>
<span
class={`${index > 0 ? "lowercase" : "capitalize"}`}
aria-current="page"
>
{/* make the last part lowercase in Home > Tags > some-tag */}
{breadcrumb}
</span>
</li>
) : (
<li>
<a href={`/${breadcrumb}`}>{breadcrumb}</a>
<span aria-hidden="true">&#62;</span>
</li>
)
)
}
</ul>
</nav>

<style>
.breadcrumb {
@apply mx-auto mb-1 mt-8 w-full max-w-3xl px-4;
}
.breadcrumb ul li {
@apply inline;
}
.breadcrumb ul li a {
@apply capitalize opacity-70;
}
.breadcrumb ul li span {
@apply opacity-70;
}
.breadcrumb ul li:not(:last-child) a {
@apply hover:opacity-100;
}
</style>
32 changes: 32 additions & 0 deletions components/Card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Datetime from "./Datetime";
import type { BlogFrontmatter } from "@content/_schemas";

export interface Props {
href?: string;
frontmatter: BlogFrontmatter;
secHeading?: boolean;
}

export default function Card({ href, frontmatter, secHeading = true }: Props) {
const { title, pubDatetime, description } = frontmatter;
return (
<li className="my-6">
<a
href={href}
className="mb-1 inline-block text-xl font-medium text-skin-accent decoration-dashed underline-offset-4 focus-visible:no-underline focus-visible:underline-offset-0"
>
{secHeading ? (
<h2 className="text-xl font-medium decoration-dashed hover:underline">
{title}
</h2>
) : (
<h3 className="text-xl font-medium decoration-dashed hover:underline">
{title}
</h3>
)}
</a>
<Datetime datetime={pubDatetime} className="mt-1"/>
<p className="mt-2">{description}</p>
</li>
);
}
52 changes: 52 additions & 0 deletions components/Datetime.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { LOCALE } from "@config";

export interface Props {
datetime: string | Date;
size?: "sm" | "lg";
className?: string;
}

export default function Datetime({ datetime, size = "sm", className }: Props) {
return (
<div className={`flex items-center space-x-2 opacity-80 ${className}`}>
<svg
xmlns="http://www.w3.org/2000/svg"
className={`${
size === "sm" ? "scale-90" : "scale-100"
} inline-block h-6 w-6 fill-skin-base`}
aria-hidden="true"
>
<path d="M7 11h2v2H7zm0 4h2v2H7zm4-4h2v2h-2zm0 4h2v2h-2zm4-4h2v2h-2zm0 4h2v2h-2z"></path>
<path d="M5 22h14c1.103 0 2-.897 2-2V6c0-1.103-.897-2-2-2h-2V2h-2v2H9V2H7v2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2zM19 8l.001 12H5V8h14z"></path>
</svg>
<span className="sr-only">Posted on:</span>
<span className={`italic ${size === "sm" ? "text-sm" : "text-base"}`}>
<FormattedDatetime datetime={datetime} />
</span>
</div>
);
}

const FormattedDatetime = ({ datetime }: { datetime: string | Date }) => {
const myDatetime = new Date(datetime);

const date = myDatetime.toLocaleDateString(LOCALE, {
year: "numeric",
month: "long",
day: "numeric",
});

const time = myDatetime.toLocaleTimeString(LOCALE, {
hour: "2-digit",
minute: "2-digit",
});

return (
<>
{date}
{/* <span aria-hidden="true"> | </span> */}
{/* <span className="sr-only">&nbsp;at&nbsp;</span> */}
{/* {time} */}
</>
);
};
45 changes: 45 additions & 0 deletions components/Footer.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
import Hr from "./Hr.astro";
import Socials from "./Socials.astro";
const currentYear = new Date().getFullYear();
export interface Props {
noMarginTop?: boolean;
}
const { noMarginTop = false } = Astro.props;
---

<footer class={`${noMarginTop ? "" : "mt-auto"}`}>
<Hr noPadding />
<div class="footer-wrapper">
<Socials centered />
<div class="copyright-wrapper">
<span>Copyright &#169; {currentYear}</span>
<span class="separator">&nbsp;|&nbsp;</span>
<span>All rights reserved.</span>
</div>
</div>
</footer>

<style>
footer {
@apply w-full;
}
.footer-wrapper {
@apply flex flex-col items-center justify-between py-6 sm:flex-row-reverse sm:py-4;
}
.link-button {
@apply my-1 p-2 hover:rotate-6;
}
.link-button svg {
@apply scale-125;
}
.copyright-wrapper {
@apply my-2 flex flex-col items-center whitespace-nowrap sm:flex-row;
}
.separator {
@apply hidden sm:inline;
}
</style>
197 changes: 197 additions & 0 deletions components/Header.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
import { SITE } from "@config";
import Hr from "./Hr.astro";
import LinkButton from "./LinkButton.astro";
export interface Props {
activeNav?: "posts" | "projects" | "about" | "search";
}
const { activeNav } = Astro.props;
---

<header>
<a id="skip-to-content" href="#main-content">Skip to content</a>
<div class="nav-container">
<div class="top-nav-wrap">
<a href="/" class="logo">{SITE.title}</a>
<nav id="nav-menu">
<button
class="hamburger-menu focus-outline"
aria-label="Open Menu"
aria-expanded="false"
aria-controls="menu-items"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
class="menu-icon"
>
<line x1="7" y1="12" x2="21" y2="12" class="line"></line>
<line x1="3" y1="6" x2="21" y2="6" class="line"></line>
<line x1="12" y1="18" x2="21" y2="18" class="line"></line>
<line x1="18" y1="6" x2="6" y2="18" class="close"></line>
<line x1="6" y1="6" x2="18" y2="18" class="close"></line>
</svg>
</button>
<ul id="menu-items" class="display-none sm:flex">
<li>
<a
href="/projects"
class={activeNav === "projects" ? "active" : ""}
>
Projects
</a>
</li>
<li>
<a href="/posts" class={activeNav === "posts" ? "active" : ""}>
Posts
</a>
</li>
<li>
<a href="/about" class={activeNav === "about" ? "active" : ""}>
About
</a>
</li>
<li>
<LinkButton
href="/search"
className={`focus-outline p-3 sm:p-1 ${
activeNav === "search" ? "active" : ""
}`}
ariaLabel="search"
title="Search"
>
<svg
xmlns="http://www.w3.org/2000/svg"
class="scale-125 sm:scale-100"
><path
d="M19.023 16.977a35.13 35.13 0 0 1-1.367-1.384c-.372-.378-.596-.653-.596-.653l-2.8-1.337A6.962 6.962 0 0 0 16 9c0-3.859-3.14-7-7-7S2 5.141 2 9s3.14 7 7 7c1.763 0 3.37-.66 4.603-1.739l1.337 2.8s.275.224.653.596c.387.363.896.854 1.384 1.367l1.358 1.392.604.646 2.121-2.121-.646-.604c-.379-.372-.885-.866-1.391-1.36zM9 14c-2.757 0-5-2.243-5-5s2.243-5 5-5 5 2.243 5 5-2.243 5-5 5z"
></path>
</svg>
</LinkButton>
</li>
<li>
{
SITE.lightAndDarkMode && (
<button
id="theme-btn"
class="focus-outline"
title="Toggles light & dark"
aria-label="auto"
aria-live="polite"
>
<svg xmlns="http://www.w3.org/2000/svg" id="moon-svg">
<path d="M20.742 13.045a8.088 8.088 0 0 1-2.077.271c-2.135 0-4.14-.83-5.646-2.336a8.025 8.025 0 0 1-2.064-7.723A1 1 0 0 0 9.73 2.034a10.014 10.014 0 0 0-4.489 2.582c-3.898 3.898-3.898 10.243 0 14.143a9.937 9.937 0 0 0 7.072 2.93 9.93 9.93 0 0 0 7.07-2.929 10.007 10.007 0 0 0 2.583-4.491 1.001 1.001 0 0 0-1.224-1.224zm-2.772 4.301a7.947 7.947 0 0 1-5.656 2.343 7.953 7.953 0 0 1-5.658-2.344c-3.118-3.119-3.118-8.195 0-11.314a7.923 7.923 0 0 1 2.06-1.483 10.027 10.027 0 0 0 2.89 7.848 9.972 9.972 0 0 0 7.848 2.891 8.036 8.036 0 0 1-1.484 2.059z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" id="sun-svg">
<path d="M6.993 12c0 2.761 2.246 5.007 5.007 5.007s5.007-2.246 5.007-5.007S14.761 6.993 12 6.993 6.993 9.239 6.993 12zM12 8.993c1.658 0 3.007 1.349 3.007 3.007S13.658 15.007 12 15.007 8.993 13.658 8.993 12 10.342 8.993 12 8.993zM10.998 19h2v3h-2zm0-17h2v3h-2zm-9 9h3v2h-3zm17 0h3v2h-3zM4.219 18.363l2.12-2.122 1.415 1.414-2.12 2.122zM16.24 6.344l2.122-2.122 1.414 1.414-2.122 2.122zM6.342 7.759 4.22 5.637l1.415-1.414 2.12 2.122zm13.434 10.605-1.414 1.414-2.122-2.122 1.414-1.414z" />
</svg>
</button>
)
}
</li>
</ul>
</nav>
</div>
</div>
<Hr />
</header>

<style>
#skip-to-content {
@apply absolute -top-full left-16 z-50 bg-skin-accent px-3 py-2 text-skin-inverted transition-all focus:top-4;
}
.nav-container {
@apply mx-auto flex max-w-3xl flex-col items-center justify-between sm:flex-row;
}
.top-nav-wrap {
@apply relative flex w-full items-start justify-between p-4 sm:items-center sm:py-8;
}
.logo {
@apply absolute py-1 text-xl font-semibold sm:static sm:text-2xl;
}
.hamburger-menu {
@apply self-end p-2 sm:hidden;
}
.hamburger-menu svg {
@apply h-6 w-6 scale-125 fill-skin-base;
}

nav {
@apply flex w-full flex-col items-center bg-skin-fill sm:ml-2 sm:flex-row sm:justify-end sm:space-x-4 sm:py-0;
}
nav ul {
@apply mt-4 grid w-44 grid-cols-2 grid-rows-4 gap-x-2 gap-y-2 sm:ml-0 sm:mt-0 sm:w-auto sm:gap-x-5 sm:gap-y-0;
}
nav ul li {
@apply col-span-2 flex items-center justify-center;
}
nav ul li a {
@apply w-full px-4 py-3 text-center font-medium hover:text-skin-accent sm:my-0 sm:px-2 sm:py-1;
}
nav ul li:nth-child(4) a {
@apply w-auto;
}
nav ul li:nth-child(4),
nav ul li:nth-child(5) {
@apply col-span-1;
}
nav a.active {
@apply underline decoration-wavy decoration-2 underline-offset-4;
}
nav a.active svg {
@apply fill-skin-accent;
}

nav button {
@apply p-1;
}
nav button svg {
@apply h-6 w-6 fill-skin-base hover:fill-skin-accent;
}
#theme-btn {
@apply p-3 sm:p-1;
}
#theme-btn svg {
@apply scale-125 hover:rotate-12 sm:scale-100;
}

.menu-icon line {
@apply transition-opacity duration-75 ease-in-out;
}
.menu-icon .close {
opacity: 0;
}
.menu-icon.is-active .line {
@apply opacity-0;
}
.menu-icon.is-active .close {
@apply opacity-100;
}
</style>

<script>
// Toggle menu
const menuBtn = document.querySelector(".hamburger-menu");
const menuIcon = document.querySelector(".menu-icon");
const menuItems = document.querySelector("#menu-items");

menuBtn?.addEventListener("click", () => {
const menuExpanded = menuBtn.getAttribute("aria-expanded") === "true";
menuIcon?.classList.toggle("is-active");
menuBtn.setAttribute("aria-expanded", menuExpanded ? "false" : "true");
menuBtn.setAttribute(
"aria-label",
menuExpanded ? "Open Menu" : "Close Menu"
);
menuItems?.classList.toggle("display-none");
});
</script>
Loading

0 comments on commit 3f16da5

Please sign in to comment.