Skip to content

Commit

Permalink
Merge pull request #60 from david-abell/view-transitions-dark-mode
Browse files Browse the repository at this point in the history
Support view transitions for dark mode toggle & Modal
  • Loading branch information
markteekman committed Oct 22, 2023
2 parents b89726d + f5cc04c commit 3fe847b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 49 deletions.
76 changes: 43 additions & 33 deletions DarkMode.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
type Props = Record<string, never>
---
<button class="darkmode-toggle" aria-pressed="false" aria-label="Enable dark mode">
<button class="darkmode-toggle" aria-pressed="false" aria-label="Enable dark mode" transition:persist>
<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="32" height="32" viewBox="0 0 24 24"
><path
fill="currentColor"
Expand All @@ -12,44 +12,54 @@ type Props = Record<string, never>
</button>
<script is:inline>
// variables
let darkMode = localStorage.getItem('darkMode')
const darkModeToggle = document.querySelector('.darkmode-toggle')
// functions
const enableDarkMode = (store = true) => {
document.body.classList.add('darkmode')
darkModeToggle.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="32" height="32" viewBox="0 0 24 24"><path fill-rule="evenodd" clip-rule="evenodd" d="M13 3a1 1 0 1 0-2 0v1a1 1 0 1 0 2 0V3zM5.707 4.293a1 1 0 0 0-1.414 1.414l1 1a1 1 0 0 0 1.414-1.414l-1-1zm14 0a1 1 0 0 0-1.414 0l-1 1a1 1 0 0 0 1.414 1.414l1-1a1 1 0 0 0 0-1.414zM12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10zm-9 4a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2H3zm17 0a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2h-1zM6.707 18.707a1 1 0 1 0-1.414-1.414l-1 1a1 1 0 1 0 1.414 1.414l1-1zm12-1.414a1 1 0 0 0-1.414 1.414l1 1a1 1 0 0 0 1.414-1.414l-1-1zM13 20a1 1 0 1 0-2 0v1a1 1 0 1 0 2 0v-1z" fill="currentColor"/></svg>`
darkModeToggle.setAttribute('aria-pressed', 'true')
darkModeToggle.setAttribute('aria-label', 'Disable dark mode')
if (store) localStorage.setItem('darkMode', 'enabled')
}
// variables
let darkMode = localStorage.getItem('darkMode')
const darkModeToggle = document.querySelector('.darkmode-toggle')
const disableDarkMode = (store = true) => {
document.body.classList.remove('darkmode')
darkModeToggle.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M9.353 3C5.849 4.408 3 7.463 3 11.47A9.53 9.53 0 0 0 12.53 21c4.007 0 7.062-2.849 8.47-6.353C8.17 17.065 8.14 8.14 9.353 3z"/></svg>`
darkModeToggle.setAttribute('aria-pressed', 'false')
darkModeToggle.setAttribute('aria-label', 'Enable dark mode')
if (store) localStorage.setItem('darkMode', 'disabled')
}
// functions
const enableDarkMode = (store = true) => {
document.body.classList.add('darkmode')
darkModeToggle.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="32" height="32" viewBox="0 0 24 24"><path fill-rule="evenodd" clip-rule="evenodd" d="M13 3a1 1 0 1 0-2 0v1a1 1 0 1 0 2 0V3zM5.707 4.293a1 1 0 0 0-1.414 1.414l1 1a1 1 0 0 0 1.414-1.414l-1-1zm14 0a1 1 0 0 0-1.414 0l-1 1a1 1 0 0 0 1.414 1.414l1-1a1 1 0 0 0 0-1.414zM12 7a5 5 0 1 0 0 10 5 5 0 0 0 0-10zm-9 4a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2H3zm17 0a1 1 0 1 0 0 2h1a1 1 0 1 0 0-2h-1zM6.707 18.707a1 1 0 1 0-1.414-1.414l-1 1a1 1 0 1 0 1.414 1.414l1-1zm12-1.414a1 1 0 0 0-1.414 1.414l1 1a1 1 0 0 0 1.414-1.414l-1-1zM13 20a1 1 0 1 0-2 0v1a1 1 0 1 0 2 0v-1z" fill="currentColor"/></svg>`
darkModeToggle.setAttribute('aria-pressed', 'true')
darkModeToggle.setAttribute('aria-label', 'Disable dark mode')
if (store) localStorage.setItem('darkMode', 'enabled')
}
const checkPreference = () => {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
enableDarkMode(false); // don't set localStorage from preferences to respect future changes in client prefs
} else {
disableDarkMode(false);
}
const disableDarkMode = (store = true) => {
document.body.classList.remove('darkmode')
darkModeToggle.innerHTML = `<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" width="32" height="32" viewBox="0 0 24 24"><path fill="currentColor" d="M9.353 3C5.849 4.408 3 7.463 3 11.47A9.53 9.53 0 0 0 12.53 21c4.007 0 7.062-2.849 8.47-6.353C8.17 17.065 8.14 8.14 9.353 3z"/></svg>`
darkModeToggle.setAttribute('aria-pressed', 'false')
darkModeToggle.setAttribute('aria-label', 'Enable dark mode')
if (store) localStorage.setItem('darkMode', 'disabled')
}
const checkPreference = () => {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
enableDarkMode(false) // don't set localStorage from preferences to respect future changes in client prefs
} else {
disableDarkMode(false)
}
}
// execution
if (darkMode === 'enabled') enableDarkMode()
if (darkMode === 'disabled') disableDarkMode()
if (!darkMode) checkPreference()
darkModeToggle.addEventListener('click', () => {
darkMode = document.body.classList.contains('darkmode')
// execution
!darkMode ? enableDarkMode() : disableDarkMode()
})
// Listen for view transitions
document.addEventListener('astro:after-swap', () => {
// Setup
darkMode = localStorage.getItem('darkMode')
// Execution
if (darkMode === 'enabled') enableDarkMode()
if (darkMode === 'disabled') disableDarkMode()
if (!darkMode) checkPreference()
darkModeToggle.addEventListener('click', () => {
darkMode = document.body.classList.contains('darkmode')
!darkMode ? enableDarkMode() : disableDarkMode()
})
})
</script>
53 changes: 39 additions & 14 deletions Modal.astro
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const { triggerId, title, closeText = 'Close' } = Astro.props
| HTMLDetailsElement

