Skip to content

feat: add Toggle component with default icons #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 16, 2025
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
58 changes: 25 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,41 +31,33 @@ npm install astro-theme-toggle
</head>
```

2. Add a button to your `<body>` to toggle the theme:
2. Add the `Toggle` component to your `<body>` to toggle the theme:

```astro
<button id="theme-toggle">
<!-- https://lucide.dev/icons/moon -->
<svg class="icon-moon" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-moon"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></svg>
<!-- https://lucide.dev/icons/sun -->
<svg class="icon-sun" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
</button>

<script>
import { handleToggleClick } from 'astro-theme-toggle'
const addListener = () => {
document
.getElementById('theme-toggle')
?.addEventListener('click', handleToggleClick)
}
addListener()
document.addEventListener('astro:after-swap', addListener)
</script>

<style is:global>
.icon-sun {
display: block;
}
.icon-moon {
display: none;
}
.dark .icon-sun {
display: none;
}
.dark .icon-moon {
display: block;
}
</style>
---
import { Toggle } from 'astro-theme-toggle'
---

<Toggle style="width: 32px; height: 32px;" />
```

3. You can customize the icon by passing a `Fragment` with the `icon-light` and `icon-dark` slots.

```astro
---
import { Toggle } from 'astro-theme-toggle'
import MyLightIcon from './my-light-icon.astro'
import MyDarkIcon from './my-dark-icon.astro'
---

