Skip to content
Open
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
2 changes: 1 addition & 1 deletion src/lib/components/NewsletterSignup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

<div class="newsletter-signup">
<div class="newsletter-content">
<h3>{headingText}</h3>
<h3 class="toc-exclude">{headingText}</h3>
<p>{descriptionText}</p>

<!-- Direct POST to Substack API in new tab -->
Expand Down
148 changes: 145 additions & 3 deletions src/lib/components/Toc.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,88 @@
import List from 'lucide-svelte/icons/list'
import '$lib/components/Card.css'
import Backdrop from '$lib/components/Backdrop.svelte'
import { onMount } from 'svelte'

let desktop: boolean | undefined
let open: boolean | undefined
let headings: HTMLHeadingElement[] | undefined
let sidebarTop = 16 // Initial top offset in rem (below banner)

// Track scroll to adjust sidebar position
onMount(() => {
const bannerHeight = 275 // Scroll distance in pixels for full transition (higher = slower)
const minTop = 1 // Minimum top value in rem when scrolled past banner
const maxTop = 16 // Maximum top value in rem when at page top

function handleScroll() {
const scrollY = window.scrollY
// Calculate top value based on scroll position
// As user scrolls down, reduce the top value
const remValue = Math.max(minTop, maxTop - (scrollY / bannerHeight) * (maxTop - minTop))
sidebarTop = remValue
}

window.addEventListener('scroll', handleScroll, { passive: true })
handleScroll() // Initial call

return () => {
window.removeEventListener('scroll', handleScroll)
}
})

function autoScroll(node: HTMLElement) {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
const target = mutation.target as HTMLElement
if (target.classList.contains('active')) {
target.scrollIntoView({ block: 'center', behavior: 'smooth' })
}
}
}
})

observer.observe(node, {
attributes: true,
subtree: true,
attributeFilter: ['class']
})

return {
destroy() {
observer.disconnect()
}
}
}
</script>

<!-- Mobile: Backdrop for popup -->
<Backdrop {open} />
<div class="toc-wrapper card" style={desktop ? 'display: none;' : ''}>

