1
0

Basic layout and styles with some fancy transitions

This commit is contained in:
suroh 2025-01-20 21:50:02 +01:00
parent 654521b04d
commit ba4f8527af
22 changed files with 378 additions and 95 deletions

@ -1,5 +1,8 @@
import pluginWebc from '@11ty/eleventy-plugin-webc'
import mdit from 'markdown-it'
import fs from 'fs/promises'
const MD_REGEX = /\.[^/.]{1,4}$/i
export default function (config) {
// markdown parser
@ -22,6 +25,37 @@ export default function (config) {
// 'src/admin': 'admin',
})
// add collection for pages
config.addCollection('categories', async (collection) => {
const categoryNames = (await fs.readdir('src/content/')).filter((c) => !c.match(MD_REGEX))
let categories = new Map()
for (const catName of categoryNames) {
categories = collection.getFilteredByGlob(`src/content/${catName}/index.md`).reduce((accumulator, category) => {
accumulator.set(category, [])
return accumulator
}, categories)
categories = collection.getFilteredByGlob(`src/content/${catName}/*.md`).reduce((accumulator, category) => {
const categoryIsKey = accumulator.keys().find(key => category === key)
if (!categoryIsKey) {
const categoryKey = accumulator.keys().find(key => category.data.tags.includes(key.data.tags[0]))
const catAccum = accumulator.get(categoryKey)
catAccum.push(category)
}
return accumulator
}, categories)
}
return map2arr(categories)
})
config.addCollection('pages', (collection) => {
return collection.getFilteredByGlob('src/content/*.md').filter(p => p.page.fileSlug)
})
return {
markdownTemplateEngine: 'md',
dir: {
@ -32,3 +66,11 @@ export default function (config) {
},
}
}
const map2arr = (myMap) => {
const arr = []
myMap.forEach((value, key) => {
arr.push([key, value])
})
return arr
}

