Basic layout and styles with some fancy transitions
This commit is contained in:
parent
654521b04d
commit
ba4f8527af
@ -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",
|
||||
|
BIN
src/assets/images/perception.1.webp
Normal file
BIN
src/assets/images/perception.1.webp
Normal file
Binary file not shown.
After ![]() (image error) Size: 93 KiB |
BIN
src/assets/images/perception.2.webp
Normal file
BIN
src/assets/images/perception.2.webp
Normal file
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;
|
||||
}
|
||||
|
56
src/assets/styles/type.css
Normal file
56
src/assets/styles/type.css
Normal file
@ -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.
|
||||
|
10
src/content/art/2-and-2-aint-22.md
Normal file
10
src/content/art/2-and-2-aint-22.md
Normal file
@ -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 city’s fast-paced reality and fleeting memory. Each skater’s 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 city’s 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
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
|
||||
---
|
||||
|
13
src/content/art/let-my-baby-stay.md
Normal file
13
src/content/art/let-my-baby-stay.md
Normal file
@ -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 isn’t 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.
|
||||
|
14
src/content/art/perception.md
Normal file
14
src/content/art/perception.md
Normal file
@ -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
|
||||
---
|
||||
|
4
src/content/research/research.json
Normal file
4
src/content/research/research.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"tags": ["research"],
|
||||
"layout": "page"
|
||||
}
|
1
src/data/eleventyComputed.js
Normal file
1
src/data/eleventyComputed.js
Normal file
@ -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>
|
Loading…
x
Reference in New Issue
Block a user