feat: external links now open in new tab + MDXAccordion component
This commit is contained in:
parent
5f8a34cbd3
commit
06e76d38df
4 changed files with 157 additions and 0 deletions
|
@ -2,6 +2,7 @@ import HR from './components/HR.astro'
|
|||
import MDXImage from './components/mdx/MDXImage.astro'
|
||||
import MDXCallout from './components/mdx/MDXCallout.astro'
|
||||
import MDXCodeBlock from './components/mdx/MDXCodeBlock.astro'
|
||||
import MDXLink from './components/mdx/MDXLink.astro'
|
||||
|
||||
export const components = {
|
||||
hr: HR,
|
||||
|
@ -9,4 +10,5 @@ export const components = {
|
|||
MDXImage: MDXImage,
|
||||
MDXCallout: MDXCallout,
|
||||
pre: MDXCodeBlock,
|
||||
a: MDXLink,
|
||||
}
|
126
src/components/mdx/MDXAccordion.astro
Normal file
126
src/components/mdx/MDXAccordion.astro
Normal file
|
@ -0,0 +1,126 @@
|
|||
---
|
||||
|
||||
// I stole ALLLLLL of this from https://webreaper.dev/posts/astro-accessible-accordion/
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const { title } = Astro.props as Props;
|
||||
|
||||
import HR from "../HR.astro";
|
||||
|
||||
---
|
||||
|
||||
<noscript>
|
||||
<h2 class="text-xl text-title font-serif">
|
||||
{ title }
|
||||
<svg
|
||||
class="inline-flex h-7 w-7"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m6 9l6 6l6-6"></path></svg
|
||||
>
|
||||
</h2>
|
||||
<slot/>
|
||||
</noscript>
|
||||
|
||||
<div class="accordion group relative mb-2 rounded-md border border-crusta-900 dark:border-indigo-400 hidden">
|
||||
<button
|
||||
class="accordion__button flex w-full flex-1 items-center justify-between gap-2 p-3 text-left font-medium transition hover:text-subtitle sm:px-4"
|
||||
type="button"
|
||||
id={`${title} accordion menu button`}
|
||||
aria-expanded="false"
|
||||
aria-controls={`${title} accordion menu content`}
|
||||
>
|
||||
<span class="text-xl font-serif">{title}</span>
|
||||
|
||||
<!-- if using astro and the astro-icon package
|
||||
<Icon
|
||||
name="tabler:chevron-down"
|
||||
aria-hidden="true"
|
||||
class="accordion__chevron h-7 w-7 shrink-0 transition-transform"
|
||||
/>
|
||||
-->
|
||||
|
||||
<!-- use this is not using astro-icon (or another SVG you like) -->
|
||||
<svg
|
||||
class="accordion__chevron h-7 w-7 shrink-0 transition-transform"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
><path
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
d="m6 9l6 6l6-6"></path></svg
|
||||
>
|
||||
|
||||
</button>
|
||||
|
||||
<div
|
||||
id={`${title} accordion menu content`}
|
||||
aria-labelledby={`${title} accordion menu button`}
|
||||
class="accordion__content hidden max-h-0 overflow-hidden px-3 transition-all duration-300 ease-in-out sm:px-4"
|
||||
>
|
||||
<HR class="mt-0"/>
|
||||
<div class="prose mb-4 items-center mt-1 max-w-full transition-[height]">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function accordionSetup() {
|
||||
const menus = document.querySelectorAll(".accordion") as NodeListOf<HTMLElement>; // set this up on each menu
|
||||
menus.forEach((menu) => {
|
||||
menu.classList.remove("hidden");
|
||||
|
||||
const button = menu.querySelector(".accordion__button") as HTMLElement; // the clickable banner
|
||||
const chevron = menu.querySelector(".accordion__chevron") as HTMLElement; // the chevron icon that animates
|
||||
const content = menu.querySelector(".accordion__content") as HTMLElement; // the stuff that's revealed when open
|
||||
|
||||
if (button && content && chevron) {
|
||||
button.addEventListener("click", (event) => {
|
||||
if (!menu.classList.contains("active")) { // if closed, stop having it be closed!
|
||||
menu.classList.add("active");
|
||||
button.setAttribute("aria-expanded", true);
|
||||
|
||||
// we need to set the max height to the height of the accordion object so the animations work correctly
|
||||
content.classList.remove("hidden");
|
||||
content.style.maxHeight = content.scrollHeight + "px";
|
||||
chevron.classList.add("rotate-180");
|
||||
} else { // if open, stop having it be open!!!!
|
||||
menu.classList.remove("active");
|
||||
button.setAttribute("aria-expanded", false);
|
||||
|
||||
content.style.maxHeight = '0px';
|
||||
chevron.classList.remove("rotate-180");
|
||||
|
||||
// make text invisible after animation
|
||||
setTimeout(() => { content.classList.add("hidden") }, 300);
|
||||
}
|
||||
event.preventDefault();
|
||||
return false;
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
accordionSetup();
|
||||
|
||||
document.addEventListener("astro:after-swap", accordionSetup);
|
||||
</script>
|
28
src/components/mdx/MDXLink.astro
Normal file
28
src/components/mdx/MDXLink.astro
Normal file
|
@ -0,0 +1,28 @@
|
|||
---
|
||||
|
||||
import Icon from '../Icon.astro'
|
||||
|
||||
interface Props {
|
||||
href: string
|
||||
class: string
|
||||
}
|
||||
|
||||
const p = Astro.props as Props;
|
||||
|
||||
let external = false;
|
||||
|
||||
if (p.href.includes('https://') || p.href.includes('http://')) {
|
||||
external = true;
|
||||
}
|
||||
|
||||
---
|
||||
|
||||
<a href={p.href} class={p.class} target={external ? '_blank' : '_self'}>
|
||||
<slot/>
|
||||
{external ? (
|
||||
<>
|
||||
<Icon icon="FaExternalLink" class='w-2.5 inline-block align-super fill-crusta-800 fill:stroke-night-400' aria-hidden="true"/>
|
||||
<span class="hidden">opens in a new tab</span>
|
||||
</>
|
||||
) : ''}
|
||||
</a>
|
1
src/svg/FaExternalLink.svg
Normal file
1
src/svg/FaExternalLink.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z"/></svg>
|
After Width: | Height: | Size: 672 B |
Loading…
Add table
Reference in a new issue