This commit is contained in:
tree🌴 2023-02-23 14:29:23 +01:00
parent 012de9d209
commit 26fee8006e
9 changed files with 245 additions and 179 deletions

View file

@ -7,6 +7,7 @@ Website and data repository for the Web3Privacy Summit #1 that will take place i
- Twitter: [@web3privacy](http://twitter.com/web3privacy) - Twitter: [@web3privacy](http://twitter.com/web3privacy)
JSON data about `w3ps1`: JSON data about `w3ps1`:
- source: ([src/lib/config.yaml](src/lib/config.yaml)) - source: ([src/lib/config.yaml](src/lib/config.yaml))
- build: [prague.web3privacy.info/config.json](https://prague.web3privacy.info/config.json) - build: [prague.web3privacy.info/config.json](https://prague.web3privacy.info/config.json)

View file

@ -59,7 +59,8 @@
.table-custom th { .table-custom th {
@apply text-mild; @apply text-mild;
} }
.table-custom tbody tr:hover td, .table-custom tbody tr:hover td span { .table-custom tbody tr:hover td,
.table-custom tbody tr:hover td span {
@apply bg-white text-black; @apply bg-white text-black;
} }
.table-custom tbody tr:hover td .description { .table-custom tbody tr:hover td .description {
@ -82,7 +83,10 @@
.person-item:hover img { .person-item:hover img {
@apply grayscale-0 invert-0 blur-none; @apply grayscale-0 invert-0 blur-none;
} }
.person-item:hover .text-mild, .person-item:hover .text-supermild, .topic-item:hover .text-mild, .topic-item:hover .text-supermild { .person-item:hover .text-mild,
.person-item:hover .text-supermild,
.topic-item:hover .text-mild,
.topic-item:hover .text-supermild {
@apply text-black; @apply text-black;
} }
} }

View file

@ -9,6 +9,10 @@
</head> </head>
<body data-sveltekit-preload-data="hover"> <body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div> <div style="display: contents">%sveltekit.body%</div>
<script defer data-domain="prague.web3privacy.info" src="https://x.gwei.cz/js/script.js"></script> <script
defer
data-domain="prague.web3privacy.info"
src="https://x.gwei.cz/js/script.js"
></script>
</body> </body>
</html> </html>

View file

@ -1,7 +1,7 @@
<script> <script>
export let items; export let items;
export let people; export let people;
export let size = 'normal'; export let size = 'normal';
import SvelteMarkdown from 'svelte-markdown'; import SvelteMarkdown from 'svelte-markdown';
import { animateText } from '$lib/helpers'; import { animateText } from '$lib/helpers';
@ -13,21 +13,27 @@
return `https://twitter.com/${handle}`; return `https://twitter.com/${handle}`;
} }
function animateSpeaker (el) { function animateSpeaker(el) {
for(const e of el.target.getElementsByClassName('animate-speaker')) { for (const e of el.target.getElementsByClassName('animate-speaker')) {
animateText({ target: e }) animateText({ target: e });
} }
} }
</script> </script>
{#each items.map(getPerson) as item} {#each items.map(getPerson) as item}
<div class="hover:bg-white hover:text-black p-2 {size === 'small' ? 'w-2/3 sm:w-48' : 'w-2/3 sm:w-64'} person-item" on:mouseenter={animateSpeaker}> <div
class="hover:bg-white hover:text-black p-2 {size === 'small'
? 'w-2/3 sm:w-48'
: 'w-2/3 sm:w-64'} person-item"
on:mouseenter={animateSpeaker}
>
<div> <div>
<img src="/people/{item.img}" class="grayscale invert aspect-square object-cover w-full" /> <img src="/people/{item.img}" class="grayscale invert aspect-square object-cover w-full" />
</div> </div>
<div class="mt-4 speaker-name animate-speaker text-xl">{item.name.toUpperCase()}</div> <div class="mt-4 speaker-name animate-speaker text-xl">{item.name.toUpperCase()}</div>
<div class="text-lg text-mild"> <div class="text-lg text-mild">
<a href={twitterLink(item.twitter)} class="hover:underline animate-speaker">@{item.twitter}</a> <a href={twitterLink(item.twitter)} class="hover:underline animate-speaker">@{item.twitter}</a
>
</div> </div>
{#if item.caption} {#if item.caption}
<div class="mt-2 text-base text-supermild"><SvelteMarkdown source={item.caption} /></div> <div class="mt-2 text-base text-supermild"><SvelteMarkdown source={item.caption} /></div>

View file

@ -1,16 +1,16 @@
title: Web3Privacy Prague 2023 title: Web3Privacy Prague 2023
shortname: "Web3Privacy Summit #1" shortname: 'Web3Privacy Summit #1'
date: 5. June 2023 date: 5. June 2023
venue: X10, Prague venue: X10, Prague
domain: prague.web3privacy.info domain: prague.web3privacy.info
image: "/web3privacy.png" image: '/web3privacy.png'
logo: "/web3privacy-cropped.jpg" logo: '/web3privacy-cropped.jpg'
twitter: web3privacy twitter: web3privacy
parent: Web3Privacy Now parent: Web3Privacy Now
venueMapUrl: https://goo.gl/maps/VCSC7wcNueEKgt996 venueMapUrl: https://goo.gl/maps/VCSC7wcNueEKgt996
parentUrl: https://web3privacy.info parentUrl: https://web3privacy.info
desc: June 5, 2023 - A lunarpunk conference focused on privacy in the Web3 industry as a complement to the Web3Privacy Now research. desc: June 5, 2023 - A lunarpunk conference focused on privacy in the Web3 industry as a complement to the Web3Privacy Now research.
authors: "💛 Collaboration of [Web3Privacy Now](https://web3privacy.info) & [ETHBrno](https://ethbrno.cz) team" authors: '💛 Collaboration of [Web3Privacy Now](https://web3privacy.info) & [ETHBrno](https://ethbrno.cz) team'
license: This web is built with [SvelteKit](https://kit.svelte.dev/) and is [open-source](https://github.com/web3privacy/w3ps1) under CC0 license license: This web is built with [SvelteKit](https://kit.svelte.dev/) and is [open-source](https://github.com/web3privacy/w3ps1) under CC0 license
slogan: Diving into the culture of the Web3 privacy industry slogan: Diving into the culture of the Web3 privacy industry
aggregator: Prague Blockchain Week 2023 aggregator: Prague Blockchain Week 2023
@ -37,15 +37,15 @@ themes:
desc: We need resilient privacy-preserving, p2p communication layers for Web3, that allows free and uncensored human-to-human, machine-to-machine or hybrid communication. desc: We need resilient privacy-preserving, p2p communication layers for Web3, that allows free and uncensored human-to-human, machine-to-machine or hybrid communication.
- title: Lunarpunk vs Solarpunk - title: Lunarpunk vs Solarpunk
desc: For solarpunk to succeed it must integrate the lunarpunk unconscious. The only hope for solarpunk is to [go dark](https://www.egirlcapital.com/writings/107533289). Do you agree? desc: For solarpunk to succeed it must integrate the lunarpunk unconscious. The only hope for solarpunk is to [go dark](https://www.egirlcapital.com/writings/107533289). Do you agree?
- title: "R&D: ZK, MPC, THE" - title: 'R&D: ZK, MPC, THE'
desc: There are many different cryptography technics for privacy preservation. How to balance them all & avoid 1-tool chokepoint? desc: There are many different cryptography technics for privacy preservation. How to balance them all & avoid 1-tool chokepoint?
- title: Privacy readiness levels - title: Privacy readiness levels
desc: Introduction of the privacy scoring mechanism to help non-tech people understand security level of the solution desc: Introduction of the privacy scoring mechanism to help non-tech people understand security level of the solution
- title: Privacy wars - title: Privacy wars
desc: Why are privacy-blockchain socials so toxic? How could we stop hating each other & work together desc: Why are privacy-blockchain socials so toxic? How could we stop hating each other & work together
- title: Privacy workforce - title: Privacy workforce
- title: "Privacy activism" - title: 'Privacy activism'
desc: "Mapping down tools to protect privacy industry: from builders like Alexey Pertsev to projects." desc: 'Mapping down tools to protect privacy industry: from builders like Alexey Pertsev to projects.'
- title: Network states (with a privacy focus) - title: Network states (with a privacy focus)
desc: Time ot imagine the network state-as-a-grassroots movement for privacy, freedom & better future. desc: Time ot imagine the network state-as-a-grassroots movement for privacy, freedom & better future.
- title: Veksl - title: Veksl
@ -58,22 +58,22 @@ tickets:
- title: All-day Access - title: All-day Access
price: €99 price: €99
includes: includes:
- All talks & panels - All talks & panels
- Food and drinks included - Food and drinks included
- Web3Privacy t-shirt - Web3Privacy t-shirt
- Networking drinks with speakers & attendees - Networking drinks with speakers & attendees
- "#Lunarpunk party" - '#Lunarpunk party'
hint: | hint: |
[Apply for a discount →](https://attend.web3privacy.info)<br />(as independent developer, student, privacy advocate, open-source contributor..) [Apply for a discount →](https://attend.web3privacy.info)<br />(as independent developer, student, privacy advocate, open-source contributor..)
- title: "#Lunarpunk Party" - title: '#Lunarpunk Party'
price: €15 price: €15
includes: includes:
- 8pm - morning - 8pm - morning
- Prague rave from top DJs - Prague rave from top DJs
- VJs and projections - VJs and projections
- "\"Privacy experience\"" - '"Privacy experience"'
- Networking with attendees, speakers & sponsors - Networking with attendees, speakers & sponsors
note: "*Party access is included in the All-day Pass" note: '*Party access is included in the All-day Pass'
faq: faq:
- title: What is Web3Privacy Now? - title: What is Web3Privacy Now?
text: | text: |
@ -94,44 +94,44 @@ faq:
- title: Will the talks be livestreamed and/or recorded? - title: Will the talks be livestreamed and/or recorded?
text: Yes, we're planning both. A livestream of the conference and recordings of the talks and panels will be publicly available after the conference. text: Yes, we're planning both. A livestream of the conference and recordings of the talks and panels will be publicly available after the conference.
- title: I have another question, where can I contact you? - title: I have another question, where can I contact you?
text: "You can contact the organizing team or the community around the event in our public Signal group: [chat.web3privacy.info](https://chat.web3privacy.info/)" text: 'You can contact the organizing team or the community around the event in our public Signal group: [chat.web3privacy.info](https://chat.web3privacy.info/)'
people: people:
- id: mykola - id: mykola
name: Mykola Siusko name: Mykola Siusko
twitter: nicksvyaznoy twitter: nicksvyaznoy
img: mykola.png img: mykola.png
caption: Web3 privacy advocate caption: Web3 privacy advocate
country: es country: es
- id: tree - id: tree
name: Tree name: Tree
twitter: treecz twitter: treecz
img: tree.jpeg img: tree.jpeg
caption: Creator of lunarpunk hackathons & events caption: Creator of lunarpunk hackathons & events
country: cz country: cz
- id: juraj-bednar - id: juraj-bednar
name: Juraj Bednar name: Juraj Bednar
twitter: jurbed twitter: jurbed
img: juraj-bednar.jpeg img: juraj-bednar.jpeg
caption: Educator, writer, cryptoanarchist & biohacker caption: Educator, writer, cryptoanarchist & biohacker
country: sk country: sk
- id: mario-havel - id: mario-havel
name: Mario Havel name: Mario Havel
twitter: TMIYChao twitter: TMIYChao
img: mario-havel.jpeg img: mario-havel.jpeg
caption: Hacker, Co-Founder of [Bordel Hackerspace](https://bordel.paralelnipolis.cz/#/) caption: Hacker, Co-Founder of [Bordel Hackerspace](https://bordel.paralelnipolis.cz/#/)
country: cz country: cz
- id: guy-zyskind - id: guy-zyskind
name: Guy Zyskind name: Guy Zyskind
twitter: GuyZys twitter: GuyZys
img: guy-zyskind.jpeg img: guy-zyskind.jpeg
caption: Founder of [Secret Network](https://scrt.network/), CEO [SCRT Labs](https://www.scrtlabs.com/) caption: Founder of [Secret Network](https://scrt.network/), CEO [SCRT Labs](https://www.scrtlabs.com/)
country: is country: is
- id: manu-alzuru - id: manu-alzuru
name: Manu Alzuru name: Manu Alzuru
twitter: ManuAlzuru twitter: ManuAlzuru
img: manu-alzuru.jpeg img: manu-alzuru.jpeg
caption: Humanist, solarpunk, Founder of [DoinGud](https://doingud.com/) & [ETH Barcelona](https://ethbarcelona.com/) caption: Humanist, solarpunk, Founder of [DoinGud](https://doingud.com/) & [ETH Barcelona](https://ethbarcelona.com/)
country: es country: es
speakersNote: We keep adding more and more speakers, stay tuned ... speakersNote: We keep adding more and more speakers, stay tuned ...
speakers: speakers:
- guy-zyskind - guy-zyskind
@ -154,7 +154,7 @@ program:
- time: 9:30 - 9:35 - time: 9:30 - 9:35
title: Welcome to Web3Privacy title: Welcome to Web3Privacy
speakers: speakers:
- name: TBA - name: TBA
desc: Welcoming visitors to our private-centric research, community and conference desc: Welcoming visitors to our private-centric research, community and conference
- time: 9:35 - 10:55 - time: 9:35 - 10:55
title: Talks I. - TBA title: Talks I. - TBA
@ -181,7 +181,7 @@ program:
title: Networking & Drinks title: Networking & Drinks
type: other type: other
- time: 20:00 - 4:00 - time: 20:00 - 4:00
title: "#Lunarpunk party" title: '#Lunarpunk party'
desc: Enjoy our afterparty in Lunarpunk style with quality Prague rave DJs, which will take place in the same venue until the morning (4am). desc: Enjoy our afterparty in Lunarpunk style with quality Prague rave DJs, which will take place in the same venue until the morning (4am).
second: second:
- time: 09:35 - 10:55 - time: 09:35 - 10:55

View file

@ -1,53 +1,65 @@
import removeMd from 'remove-markdown';
import removeMd from 'remove-markdown'
export function rand(length) { export function rand(length) {
let result = ''; let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length; const charactersLength = characters.length;
let counter = 0; let counter = 0;
while (counter < length) { while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength)); result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1; counter += 1;
} }
return result; return result;
} }
export function animateText (ev, interval = 50) { export function animateText(ev, interval = 50) {
if (!ev.target.getAttribute('data-text')) { if (!ev.target.getAttribute('data-text')) {
ev.target.setAttribute('data-text', ev.target.innerHTML) ev.target.setAttribute('data-text', ev.target.innerHTML);
} }
if (ev.target.getAttribute('data-animate') === "1") { if (ev.target.getAttribute('data-animate') === '1') {
return; return;
} }
ev.target.setAttribute('data-animate', "1") ev.target.setAttribute('data-animate', '1');
const orig = removeMd(ev.target.getAttribute('data-text')).replace('&amp;', '&') const orig = removeMd(ev.target.getAttribute('data-text')).replace('&amp;', '&');
const steps = orig.length const steps = orig.length;
const genRand = (pos = 0, len = null) => orig.substring(pos, len).split(' ').map(x => rand(x.length)).join(' ') const genRand = (pos = 0, len = null) =>
const random = genRand(0, orig.length) orig
.substring(pos, len)
.split(' ')
.map((x) => rand(x.length))
.join(' ');
const random = genRand(0, orig.length);
ev.target.innerHTML = random ev.target.innerHTML = random;
for (let i = 0; i <= steps; i++) { for (let i = 0; i <= steps; i++) {
setTimeout(() => { setTimeout(() => {
ev.target.innerHTML = orig.substring(0, i) + genRand(i, orig.length) ev.target.innerHTML = orig.substring(0, i) + genRand(i, orig.length);
//console.log(ev.target.innerHTML) //console.log(ev.target.innerHTML)
if (i === steps) { if (i === steps) {
ev.target.setAttribute('data-animate', "0") ev.target.setAttribute('data-animate', '0');
} }
}, interval * i) }, interval * i);
} }
} }
export async function handleAnchorClick (event) { export async function handleAnchorClick(event) {
event.preventDefault() event.preventDefault();
const link = event.currentTarget const link = event.currentTarget;
const anchorId = new URL(link.href).hash.replace('#', '') const anchorId = new URL(link.href).hash.replace('#', '');
const anchor = document.getElementById(anchorId || 'intro') const anchor = document.getElementById(anchorId || 'intro');
return window.scrollTo({ return window.scrollTo({
top: anchor.offsetTop, top: anchor.offsetTop,
behavior: 'smooth' behavior: 'smooth'
}) });
}
export function animateSection(interval = 50) {
return (el) => {
for (const e of el.target.getElementsByClassName('animate-section')) {
animateText({ target: e }, interval);
}
};
} }

View file

@ -3,10 +3,10 @@
export let data; export let data;
import SvelteMarkdown from 'svelte-markdown'; import SvelteMarkdown from 'svelte-markdown';
import { animateText, handleAnchorClick } from '$lib/helpers'; import { animateText, animateSection, handleAnchorClick } from '$lib/helpers';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let navbar = false; let navbar = false;
let choosed = null; let choosed = null;
let lastScrollTop = null; let lastScrollTop = null;
@ -23,34 +23,34 @@
]; ];
const homepageAnimation = () => { const homepageAnimation = () => {
const collection = document.getElementsByClassName('animation-crypt') const collection = document.getElementsByClassName('animation-crypt');
for (const el of collection) { for (const el of collection) {
animateText({ target: el }) animateText({ target: el });
} }
} };
function locationHashUpdateTick () { function locationHashUpdateTick() {
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (lastScrollTop === scrollTop) { if (lastScrollTop === scrollTop) {
return null; return null;
} else { } else {
lastScrollTop = scrollTop lastScrollTop = scrollTop;
} }
const arr = [] const arr = [];
for (const mi of menu) { for (const mi of menu) {
if (mi.external) continue; if (mi.external) continue;
const el = document.getElementById(mi.title.toLowerCase()) const el = document.getElementById(mi.title.toLowerCase());
const pos = el.getBoundingClientRect() const pos = el.getBoundingClientRect();
//console.log(mi.title, pos.top, pos.bottom) //console.log(mi.title, pos.top, pos.bottom)
if (pos.top <= 100 && pos.bottom > 100) { if (pos.top <= 100 && pos.bottom > 100) {
arr.push([ mi, pos.top, pos.bottom ]) arr.push([mi, pos.top, pos.bottom]);
} }
} }
choosed = arr[arr.length-1] choosed = arr[arr.length - 1];
if (choosed) { if (choosed) {
//console.log('choosed = ', choosed[0].title) //console.log('choosed = ', choosed[0].title)
const currentHash = window.location.hash const currentHash = window.location.hash;
const hash = choosed[0].url const hash = choosed[0].url;
if (hash !== currentHash) { if (hash !== currentHash) {
if (hash === '') { if (hash === '') {
history.replaceState(null, null, ' '); history.replaceState(null, null, ' ');
@ -62,11 +62,10 @@
} }
onMount(async () => { onMount(async () => {
setTimeout(homepageAnimation, 0) // initial animation setTimeout(homepageAnimation, 0); // initial animation
setInterval(homepageAnimation, 10000) // every 10 seconds setInterval(homepageAnimation, 10000); // every 10 seconds
setInterval(locationHashUpdateTick, 1000) // every 1 seconds setInterval(locationHashUpdateTick, 1000); // every 1 seconds
}); });
</script> </script>
<div class="relative w-full min-h-screen text-white"> <div class="relative w-full min-h-screen text-white">
@ -75,15 +74,26 @@
<div class="flex"> <div class="flex">
<div class="flex items-center gap-4 grow"> <div class="flex items-center gap-4 grow">
<div class="w-16 py-2"> <div class="w-16 py-2">
<a href={data.config.parentUrl} target="_blank"><img src={data.config.logo} alt={data.config.parent} /></a> <a href={data.config.parentUrl} target="_blank"
><img src={data.config.logo} alt={data.config.parent} /></a
>
</div> </div>
<!--h1 class="text-2xl uppercase">{data.config.title}</h1--> <!--h1 class="text-2xl uppercase">{data.config.title}</h1-->
</div> </div>
<div class="flex items-center gap-6 text-xl"> <div class="flex items-center gap-6 text-xl">
<button class="md:hidden text-3xl" on:click={(ev) => (navbar = !navbar)}>☰</button> <button class="md:hidden text-3xl" on:click={(ev) => (navbar = !navbar)}>☰</button>
{#each menu.filter(i => !i.hidden) as mi} {#each menu.filter((i) => !i.hidden) as mi}
<div class="hidden md:block"> <div class="hidden md:block">
<a class="{mi.class ? mi.class : 'hover:underline'} {choosed && mi.url === choosed[0].url ? 'font-bold underline' : null} {mi.external ? 'external' : ''}" href={mi.url} on:mouseenter={animateText} on:click={!mi.external ? handleAnchorClick : null} target={mi.external ? '_blank' : ''}> <a
class="{mi.class ? mi.class : 'hover:underline'} {choosed &&
mi.url === choosed[0].url
? 'font-bold underline'
: null} {mi.external ? 'external' : ''}"
href={mi.url}
on:mouseenter={animateText}
on:click={!mi.external ? handleAnchorClick : null}
target={mi.external ? '_blank' : ''}
>
{mi.name?.toUpperCase() || mi.title.toUpperCase()} {mi.name?.toUpperCase() || mi.title.toUpperCase()}
</a> </a>
</div> </div>
@ -92,24 +102,35 @@
</div> </div>
</div> </div>
{#if navbar} {#if navbar}
<div class="w-full md:hidden p-4"> <div class="w-full md:hidden p-4">
{#each menu.filter(i => !i.hidden) as mi} {#each menu.filter((i) => !i.hidden) as mi}
<div class="my-3 mx-4"> <div class="my-3 mx-4">
<a href={mi.url} on:click={() => navbar = false}><button class="{mi.class} uppercase text-xl {mi.external ? 'external' : ''}">{mi.title}</button></a> <a href={mi.url} on:click={() => (navbar = false)}
><button class="{mi.class} uppercase text-xl {mi.external ? 'external' : ''}"
>{mi.title}</button
></a
>
</div>
{/each}
</div> </div>
{/each}
</div>
{/if} {/if}
</div> </div>
<div class="w-full h-screen" id="intro"> <div class="w-full h-screen" id="intro">
<div class="w-full h-full flex items-center text-center"> <div class="w-full h-full flex items-center text-center">
<div class="mx-auto px-4"> <div class="mx-auto px-4">
<div class="text-5xl md:text-8xl font-bold mb-4 md:mb-8 animation-crypt" on:mouseenter={animateText}> <div
class="text-5xl md:text-8xl font-bold mb-4 md:mb-8 animation-crypt"
on:mouseenter={animateText}
>
{data.config.shortname.toUpperCase()} {data.config.shortname.toUpperCase()}
</div> </div>
<div class="text-3xl md:text-5xl md:mb-4 uppercase"> <div class="text-3xl md:text-5xl md:mb-4 uppercase">
<span class="">{data.config.date}</span> @ <a href={data.config.venueMapUrl} target="_blank" class="underline hover:no-underline">{data.config.venue}</a></div> <span class="">{data.config.date}</span> @
<a href={data.config.venueMapUrl} target="_blank" class="underline hover:no-underline"
>{data.config.venue}</a
>
</div>
<div class="mt-8 text-lg text-mild mx-4"> <div class="mt-8 text-lg text-mild mx-4">
<p class="">{data.config.slogan}</p> <p class="">{data.config.slogan}</p>
<p> <p>
@ -132,11 +153,13 @@
<div class="flex gap-4"> <div class="flex gap-4">
<div class="grow"> <div class="grow">
<div class="w-32 sm:w-40"> <div class="w-32 sm:w-40">
<a href={data.config.parentUrl}><img src={data.config.logo} alt={data.config.parent} /></a> <a href={data.config.parentUrl}
><img src={data.config.logo} alt={data.config.parent} /></a
>
</div> </div>
</div> </div>
<div class="text-right"> <div class="text-right">
<div class=""> <div class="" on:mouseenter={animateSection()}>
<a class="inline-block w-5 mr-1" href="https://twitter.com/{data.config.twitter}"> <a class="inline-block w-5 mr-1" href="https://twitter.com/{data.config.twitter}">
<svg viewBox="0 0 29 26" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg viewBox="0 0 29 26" fill="none" xmlns="http://www.w3.org/2000/svg">
<path <path
@ -145,7 +168,11 @@
/> />
</svg> </svg>
</a> </a>
<a href="https://twitter.com/{data.config.twitter}" class="text-2xl no-underline hover:underline external" target="_blank"> <a
href="https://twitter.com/{data.config.twitter}"
class="text-2xl no-underline hover:underline external animate-section"
target="_blank"
>
@{data.config.twitter} @{data.config.twitter}
</a> </a>
</div> </div>

View file

@ -1,28 +1,20 @@
<script> <script>
import SvelteMarkdown from 'svelte-markdown'; import SvelteMarkdown from 'svelte-markdown';
import PeopleList from '$lib/components/PeopleList.svelte'; import PeopleList from '$lib/components/PeopleList.svelte';
import { animateText } from '$lib/helpers'; import { animateText, animateSection } from '$lib/helpers';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
export let data; export let data;
function animateSection (interval = 50) {
return (el) => {
for(const e of el.target.getElementsByClassName('animate-section')) {
animateText({ target: e }, interval)
}
}
}
</script> </script>
<svelte:head> <svelte:head>
<title>{data.config.title} | {data.config.date}</title> <title>{data.config.title} | {data.config.date}</title>
<meta name="description" content={data.config.desc} /> <meta name="description" content={data.config.desc} />
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@{data.config.twitter}" /> <meta name="twitter:site" content="@{data.config.twitter}" />
<meta name="twitter:title" content={data.config.title} /> <meta name="twitter:title" content={data.config.title} />
<meta name="twitter:description" content={data.config.desc} /> <meta name="twitter:description" content={data.config.desc} />
<meta name="twitter:image" content="https://{data.config.domain}{data.config.image}" /> <meta name="twitter:image" content="https://{data.config.domain}{data.config.image}" />
</svelte:head> </svelte:head>
<div class="bg-black" id="about"> <div class="bg-black" id="about">
@ -33,7 +25,10 @@
<div class="section-header" on:mouseenter={animateText}>Key themes</div> <div class="section-header" on:mouseenter={animateText}>Key themes</div>
<div class="grid md:grid-cols-3 gap-4 md:gap-10"> <div class="grid md:grid-cols-3 gap-4 md:gap-10">
{#each data.config.themes as ti} {#each data.config.themes as ti}
<div class="bg-[#0d1117] hover:text-black hover:bg-white px-4 py-6 topic-item" on:mouseenter={animateSection(35)}> <div
class="bg-[#0d1117] hover:text-black hover:bg-white px-4 py-6 topic-item"
on:mouseenter={animateSection(35)}
>
<div class="text-2xl animate-section">{ti.title.toUpperCase()}</div> <div class="text-2xl animate-section">{ti.title.toUpperCase()}</div>
<div class="mt-4 text-lg text-mild markdown"> <div class="mt-4 text-lg text-mild markdown">
<SvelteMarkdown source={ti.desc} /> <SvelteMarkdown source={ti.desc} />
@ -76,7 +71,9 @@
<div class="text-lg text-supermild mb-16">{data.config.programNote}</div> <div class="text-lg text-supermild mb-16">{data.config.programNote}</div>
{/if} {/if}
<div class="program xl:flex gap-10 xl:gap-4"> <div class="program xl:flex gap-10 xl:gap-4">
{#each data.config.stages.map(s => ({ ...s, program: data.config.program[s.id]})).filter(s => s.program) as stage} {#each data.config.stages
.map((s) => ({ ...s, program: data.config.program[s.id] }))
.filter((s) => s.program) as stage}
<div class="w-auto xl:w-1/2 mb-10 xl:mb-0"> <div class="w-auto xl:w-1/2 mb-10 xl:mb-0">
<div class="text-3xl font-bold mb-4">{stage.name}</div> <div class="text-3xl font-bold mb-4">{stage.name}</div>
<table class="table-auto table-custom w-full mx-0 lg:mx-8"> <table class="table-auto table-custom w-full mx-0 lg:mx-8">
@ -90,14 +87,22 @@
<tbody> <tbody>
{#each stage.program as pi} {#each stage.program as pi}
<tr class="" on:mouseenter={animateSection(35)}> <tr class="" on:mouseenter={animateSection(35)}>
<td class="text-right time xl:whitespace-nowrap sm:w-16 xl:w-36 {pi.type==="other" ? 'text-mild' : ''}" <td
class="text-right time xl:whitespace-nowrap sm:w-16 xl:w-36 {pi.type === 'other'
? 'text-mild'
: ''}"
>{@html pi.time >{@html pi.time
.split('-') .split('-')
.map((x) => x) .map((x) => x)
.join('<div class="xl:inline-block hidden mx-1">-</div>')} .join('<div class="xl:inline-block hidden mx-1">-</div>')}
</td> </td>
<td class="text-left"> <td class="text-left">
<div class="text-xl"><span class="animate-section {pi.type==="other" ? 'text-mild' : ''}">{pi.title}</span> {pi.speakers ? '― ' + pi.speakers[0]?.name : ''}</div> <div class="text-xl">
<span class="animate-section {pi.type === 'other' ? 'text-mild' : ''}"
>{pi.title}</span
>
{pi.speakers ? '― ' + pi.speakers[0]?.name : ''}
</div>
{#if pi.desc} {#if pi.desc}
<div class="mt-2 text-base description text-mild markdown"> <div class="mt-2 text-base description text-mild markdown">
<SvelteMarkdown source={pi.desc} /> <SvelteMarkdown source={pi.desc} />
@ -120,8 +125,8 @@
<div> <div>
<a href={data.config.sponsorUrl} <a href={data.config.sponsorUrl}
><button ><button
class="py-2 px-5 bg-white text-black hover:bg-black border border-bg-white hover:text-white" on:mouseenter={animateText} class="py-2 px-5 bg-white text-black hover:bg-black border border-bg-white hover:text-white"
>Become a Sponsor</button on:mouseenter={animateText}>Become a Sponsor</button
></a ></a
> >
</div> </div>
@ -135,12 +140,19 @@
<div class="grid lg:grid-cols-2 gap-10 md:w-2/3 mx-auto"> <div class="grid lg:grid-cols-2 gap-10 md:w-2/3 mx-auto">
{#each data.config.tickets as tt} {#each data.config.tickets as tt}
<div <div
class="bg-[#0d1117] hover:border-0 py-10 px-10 hover:text-black hover:bg-white {data.config.ticketing ? "cursor-pointer" : ""}" class="bg-[#0d1117] hover:border-0 py-10 px-10 hover:text-black hover:bg-white {data
.config.ticketing
? 'cursor-pointer'
: ''}"
on:mouseenter={animateSection(40)} on:mouseenter={animateSection(40)}
on:click={() => data.config.ticketing ? goto(data.config.ticketingUrl) : false} on:click={() => (data.config.ticketing ? goto(data.config.ticketingUrl) : false)}
> >
<div class="text-3xl uppercase"><a href={data.config.ticketingUrl} class="animate-section">{tt.title}</a></div> <div class="text-3xl uppercase">
<div class="text-xl mt-6 font-bold"><a href={data.config.ticketingUrl}>{tt.price}</a></div> <a href={data.config.ticketingUrl} class="animate-section">{tt.title}</a>
</div>
<div class="text-xl mt-6 font-bold">
<a href={data.config.ticketingUrl}>{tt.price}</a>
</div>
<ul class="mt-6 text-lg text-left list-disc px-6"> <ul class="mt-6 text-lg text-left list-disc px-6">
{#each tt.includes as ti} {#each tt.includes as ti}
<li>{ti}</li> <li>{ti}</li>
@ -157,9 +169,12 @@
</div> </div>
{#if data.config.ticketing} {#if data.config.ticketing}
<div class="mt-10"> <div class="mt-10">
<a href={data.config.ticketingUrl}><button <a href={data.config.ticketingUrl}
class="py-2 px-5 bg-white text-black hover:bg-black border border-bg-white hover:text-white" on:mouseenter={animateText} ><button
>Buy a ticket</button></a> class="py-2 px-5 bg-white text-black hover:bg-black border border-bg-white hover:text-white"
on:mouseenter={animateText}>Buy a ticket</button
></a
>
</div> </div>
{/if} {/if}
{#if data.config.ticketsNote} {#if data.config.ticketsNote}

View file

@ -3,8 +3,5 @@ import { defineConfig } from 'vite';
import ViteYaml from '@modyfi/vite-plugin-yaml'; import ViteYaml from '@modyfi/vite-plugin-yaml';
export default defineConfig({ export default defineConfig({
plugins: [ plugins: [ViteYaml(), sveltekit()]
ViteYaml(),
sveltekit()
]
}); });