<!-- Desktop: Fixed sidebar on the left -->
{#if desktop}
<div class="desktop-toc-wrapper" style="top: {sidebarTop}rem;" use:autoScroll>
<Toc
headingSelector=":is(h2, h3, h4):not(.toc-exclude):not(footer *)"
title="Contents"
bind:headings
hide={(headings?.length ?? 0) <= 2}
open={true}
desktop={true}
>
<svelte:fragment slot="title">
<h2 class="toc-title-heading toc-exclude">Contents</h2>
</svelte:fragment>
</Toc>
</div>
{/if}

<!-- Mobile: Floating button with popup (hidden on desktop) -->
<div class="toc-wrapper card" class:hidden-on-desktop={desktop}>
<Toc
headingSelector=":is(h2, h3, h4):not(.toc-exclude):not(footer *)"
title="Contents"
breakpoint={1250}
bind:open
bind:desktop
bind:headings
Expand All @@ -40,16 +111,82 @@

<style>
:root {
--toc-active-color: var(--bg);
--toc-active-color: var(--brand);
--toc-li-hover-color: var(--brand);
--toc-li-color: var(--text);
--toc-mobile-bg: var(--bg);
--toc-active-bg: var(--brand);
--toc-active-bg: transparent;
--toc-max-height: 80vh;
--toc-padding: 0em 1em 1em;
--toc-z-index: 10;
}

/* Desktop sidebar: fixed on left */
.desktop-toc-wrapper {
position: fixed;
/* top is set dynamically via inline style */
width: 220px;
max-height: calc(100vh - 3rem); /* Extend nearly to bottom of viewport */
overflow-y: auto;
background-color: transparent;
z-index: 5;
padding: 1rem;
font-size: 0.85rem;

/* Hide scrollbar but allow scrolling */
scrollbar-width: none; /* Firefox */
-ms-overflow-style: none; /* IE and Edge */
}

.desktop-toc-wrapper::-webkit-scrollbar {
display: none; /* Chrome, Safari, Opera */
}

.desktop-toc-wrapper :global(.toc) {
background-color: transparent;
}

.desktop-toc-wrapper :global(.toc > nav) {
background-color: transparent;
}

.desktop-toc-wrapper :global(aside.toc > nav > ol) {
padding-left: 0;
}

.desktop-toc-wrapper :global(aside.toc > nav > ol > li) {
margin-bottom: 0.5rem;
}

/* Hide open button on desktop ToC */
.desktop-toc-wrapper :global(button.toc-icon) {
display: none;
}

/* Hide the arrows/navigation bar */
.desktop-toc-wrapper :global(.toc-title),
.desktop-toc-wrapper :global(.toc-nav),
.desktop-toc-wrapper :global(.toc-header) {
display: none !important;
}

/* Hide all buttons in desktop sidebar */
.desktop-toc-wrapper :global(button) {
display: none !important;
}

/* Remove inner scrollbar - only wrapper should scroll */
.desktop-toc-wrapper :global(nav) {
max-height: none;
overflow: visible;
}

/* Hide mobile wrapper on desktop */
.hidden-on-desktop {
display: none;
}

/* Mobile styles */
.toc-head {
position: sticky;
top: 0;
Expand Down Expand Up @@ -87,6 +224,8 @@

.toc-wrapper :global(.toc > nav) {
background-color: inherit;
border-radius: inherit;
box-shadow: inherit;
}

@media (hover: none) {
Expand All @@ -99,6 +238,9 @@
.toc-wrapper :global(aside.toc > nav > ol > li:hover) {
text-decoration-line: underline;
}
.desktop-toc-wrapper :global(aside.toc > nav > ol > li:hover) {
text-decoration-line: underline;
}
.toc-close:hover {
color: var(--brand);
}
Expand Down
10 changes: 5 additions & 5 deletions src/posts/action.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Choose an activity below depending on your interests or skills.
title: 'Journalist or Creator',
content: `

<h3>If you work as a journalist or have a social media following</h3>
<h3 class="toc-exclude">If you work as a journalist or have a social media following</h3>
<ul>
<li><strong>Create content</strong> about AI dangers or PauseAI. For more information, reach out to us through any of our <a href="/faq#do-you-have-social-media">communication channels</a>.</li>
</ul>
Expand All @@ -50,7 +50,7 @@ content: `
{
title: 'Politician or Public Servant',
content: `
<h3>If you are a politician or work in government</h3>
<h3 class="toc-exclude">If you are a politician or work in government</h3>
<ul>
<li><strong>Prepare for the next <a href="/summit">AI safety summit</a></strong>. Form coalitions with other countries to share safety information and act quickly when harms arise. Work towards a global treaty.</li>
<li><strong>Invite (or subpoena) AI lab leaders</strong> to parliamentary/congressional hearings to give their predictions and timelines of AI disasters.</li>
Expand All @@ -63,7 +63,7 @@ content: `
{
title: 'Legal or Policy Expert',
content: `
<h3>If you have experience with (international) law</h3>
<h3 class="toc-exclude">If you have experience with (international) law</h3>
<ul>
<li><strong>Help draft policy</strong>. <a href="https://www.campaignforaisafety.org/celebrating-the-winners-law-student-moratorium-treaty-competition/">Draft examples</a>. <a href="https://futureoflife.org/wp-content/uploads/2023/04/FLI_Policymaking_In_The_Pause.pdf">Some</a> <a href="https://www.openphilanthropy.org/research/12-tentative-ideas-for-us-ai-policy/">frameworks</a>.</li>
<li><strong>Make submissions</strong> to government requests for comment on AI policy (<a href="https://ntia.gov/issues/artificial-intelligence/request-for-comments">example</a>).</li>
Expand All @@ -73,7 +73,7 @@ content: `
{
title: 'Academic or Educator',
content: `
<h3>If you are a university professor or work in an academic institution</h3>
<h3 class="toc-exclude">If you are a university professor or work in an academic institution</h3>
<ul>
<li><strong>Write op-eds</strong> and articles for media outlets</li>
<li><strong>Mentor students</strong> who are interested in this topic</li>
Expand All @@ -85,7 +85,7 @@ content: `
{
title: 'AI Industry Professional',
content: `
<h3>If you work in AI</h3>
<h3 class="toc-exclude">If you work in AI</h3>
<ul>
<li><strong>Don't work towards better AI</strong>: Do not work for AI companies or capabilities research. And do not spread ideas on how we can make AI systems faster or smarter.</li>
<li><strong>Talk to your management and colleagues</strong> about the risks. Get them to take an institutional position toward mitigating risk over profit. Encourage implementation of standard risk mitigation procedures and anonymous reporting.</li>
Expand Down
2 changes: 1 addition & 1 deletion src/routes/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
<PreloadFonts urls={[robotoSlabLatin300, sairaCondensedLatin700]} />

<h2 style="width: 0; height: 0; margin: 0; padding: 0; visibility: hidden;" data-pagefind-ignore>
(Top)
Top
</h2>

<!-- Make sure we only show one banner at a time-->
Expand Down
1 change: 1 addition & 0 deletions src/styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ h5 {
font-family: var(--font-heading);
font-weight: 700;
line-height: 1em;
scroll-margin-top: 3rem;
}

h1 {
Expand Down
Loading