<Toggle style="width: 32px; height: 32px;">
<Fragment slot="icon-light">
<MyLightIcon />
</Fragment>
<Fragment slot="icon-dark">
<MyDarkIcon />
</Fragment>
</Toggle>
```

## Live Examples
Expand Down
10 changes: 10 additions & 0 deletions lib/icons/lucide-moon.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
/*
https://icones.js.org/collection/lucide?s=moon&icon=lucide:moon

LICENSE: ISC

https://github.com/lucide-icons/lucide/blob/main/LICENSE
*/
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3a6 6 0 0 0 9 9a9 9 0 1 1-9-9"/></svg>
10 changes: 10 additions & 0 deletions lib/icons/lucide-sun.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
/*
https://icones.js.org/collection/lucide?s=sun&icon=lucide:sun

LICENSE: ISC

https://github.com/lucide-icons/lucide/blob/main/LICENSE
*/
}
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><circle cx="12" cy="12" r="4"/><path d="M12 2v2m0 16v2M4.93 4.93l1.41 1.41m11.32 11.32l1.41 1.41M2 12h2m16 0h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></g></svg>
1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export { handleToggleClick } from './handle-toggle-click'
export { getTheme, setTheme } from './theme'
export { default as ThemeScript } from './theme-script.astro'
export { default as Toggle } from './toggle.astro'
71 changes: 71 additions & 0 deletions lib/toggle.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
import type { HTMLAttributes } from 'astro/types'

import IconSunSvg from './icons/lucide-sun.astro'
import IconMoonSvg from './icons/lucide-moon.astro'

type Props = HTMLAttributes<'button'>
const props: Props = Astro.props
---

<button id="astro-theme-toggle" {...props}>
<div class="astro-theme-toggle-icon-light">
<slot name="icon-light">
<IconSunSvg />
</slot>
</div>
<div class="astro-theme-toggle-icon-dark">
<slot name="icon-dark">
<IconMoonSvg />
</slot>
</div>
</button>

<script>
import { handleToggleClick } from './handle-toggle-click'
const addListener = () => {
document
.getElementById('astro-theme-toggle')
?.addEventListener('click', handleToggleClick)
}
addListener()
document.addEventListener('astro:after-swap', addListener)
</script>

<style is:global>
:where(#astro-theme-toggle) {
padding: 0;
margin: 0;
border: none;
background: none;
cursor: pointer;
width: 100%;
height: 100%;
}

.astro-theme-toggle-icon-light,
.astro-theme-toggle-icon-dark {
width: 100%;
height: 100%;

& * {
display: block;
}
}

.astro-theme-toggle-icon-light {
display: block;

.dark & {
display: none;
}
}

.astro-theme-toggle-icon-dark {
display: none;

.dark & {
display: block;
}
}
</style>
23 changes: 0 additions & 23 deletions website/components/icon-moon-svg.astro

This file was deleted.

27 changes: 0 additions & 27 deletions website/components/icon-sun-svg.astro

This file was deleted.

1 change: 1 addition & 0 deletions website/components/nav.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import NavLink from './nav-link.astro'

<div class="nav">
<NavLink href="/">Astro Example</NavLink>
<NavLink href="/custom">Custom Icons</NavLink>
<NavLink href="/react">React Example</NavLink>
<NavLink href="/vue">Vue Example</NavLink>
</div>
Expand Down
12 changes: 12 additions & 0 deletions website/components/theme-toggle-button-custom.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
import { Toggle } from 'astro-theme-toggle'
---

<Toggle style="width: 64px; height: 64px;">
<Fragment slot="icon-light">
<span style="font-size: 64px;">🌞</span>
</Fragment>
<Fragment slot="icon-dark">
<span style="font-size: 64px;">🌚</span>
</Fragment>
</Toggle>
23 changes: 7 additions & 16 deletions website/components/theme-toggle-button.astro
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
---
import './icon.css'
import IconSunSvg from './icon-sun-svg.astro'
import IconMoonSvg from './icon-moon-svg.astro'
import { Toggle } from 'astro-theme-toggle'
---

<button id="theme-toggle">
<IconSunSvg class="icon-sun" />
<IconMoonSvg class="icon-moon" />
</button>
<Toggle class="theme-toggle" />

<script>
import { handleToggleClick } from 'astro-theme-toggle'
const addListener = () => {
document
.getElementById('theme-toggle')
?.addEventListener('click', handleToggleClick)
<style>
.theme-toggle {
width: 24px;
height: 24px;
}
addListener()
document.addEventListener('astro:after-swap', addListener)
</script>
</style>
7 changes: 5 additions & 2 deletions website/layouts/Layout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ import LogoBackgroundAstro from '../components/logo-background-astro.astro'
}

.instructions {
margin-bottom: 5rem;
text-align: center;
margin-bottom: 3rem;
min-height: 6rem;
display: flex;
justify-content: center;
align-items: center;
}
</style>
22 changes: 22 additions & 0 deletions website/pages/custom.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
import { Code } from 'astro-expressive-code/components'
import headCode from '../components/head.astro?raw'
import Nav from '../components/nav.astro'
import ThemeToggleButton from '../components/theme-toggle-button-custom.astro'
import buttonCode from '../components/theme-toggle-button-custom.astro?raw'
import Layout from '../layouts/Layout.astro'
---

<Layout>
<main>
<div class="instructions">
<ThemeToggleButton />
</div>
<Nav />

<div style="display: flex; flex-direction: column; gap: 20px;">
<Code code={buttonCode} lang="astro" title="theme-toggle-button.astro" />
<Code code={headCode} lang="astro" title="head.astro" />
</div>
</main>
</Layout>
2 changes: 0 additions & 2 deletions website/pages/index.astro
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
import { Code } from 'astro-expressive-code/components'
import headCode from '../components/head.astro?raw'
import iconCssCode from '../components/icon.css?raw'
import Nav from '../components/nav.astro'
import ThemeToggleButton from '../components/theme-toggle-button.astro'
import buttonCode from '../components/theme-toggle-button.astro?raw'
Expand All @@ -18,7 +17,6 @@ import Layout from '../layouts/Layout.astro'
<div style="display: flex; flex-direction: column; gap: 20px;">
<Code code={buttonCode} lang="astro" title="theme-toggle-button.astro" />
<Code code={headCode} lang="astro" title="head.astro" />
<Code code={iconCssCode} lang="css" title="icon.css" />
</div>
</main>
</Layout>
Loading