@ -12,6 +12,7 @@
},
"author": "",
"license": "ISC",
"type": "module",
"dependencies": {
"@11ty/eleventy": "^3.0.0",
"@11ty/eleventy-plugin-webc": "^0.11.2",

Binary file not shown.

After

(image error) Size: 93 KiB

Binary file not shown.

After

(image error) Size: 27 KiB

@ -1,12 +1,53 @@
@import 'reset.css';
@import './reset.css';
@import './type.css';
@view-transition {
navigation: auto;
}
/*
* [TODO][MX] create a base class for the view transition and
* append the path to control when they open and close
**/
::view-transition-group(--primary-nav) {
animation: none;
z-index: 1;
}
::view-transition-new(--art-nav) {
height: 100vh;
animation: navSlideIn .25s linear;
}
::view-transition-old(--art-nav) {
height: 100vh;
animation: navSlideOut .25s linear;
}
::view-transition-new(--art-nav) {
height: 100vh;
animation: navSlideIn .25s linear;
}
::view-transition-old(--art-nav) {
height: 100vh;
animation: navSlideOut .25s linear;
}
@keyframes navSlideIn {
from {
translate: -15vw 0;
}
}
@keyframes navSlideOut {
to {
translate: -15vw 0;
}
}
:root {
--font-family: 'Inter', sans-serif;
--font-size: 1em;
--primary-400: #fcf807;
--primary-300: #fff961;
@ -39,25 +80,39 @@ body {
background-color: light-dark(var(--neutral-100), var(--neutral-900));
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: var(--fs-800) 1fr;
grid-template-areas:
'n m x'
'n m g';
grid-template-columns: auto auto 1fr;
}
alx-nav {
display: block;
view-transition-name: main-nav;
max-width: 10vw;
nav {
display: grid;
grid-template-rows: subgrid;
grid-auto-flow: column;
grid-area: n;
transition: max-width 0.5s ease;
}
alx-nav {
grid-row: 1 / -1;
background-color: light-dark(var(--neutral-100), var(--neutral-900));
}
alx-nav.minimised {
max-width: 3em;
a {
color: light-dark(var(--neutral-900), var(--neutral-100));
text-decoration: none;
}
ul li {
padding-block: 0.125em;
}
}
alx-themetoggle {
position: absolute;
top: 1em;
right: 1em;
bottom: 1em;
left: 1em;
}
body.dark {
@ -70,16 +125,65 @@ body.light {
main {
display: grid;
grid-auto-flow: row;
align-content: start;
gap: 1em;
grid-row: 1 / -1;
grid-template-rows: subgrid;
padding: 1em;
view-transition-name: main-content;
view-transition-name: --main;
overflow-x: hidden;
p {
max-width: 70ch;
> article {
grid-row: 2;
width: 70ch;
display: grid;
gap: 1em;
align-content: start;
}
&:has(~ .gallery) {
border-inline-end: thin solid light-dark(var(--tonal-100), var(--tonal-900));
}
}
::view-transition-new(--gallery) {
animation: slideIn 0.75s ease-out;
}
::view-transition-old(--gallery) {
animation: slideOut 0.75s ease-out;
}
@keyframes slideIn {
from {
translate: 100vw 0;
}
}
@keyframes slideOut {
to {
translate: 100vw 0;
}
}
.gallery {
display: grid;
grid-auto-flow: row;
gap: 1em;
padding: 1em;
view-transition-name: --gallery;
img {
max-width: 100%;
}
}
input[name="gallery"] {
grid-area: x;
}
body:has(input[name="gallery"]:checked) {
grid-template-columns: auto 5em 1fr;
}

@ -9,6 +9,10 @@
- `:where()` is used to lower specificity for easy overriding.
*/
:root {
view-transition-name: none;
}
* {
/* Remove default margin on everything */
margin: 0;
@ -111,11 +115,6 @@ body {
overflow-wrap: break-word;
}
/* Fix h1 font size inside article, aside, nav, and section */
h1 {
font-size: 2em;
}
/* Position list marker inside */
:where(ul, ol) {
list-style-position: inside;
@ -145,14 +144,14 @@ a:not([class]) {
}
/* Animate focus outline */
@media (prefers-reduced-motion: no-preference) {
:focus-visible {
transition: outline-offset 145ms cubic-bezier(0.25, 0, 0.4, 1);
}
:where(:not(:active)):focus-visible {
transition-duration: 0.25s;
}
}
/* @media (prefers-reduced-motion: no-preference) { */
/* :focus-visible { */
/* transition: outline-offset 145ms cubic-bezier(0.25, 0, 0.4, 1); */
/* } */
/* :where(:not(:active)):focus-visible { */
/* transition-duration: 0.25s; */
/* } */
/* } */
:where(:not(:active)):focus-visible {
outline-offset: 5px;
}

@ -0,0 +1,56 @@
:root {
--fs-000: clamp(0.32rem, -0.04vi + 0.33rem, 0.23rem);
--fs-100: clamp(0.43rem, -0.03vi + 0.43rem, 0.35rem);
--fs-200: clamp(0.57rem, -0.02vi + 0.57rem, 0.53rem);
--fs-300: clamp(0.75rem, 0.02vi + 0.75rem, 0.79rem);
--fs-400: clamp(1rem, 0.08vi + 0.98rem, 1.19rem);
--fs-500: clamp(1.33rem, 0.2vi + 1.28rem, 1.78rem);
--fs-600: clamp(1.77rem, 0.39vi + 1.67rem, 2.67rem);
--fs-700: clamp(2.35rem, 0.72vi + 2.17rem, 4.01rem);
--fs-800: clamp(3.13rem, 1.25vi + 2.82rem, 6.01rem);
--fs-900: clamp(4.16rem, 2.1vi + 3.64rem, 9.02rem);
}
.fs-900, h1 {
font-size: var(--fs-900);
}
.fs-800, h2 {
font-size: var(--fs-800);
}
.fs-700, h3 {
font-size: var(--fs-700);
}
.fs-600, h4 {
font-size: var(--fs-600);
}
.fs-500, h5 {
font-size: var(--fs-500);
}
.fs-400, h6 {
font-size: var(--fs-400);
}
.fs-300 {
font-size: var(--fs-300);
}
.fs-200 {
font-size: var(--fs-200);
}
.fs-100 {
font-size: var(--fs-100);
}
.fs-000 {
font-size: var(--fs-000);
}
.txt-trim {
text-box-trim: both;
}

@ -1,6 +1,6 @@
---
title: About
layout: single
layout: page
---
My work focuses on merging artistic practices with critical pedagogy. Through my work, I question social systems and foster awareness by engaging audiences with the immediate realities and tensions of identity, migration, and community. Using video, installations, and archival work, I capture everyday experiences, inviting viewers into narratives that reflect resilience, adaptation, and belonging.

@ -0,0 +1,10 @@
---
title: 2 and 2 ain't 22
location: Beijing
year: 2018
---
✴︎ Beijing, 2018✴
This video explores the construction and deconstruction of urban life in Beijing through the experiences of a diverse group of immigrant skaters who navigate the citys fast-paced reality and fleeting memory. Each skaters story reveals a unique perspective on migration, shaped by their individual personalities and circumstances.
Having lived and skated alongside them for six months, I gathered an extensive archive of video, photographs, and sounds that captured their interactions and routines. In editing, these fragments come together to create a narrative that mirrors the citys rhythm over time, highlighting how identity and belonging are continually redefined in dynamic, communal spaces, and emphasizing the resilience and transformation inherent in their stories.

4
src/content/art/art.json Normal file

@ -0,0 +1,4 @@
{
"tags": ["art"],
"layout": "page"
}

@ -1,4 +1,5 @@
---
title: Art
layout: page
navPage: /art
parent: true
---

@ -0,0 +1,13 @@
---
title: Let my Baby stay
location: North Carolina
year: 2018
---
✴︎ North Carolina, 2018 ✴︎
What is the first thing that comes to mind when people ask you, who are you?
Silvia, who, like many others, emigrated to the United States, compelled to take on a new identity—a name, a birthdate, a past that isnt hers—to adapt to an unfamiliar world. Her transformation into “Daisy” becomes a complex layering of self, where each gesture and word forms a narrative that questions her sense of belonging.
Through video, sound, and archival footage of her story, this piece not only documents her personal experience but also explores how identity and belonging are reshaped across borders, reflecting resilience and the profound impact of community narratives on our understanding of self and change.

@ -0,0 +1,14 @@
---
title: percepción
location: Paris
year: 2016
imageGallery:
- src: /images/perception.1.webp
alt: Girl wearing headphones next to a painted white wall and painted window listening to the audio work
- src: /images/perception.2.webp
alt: Photo of the art gallery space with people, including Ricardo are walking aroud various installations
---
✴︎ Paris 2016✴
Ricardo, with a Bluetooth microphone, wanders around the gallery. He speaks. He tells us what he sees, what he hears and what he understands of where he is: he reflects on his perception of the space. Sometimes this brings back memories: he shares it in the microphone. Everything that Ricardo says is heard thanks to a a set of headphones that is hanging on the wall in a corner of the gallery. The listner will be able to link its own interpretation of the space to the one they are is listening to, a sense of complicity is built between two strangers.

@ -1,8 +1,4 @@
---
title: Alexandra Eguiluz
layout: single
layout: page
---
## something
here

@ -1,4 +1,5 @@
---
title: Research
layout: page
navPage: research
parent: true
---

@ -0,0 +1,4 @@
{
"tags": ["research"],
"layout": "page"
}

@ -0,0 +1 @@
export default {}

@ -17,24 +17,33 @@
<script type="module" @raw="getBundle('js')" webc:keep></script>
</head>
<body>
<alx-nav navpage="/">
<ul role="list">
<li>
Art
<ul role="list">
<li>link1</li>
<li>link2</li>
<li>link3</li>
<li>link4</li>
<li>link5</li>
</ul>
</li>
<li>
<a href="/research">Research</a>
</li>
<li><a href="/about">About</a></li>
</ul>
</alx-nav>
<nav class="fs-500">
<alx-nav style="view-transition-name: --primary-nav;" @nav-path="">
<ul>
<li>
<a href="/">Home</a>
</li>
<li webc:for="category of collections.categories" >
<a :href="category[0].url" @text="category[0].data.title"></a>
</li>
<li webc:for="page of collections.pages" >
<a :href="page.url" @text="page.data.title"></a>
</li>
</ul>
</alx-nav>
<alx-nav
webc:for="category of collections.categories"
webc:if="category[1].length"
class="hidden"
style="view-transition-name: --art-nav;"
:@nav-path="category[0].data.tags[0]">
<ul>
<li webc:for="page of category[1]">
<a :href="page.url" @text="page.data.title"></a>
</li>
</ul>
</alx-nav>
</nav>
<template webc:nokeep @raw="content"></template>

@ -1,30 +1,51 @@
<nav>
<button>toggle</button>
<input type="radio" name="alxNav" :value="navPath" />
<div class="content">
<slot></slot>
</nav>
</div>
<style webc:scoped>
nav {
:host {
--nav-width: 15vw;
display: grid;
justify-content: end;
align-content: start;
grid-auto-flow: row;
gap: var(--menu-padding);
outline: thin solid light-dark(var(--tonal-100), var(--tonal-900));
padding: var(--menu-padding);
grid-template-rows: subgrid;
border-inline-end: thin solid light-dark(var(--tonal-100), var(--tonal-900));
overflow: hidden;
height: 100%;
width: var(--nav-width);
transition-delay: none;
transition: width 0.25s 0s ease-in-out;
}
:host:not(:has(input[type="radio"]:checked)).hidden {
width: 0px;
border-inline-end: thin solid transparent;
}
:host:not(:has(input[type="radio"]:checked)) {
width: 4em;
transition-delay: none;
transition: width 0.25s 0s ease-in-out;
}
.content {
display: flex;
flex-direction: column;
padding: var(--menu-padding);
width: calc(var(--nav-width));
}
ul {
display: block;
min-width: var(--menu-content-width);
list-style: none;
}
button {
display: block;
min-width: var(--menu-content-width);
input[type="radio"] {
margin-inline-end: var(--menu-padding);
margin-block-start: var(--menu-padding);
justify-self: end;
}
</style>
@ -32,24 +53,31 @@ button {
customElements.define('alx-nav', class extends HTMLElement {
static observedAttributes = ['navpage']
navPage = ''
navPath = ''
connectedCallback() {
const path = window.location.pathname?.length > 1 ? window.location.pathname.replace(/\/$/, '') : window.location.pathname
if (path !== this.navPage) {
this.classList.add('minimised')
this.navPath = this.querySelector('input').value
const nestedUls = this.querySelectorAll('li > ul')
const nestedNavs = []
for (const ulEl of nestedUls) {
if (ulEl.children.length > 0) {
nestedNavs.push(ulEl.cloneNode(true))
ulEl.remove()
}
}
this.querySelector('button').addEventListener('click', () => {
this.classList.toggle('minimised')
})
}
for (const newUl of nestedNavs) {
const newNav = document.createElement('alx-subnav')
this.append(newNav)
newNav.querySelector('nav').append(newUl)
}
attributeChangedCallback(name, ov, nv) {
switch (name) {
case 'navpage':
this.navPage = nv
break
const brokenPath = window.location.pathname.replaceAll(/((^\/)|((\/|\W)+)$)/g, '').split('/')
console.log(`path: ${brokenPath}`, `navPath: ${this.navPath}` )
if (brokenPath[0] === this.navPath) {
this.querySelector('input').checked = true
this.classList.remove('hidden')
}
}

@ -4,7 +4,16 @@ layout: base
<main>
<h1 @text="title"></h1>
<article>
<h2 class="txt-trim" @text="title"></h2>
<template webc:nokeep @raw="content"></template>
<template webc:nokeep @raw="content"></template>
</article>
</main>
<template webc:nokeep webc:if="imageGallery">
<input type="checkbox" name="gallery"></input>
<div class="gallery">
<img webc:for="img of imageGallery" :src="img.src" :alt="img.alt">
</div>
</template>

@ -1,9 +0,0 @@
---
layout: base
---
<main>
<h1 @text="title"></h1>
<template webc:nokeep @raw="content"></template>
</main>