// variables
const modals = document.querySelectorAll<HTMLDialogElement>('.modal')
let modals = document.querySelectorAll<HTMLDialogElement>('.modal')

// abort controllers for global event listeners
let trapFocusController: AbortController | undefined
Expand Down Expand Up @@ -131,6 +131,27 @@ const { triggerId, title, closeText = 'Close' } = Astro.props
})

window.closeModal = closeModal

// Listen for view transitions
document.addEventListener('astro:after-swap', () => {
// reset variables
modals = document.querySelectorAll<HTMLDialogElement>('.modal')

// execution
modals.forEach((modal) => {
const modalId = modal.getAttribute('aria-labelledby')
const modalCloseButton = modal.querySelector('.modal__close button')
const modalTrigger = document.querySelector(`#${modalId}`)

if (!modalTrigger) {
throw new Error(`Trigger element not found. \n
Did you forget to add a trigger element with id: "${modalId}"?`)
}

modalTrigger.addEventListener('click', () => openModal(modal))
modalCloseButton!.addEventListener('click', closeModal)
})
})
</script>

<style is:global>
Expand All @@ -139,30 +160,18 @@ const { triggerId, title, closeText = 'Close' } = Astro.props
filter: blur(6px);
}

.modal {
:where(.modal) {
color: black;
background-color: white;
border: 0.5rem solid black;
border-radius: 1rem;
padding: 0;
}

.modal .modal__inner {
opacity: 1;
}

.modal__inner {
width: clamp(30ch, 70%, 75ch);
color: black;
background-color: white;
border-radius: 1rem;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}

.modal__inner {
width: 100%;
height: 100%;
}

.modal__content {
Expand All @@ -182,6 +191,7 @@ const { triggerId, title, closeText = 'Close' } = Astro.props
background-color: lightgrey;
border-bottom-left-radius: 0.4rem;
border-bottom-right-radius: 0.4rem;
color: black;
text-align: right;
transition: background-color 0.15s ease-in-out;
width: 100%;
Expand All @@ -194,4 +204,19 @@ const { triggerId, title, closeText = 'Close' } = Astro.props
background-color: grey;
text-decoration: underline;
}

/* Animation */
dialog[open],
dialog[open]::backdrop {
animation: fadein 0.3s ease-in-out;
}

@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,12 @@ You can apply your own styles by either setting the individual properties using
```scss
<style lang="scss" is:global>
body {
.modal {
color: purple;
background-color: gold;
}

.modal__inner {
color: purple;
background-color: gold;
border-color: orange;
}

Expand All @@ -321,6 +324,7 @@ You can apply your own styles by either setting the individual properties using
}

.modal__close button {
color: white;
background-color: blue;

&:hover,
Expand Down

0 comments on commit 3fe847b

Please sign in to comment.