mirror of
https://github.com/Snigdha-OS/Snigdha-OS.github.io.git
synced 2025-09-12 07:35:01 +02:00
🛠️ build(astro): nuxtjs to astro
This commit is contained in:
30
src/components/CallToAction.astro
Normal file
30
src/components/CallToAction.astro
Normal file
@@ -0,0 +1,30 @@
|
||||
<div class="container">
|
||||
<div class="call-to-action mt-24 mb-32 flex flex-col items-center gap-12 rounded-xl p-12 md:p-24">
|
||||
<h2 class="text-center text-3xl md:text-5xl">Get this theme on GitHub</h2>
|
||||
<a href="https://github.com/markteekman/accessible-astro-starter" class="text-center text-lg"> Use this theme</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
.call-to-action {
|
||||
color: var(--neutral-900);
|
||||
background-image: linear-gradient(40deg, var(--primary-100), var(--secondary-200));
|
||||
}
|
||||
|
||||
.call-to-action a:not(button),
|
||||
.call-to-action a:not(button):visited {
|
||||
padding: 1rem;
|
||||
color: var(--neutral-900);
|
||||
font-weight: bold;
|
||||
border: 3px solid var(--neutral-900);
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out;
|
||||
|
||||
&:where(:hover, :focus) {
|
||||
color: var(--neutral-100);
|
||||
background-color: var(--neutral-900);
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
</style>
|
17
src/components/ContentMedia.astro
Normal file
17
src/components/ContentMedia.astro
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
import { Media } from 'accessible-astro-components'
|
||||
|
||||
const { imgSrc, reverseImg = false } = Astro.props
|
||||
---
|
||||
|
||||
<section class="my-64">
|
||||
<div class="container">
|
||||
<div class="grid grid-cols-1 gap-24 md:grid-cols-2">
|
||||
{!reverseImg ? <Media class="rounded-lg" src={imgSrc} /> : ''}
|
||||
<div class="space-content flex flex-col justify-center">
|
||||
<slot />
|
||||
</div>
|
||||
{reverseImg ? <Media class="rounded-lg" src={imgSrc} /> : ''}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
15
src/components/Counter.astro
Normal file
15
src/components/Counter.astro
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
const { count, title, sub } = Astro.props
|
||||
---
|
||||
|
||||
<div class="animate text-center">
|
||||
<p class="text-6xl font-bold">{count}</p>
|
||||
<p class="text-4xl font-semibold">{title}</p>
|
||||
<p class="text-2xl">{sub}</p>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
div > p:first-child {
|
||||
color: var(--action-color);
|
||||
}
|
||||
</style>
|
67
src/components/Feature.astro
Normal file
67
src/components/Feature.astro
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
|
||||
const { icon = 'mdi:rocket', title = 'Title' } = Astro.props
|
||||
---
|
||||
|
||||
<div class="feature flex flex-col gap-4">
|
||||
<Icon name={icon} />
|
||||
<div class="content">
|
||||
<h3>{title}</h3>
|
||||
<p>
|
||||
<slot>Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic, corporis.</slot>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../assets/scss/base/breakpoint' as *;
|
||||
|
||||
.feature {
|
||||
position: relative;
|
||||
width: calc(100% - 0.5rem);
|
||||
padding: 2rem;
|
||||
|
||||
> * {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
@include breakpoint(large) {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
&::before {
|
||||
inset: 0;
|
||||
background-color: var(--neutral-100);
|
||||
border: 3px solid var(--neutral-700);
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 0 0 6px var(--neutral-100);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
&::after {
|
||||
background-color: var(--action-color);
|
||||
inset: 1rem -0.85rem -0.85rem 1rem;
|
||||
border-radius: 1rem;
|
||||
z-index: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:global(.feature [data-icon]) {
|
||||
height: auto;
|
||||
width: 4rem;
|
||||
color: var(--action-color);
|
||||
}
|
||||
|
||||
:global(.darkmode .feature::before) {
|
||||
background-color: var(--dark-100);
|
||||
box-shadow: 0 0 0 6px var(--dark-100);
|
||||
}
|
||||
</style>
|
18
src/components/Footer.astro
Normal file
18
src/components/Footer.astro
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
import CallToAction from './CallToAction.astro'
|
||||
|
||||
const currentYear = new Date().getFullYear()
|
||||
---
|
||||
|
||||
<footer>
|
||||
<CallToAction />
|
||||
<section class="py-8">
|
||||
<div class="container">
|
||||
<p>
|
||||
© {currentYear} - Starter Theme for <a href="https://astro.build/">Astro</a>. Made with ❤️ by <a
|
||||
href="https://github.com/markteekman">Mark Teekman</a
|
||||
>.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
</footer>
|
65
src/components/Header.astro
Normal file
65
src/components/Header.astro
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import Navigation from '../components/Navigation.astro'
|
||||
import { SkipLinks } from 'accessible-astro-components'
|
||||
import { Icon } from 'astro-icon/components'
|
||||
---
|
||||
|
||||
<header>
|
||||
<SkipLinks />
|
||||
<Navigation>
|
||||
<li class="menu-item">
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="/blog/">Blog</a>
|
||||
</li>
|
||||
<li class="menu-item has-dropdown">
|
||||
<button aria-haspopup="true" aria-expanded="false">Example Pages</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="submenu-item">
|
||||
<a href="/mdx-page/">MDX Page</a>
|
||||
</li>
|
||||
<li class="submenu-item">
|
||||
<a href="/markdown-page/">Markdown Page</a>
|
||||
</li>
|
||||
<li class="submenu-item">
|
||||
<a href="/accessible-components">Accessible Components</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="https://accessible-astro.dev" title="external link" rel="external noopener noreferrer">External Link</a>
|
||||
</li>
|
||||
<li class="menu-item type-icon">
|
||||
<a href="https://github.com/markteekman/accessible-astro-starter" title="Go to the GitHub page">
|
||||
<Icon name="ion:logo-github" />
|
||||
</a>
|
||||
</li>
|
||||
</Navigation>
|
||||
</header>
|
||||
|
||||
<style lang="scss" is:global>
|
||||
@use '../assets/scss/base/outline' as *;
|
||||
|
||||
header {
|
||||
.type-icon a {
|
||||
display: block;
|
||||
|
||||
[data-icon] {
|
||||
height: auto;
|
||||
margin-top: -4px;
|
||||
width: 30px;
|
||||
|
||||
path {
|
||||
fill: var(--action-color);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
[data-icon] path {
|
||||
fill: var(--action-color-state);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
47
src/components/Hero.astro
Normal file
47
src/components/Hero.astro
Normal file
@@ -0,0 +1,47 @@
|
||||
---
|
||||
import { Icon } from 'astro-icon/components'
|
||||
|
||||
const { src = '/astronaut-hero-img.webp' } = Astro.props
|
||||
---
|
||||
|
||||
<section class="hero my-24">
|
||||
<div class="container">
|
||||
<div class="grid grid-cols-1 items-center gap-24 lg:grid-cols-2">
|
||||
<div class="flex flex-col items-center gap-8 md:items-start">
|
||||
<h1 class="text-center text-6xl md:text-left lg:text-8xl">
|
||||
<slot><span class="text-gradient">Accessible</span> Starter for Astro</slot>
|
||||
</h1>
|
||||
<div class="flex flex-col gap-3 min-[500px]:flex-row">
|
||||
<a class="button has-icon" href="https://github.com/markteekman/accessible-astro-starter">
|
||||
<Icon name="ion:star-outline" />
|
||||
Star on GitHub
|
||||
</a>
|
||||
<a
|
||||
class="button has-icon color-secondary"
|
||||
href="https://github.com/markteekman/accessible-astro-starter/blob/main/README.md"
|
||||
>
|
||||
<Icon name="ion:bookmark-outline" />
|
||||
Read the Docs
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<img class="hidden lg:block" src={src} alt="" decoding="async" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style lang="scss">
|
||||
.text-gradient {
|
||||
background: linear-gradient(315deg, var(--primary-200) 25%, var(--secondary-500));
|
||||
background-clip: border-box;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
:global(.darkmode .text-gradient) {
|
||||
background: linear-gradient(315deg, var(--primary-200) 25%, var(--secondary-400));
|
||||
background-clip: border-box;
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
</style>
|
415
src/components/Navigation.astro
Normal file
415
src/components/Navigation.astro
Normal file
@@ -0,0 +1,415 @@
|
||||
---
|
||||
import ResponsiveToggle from './ResponsiveToggle.astro'
|
||||
import { DarkMode } from 'accessible-astro-components'
|
||||
import { Image } from 'astro:assets'
|
||||
import logo from '../assets/img/logo.svg'
|
||||
---
|
||||
|
||||
<div id="main-navigation" class="is-desktop py-8">
|
||||
<div class="container">
|
||||
<a href="/" class="flex items-center gap-2 !no-underline">
|
||||
<Image src={logo} alt="Your Logo" width="47" height="37" />
|
||||
<span class="font-bold">Accessible Astro</span>
|
||||
</a>
|
||||
<div class="wrapper">
|
||||
<nav class="desktop-menu" aria-label="Main navigation desktop">
|
||||
<ul class="menu">
|
||||
<slot />
|
||||
</ul>
|
||||
</nav>
|
||||
<DarkMode />
|
||||
<ResponsiveToggle />
|
||||
</div>
|
||||
<nav class="mobile-menu" aria-label="Main navigation mobile">
|
||||
<ul class="menu">
|
||||
<slot />
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
// variables
|
||||
const mainNav = document.querySelector('#main-navigation')
|
||||
const mainMenu = mainNav.querySelector('ul')
|
||||
const dropdownMenus = [...document.querySelectorAll('.has-dropdown button')]
|
||||
|
||||
// functions
|
||||
const setActiveMenuItem = () => {
|
||||
const mobileDesktopMenus = mainNav.querySelectorAll('nav > ul')
|
||||
const currenPathname = window.location.pathname
|
||||
|
||||
mobileDesktopMenus.forEach((menu) => {
|
||||
const menuItems = [...menu.querySelectorAll('a:not([rel*="external"])')] as HTMLAnchorElement[]
|
||||
|
||||
menuItems.forEach((menuItem) => {
|
||||
if (currenPathname.includes(menuItem.pathname.replaceAll('/', '')) && menuItem.textContent !== 'Home') {
|
||||
menuItem.classList.add('is-active')
|
||||
menuItem.setAttribute('aria-current', 'page')
|
||||
} else if (menuItem.textContent === 'Home' && currenPathname === '/') {
|
||||
menuItem.classList.add('is-active')
|
||||
menuItem.setAttribute('aria-current', 'page')
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const checkMenuSize = () => {
|
||||
const mainNavWidth = mainNav.getBoundingClientRect().width
|
||||
const desktopMenuWidth = document.querySelector('.desktop-menu').getBoundingClientRect().width
|
||||
const logoWidthBuffer = 300
|
||||
const totalMenuWidth = Math.round(desktopMenuWidth) + logoWidthBuffer
|
||||
|
||||
if (totalMenuWidth >= mainNavWidth) {
|
||||
mainNav.classList.remove('is-desktop')
|
||||
mainNav.classList.add('is-mobile')
|
||||
} else if (totalMenuWidth <= mainNavWidth) {
|
||||
mainNav.classList.add('is-desktop')
|
||||
mainNav.classList.remove('is-mobile')
|
||||
}
|
||||
}
|
||||
|
||||
const isOutOfViewport = (element) => {
|
||||
const elementBounds = element.getBoundingClientRect()
|
||||
return elementBounds.right > (window.innerWidth || document.documentElement.clientWidth)
|
||||
}
|
||||
|
||||
const openDropdownMenu = (dropdownMenu) => {
|
||||
const dropdownList = dropdownMenu.parentNode.querySelector('ul')
|
||||
|
||||
dropdownMenu.classList.add('show')
|
||||
dropdownMenu.setAttribute('aria-expanded', 'true')
|
||||
|
||||
if (isOutOfViewport(dropdownList)) {
|
||||
dropdownList.style.left = 'auto'
|
||||
}
|
||||
}
|
||||
|
||||
const closeDropdownMenu = (dropdownMenu) => {
|
||||
dropdownMenu.classList.remove('show')
|
||||
dropdownMenu.setAttribute('aria-expanded', 'false')
|
||||
}
|
||||
|
||||
const closeAllDropdownMenus = () => {
|
||||
for (let i = 0; i < dropdownMenus.length; i++) {
|
||||
closeDropdownMenu(dropdownMenus[i])
|
||||
}
|
||||
}
|
||||
|
||||
const toggleDropdownMenu = (event) => {
|
||||
if (event.target.getAttribute('aria-expanded') === 'false') {
|
||||
closeAllDropdownMenus()
|
||||
openDropdownMenu(event.target)
|
||||
} else {
|
||||
closeDropdownMenu(event.target)
|
||||
}
|
||||
}
|
||||
|
||||
// execution
|
||||
mainMenu &&
|
||||
mainMenu.addEventListener('keydown', (event) => {
|
||||
const element = event.target as Element
|
||||
const currentMenuItem = element.closest('li')
|
||||
const menuItems = [...mainMenu.querySelectorAll('.menu-item')]
|
||||
const currentDropdownMenu = element.closest('.has-dropdown button')
|
||||
const currentDropdownMenuItem = element.closest('.has-dropdown li')
|
||||
const currentIndex = menuItems.findIndex((item) => item === currentMenuItem)
|
||||
|
||||
const key = event.key
|
||||
let targetItem
|
||||
|
||||
if (key === 'ArrowRight') {
|
||||
if (menuItems.indexOf(currentMenuItem) === menuItems.length - 1) {
|
||||
targetItem = menuItems[0]
|
||||
} else {
|
||||
targetItem = menuItems[currentIndex + 1]
|
||||
}
|
||||
}
|
||||
|
||||
if (key === 'ArrowLeft') {
|
||||
if (menuItems.indexOf(currentMenuItem) === 0) {
|
||||
targetItem = menuItems[menuItems.length - 1]
|
||||
} else {
|
||||
targetItem = menuItems[currentIndex - 1]
|
||||
}
|
||||
}
|
||||
|
||||
if (key === 'Escape') {
|
||||
targetItem = menuItems[0]
|
||||
}
|
||||
|
||||
if (currentDropdownMenu) {
|
||||
const firstDropdownItem = currentDropdownMenu.nextElementSibling.querySelector('li')
|
||||
|
||||
if (key === 'ArrowDown') {
|
||||
event.preventDefault()
|
||||
openDropdownMenu(currentDropdownMenu)
|
||||
targetItem = firstDropdownItem
|
||||
}
|
||||
|
||||
if (key === 'Escape') {
|
||||
closeDropdownMenu(currentDropdownMenu)
|
||||
}
|
||||
}
|
||||
|
||||
if (currentDropdownMenuItem) {
|
||||
const currentDropdownList = currentDropdownMenuItem.parentNode
|
||||
const dropdownMenuItems = [...currentDropdownList.querySelectorAll('li')]
|
||||
const currentIndex = dropdownMenuItems.findIndex((item) => item === currentDropdownMenuItem)
|
||||
|
||||
if (key === 'ArrowDown') {
|
||||
event.preventDefault()
|
||||
|
||||
if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === dropdownMenuItems.length - 1) {
|
||||
targetItem = dropdownMenuItems[0]
|
||||
} else {
|
||||
targetItem = dropdownMenuItems[currentIndex + 1]
|
||||
}
|
||||
}
|
||||
|
||||
if (key === 'ArrowUp') {
|
||||
event.preventDefault()
|
||||
|
||||
if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === 0) {
|
||||
targetItem = dropdownMenuItems[dropdownMenuItems.length - 1]
|
||||
} else {
|
||||
targetItem = dropdownMenuItems[currentIndex - 1]
|
||||
}
|
||||
}
|
||||
|
||||
if (key === 'Escape') {
|
||||
const currentDropdownMenu = (currentDropdownList as Element).previousElementSibling
|
||||
targetItem = currentDropdownMenu.parentNode
|
||||
closeAllDropdownMenus()
|
||||
}
|
||||
|
||||
if (key === 'Tab') {
|
||||
const currentDropdownMenu = (currentDropdownList as Element).previousElementSibling
|
||||
|
||||
if (dropdownMenuItems.indexOf(currentDropdownMenuItem as HTMLLIElement) === dropdownMenuItems.length - 1) {
|
||||
closeDropdownMenu(currentDropdownMenu)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (targetItem) {
|
||||
targetItem.querySelector('a, button, input').focus()
|
||||
}
|
||||
})
|
||||
|
||||
dropdownMenus &&
|
||||
dropdownMenus.forEach((dropdownMenu) => {
|
||||
dropdownMenu.addEventListener('click', toggleDropdownMenu)
|
||||
})
|
||||
|
||||
setActiveMenuItem()
|
||||
checkMenuSize()
|
||||
|
||||
window.addEventListener('resize', checkMenuSize)
|
||||
window.addEventListener('click', (event) => {
|
||||
const element = event.target as Element
|
||||
if (!element.hasAttribute('aria-haspopup') && !element.classList.contains('submenu-item')) {
|
||||
closeAllDropdownMenus()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" is:global>
|
||||
@use '../assets/scss/base/breakpoint' as *;
|
||||
@use '../assets/scss/base/outline' as *;
|
||||
|
||||
#main-navigation {
|
||||
> .container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&.is-desktop {
|
||||
.desktop-menu {
|
||||
visibility: visible;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.mobile-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.darkmode-toggle {
|
||||
margin-top: -6px;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-mobile {
|
||||
flex-direction: column;
|
||||
|
||||
.mobile-menu {
|
||||
display: none;
|
||||
|
||||
&.show {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.desktop-menu {
|
||||
visibility: hidden;
|
||||
z-index: -99;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.responsive-toggle {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
nav {
|
||||
> ul {
|
||||
display: flex;
|
||||
gap: 1.5rem;
|
||||
list-style-type: none;
|
||||
|
||||
a,
|
||||
button {
|
||||
text-decoration: none;
|
||||
font-size: 1.125rem;
|
||||
line-height: 1.6875rem;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus,
|
||||
.is-active,
|
||||
.has-dropdown > button:hover,
|
||||
.has-dropdown > button:focus {
|
||||
text-decoration: underline;
|
||||
text-decoration-thickness: 1px;
|
||||
text-decoration-style: wavy;
|
||||
text-underline-offset: 7px;
|
||||
}
|
||||
|
||||
.is-active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-menu {
|
||||
flex-basis: 100%;
|
||||
padding: 2rem 0;
|
||||
|
||||
> ul {
|
||||
flex-direction: column;
|
||||
|
||||
ul {
|
||||
position: relative;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
a,
|
||||
button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
padding: 0.5rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.has-dropdown {
|
||||
position: relative;
|
||||
|
||||
> button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0;
|
||||
margin-top: -1px;
|
||||
border: none;
|
||||
color: var(--action-color);
|
||||
|
||||
&:hover {
|
||||
color: var(--action-color-state);
|
||||
|
||||
&::after {
|
||||
border-color: var(--action-color-state);
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
width: 0.85rem;
|
||||
height: 0.75em;
|
||||
margin-top: -0.25rem;
|
||||
border-style: solid;
|
||||
border-width: 0.2em 0.2em 0 0;
|
||||
border-color: var(--action-color);
|
||||
transform: rotate(135deg);
|
||||
}
|
||||
|
||||
&.show {
|
||||
&::after {
|
||||
margin-top: 0.25rem;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
~ ul {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
display: none;
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
min-width: 260px;
|
||||
top: 125%;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
padding: 1rem;
|
||||
background-color: var(--neutral-background);
|
||||
border: 2px solid black;
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.darkmode-toggle {
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
svg path {
|
||||
fill: var(--action-color);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg path {
|
||||
fill: var(--action-color-state);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus {
|
||||
@include outline;
|
||||
|
||||
&:not(:focus-visible) {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
64
src/components/ResponsiveToggle.astro
Normal file
64
src/components/ResponsiveToggle.astro
Normal file
@@ -0,0 +1,64 @@
|
||||
<button class="responsive-toggle" aria-expanded="false" aria-label="Open menu navigation">
|
||||
<svg width="26" height="21" aria-hidden="true" fill="var(--action-color)" xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M2 1.667h24m-24 8h24m-24 8h24"
|
||||
stroke="var(--action-color)"
|
||||
stroke-width="2.667"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"></path></svg
|
||||
>
|
||||
</button>
|
||||
|
||||
<script>
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
// variables
|
||||
const responsiveToggle = document.querySelector('.responsive-toggle')
|
||||
|
||||
// functions
|
||||
const openMenu = (toggle) => {
|
||||
toggle.setAttribute('aria-expanded', true)
|
||||
toggle.setAttribute('aria-label', 'Close menu navigation')
|
||||
toggle.innerHTML = `<svg width="20" height="20" aria-hidden="true" fill="var(--action-color)" xmlns="http://www.w3.org/2000/svg"><path d="M10 10 2 2m8 8 8 8m-8-8 8-8m-8 8-8 8" stroke="var(--action-color)" stroke-width="2.667" stroke-linecap="round" stroke-linejoin="round"/></svg>`
|
||||
}
|
||||
|
||||
const closeMenu = (toggle) => {
|
||||
toggle.setAttribute('aria-expanded', false)
|
||||
toggle.setAttribute('aria-label', 'Open menu navigation')
|
||||
toggle.innerHTML = `<svg width="26" height="21" aria-hidden="true" fill="var(--action-color)" xmlns="http://www.w3.org/2000/svg"><path d="M2 1.667h24m-24 8h24m-24 8h24" stroke="var(--action-color)" stroke-width="2.667" stroke-linecap="round" stroke-linejoin="round"/></svg>`
|
||||
}
|
||||
|
||||
// execution
|
||||
responsiveToggle.addEventListener('click', (_) => {
|
||||
const mobileNavigation = document.querySelector('.mobile-menu')
|
||||
|
||||
mobileNavigation.classList.toggle('show')
|
||||
mobileNavigation.classList.contains('show') ? openMenu(responsiveToggle) : closeMenu(responsiveToggle)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@use '../assets/scss/base/breakpoint' as *;
|
||||
@use '../assets/scss/base/outline' as *;
|
||||
|
||||
.responsive-toggle {
|
||||
display: none;
|
||||
padding: 0;
|
||||
margin-top: 6px;
|
||||
border: none;
|
||||
|
||||
svg {
|
||||
width: 30px;
|
||||
|
||||
path {
|
||||
transition: fill 0.2s ease-in-out;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
svg path {
|
||||
fill: var(--primary-400);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
26
src/components/SiteMeta.astro
Normal file
26
src/components/SiteMeta.astro
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
import { ViewTransitions } from 'astro:transitions'
|
||||
|
||||
const { title, description, url, image, author } = Astro.props
|
||||
|
||||
let subtitle = 'Accessible Astro Starter'
|
||||
---
|
||||
|
||||
<!-- general meta -->
|
||||
<meta name="title" content={`${title} - ${subtitle}`} />
|
||||
<meta name="description" content={description} />
|
||||
<meta name="author" content={author} />
|
||||
|
||||
<!-- open graph -->
|
||||
<meta property="og:title" content={`${title} - ${subtitle}`} />
|
||||
<meta property="og:description" content={description} />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={url} />
|
||||
<meta property="og:image" content={Astro.site ? `${Astro.site}${image}` : image} />
|
||||
|
||||
<!-- twitter card -->
|
||||
|
||||
<!-- page title -->
|
||||
<title>{title} - {subtitle}</title>
|
||||
|
||||
<ViewTransitions />
|
Reference in New Issue
Block a user