diff options
| author | Ariel Costas Guerrero <ariel@costas.dev> | 2025-06-07 20:17:01 +0200 |
|---|---|---|
| committer | Ariel Costas Guerrero <ariel@costas.dev> | 2025-06-07 20:17:01 +0200 |
| commit | 6cb688bd1b2285fb917194852fdc285c798d43cc (patch) | |
| tree | 535293539e53dfa3ec3aeca8f217b6d066350c75 | |
| parent | 36d3a2c4c6dbfcc74271d0956eff9b1e454fc138 (diff) | |
Add new images and update portfolio layouts for enhanced presentation
19 files changed, 551 insertions, 210 deletions
diff --git a/public/images/portfolio/mapa-ferrol/home-info-narrow.png b/public/images/portfolio/mapa-ferrol/home-info-narrow.png Binary files differnew file mode 100644 index 0000000..5e9a0de --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/home-info-narrow.png diff --git a/public/images/portfolio/mapa-ferrol/home-info-narrow.webp b/public/images/portfolio/mapa-ferrol/home-info-narrow.webp Binary files differnew file mode 100644 index 0000000..9a24c99 --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/home-info-narrow.webp diff --git a/public/images/portfolio/mapa-ferrol/home-narrow.png b/public/images/portfolio/mapa-ferrol/home-narrow.png Binary files differnew file mode 100644 index 0000000..52f2ffe --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/home-narrow.png diff --git a/public/images/portfolio/mapa-ferrol/home-narrow.webp b/public/images/portfolio/mapa-ferrol/home-narrow.webp Binary files differnew file mode 100644 index 0000000..c060969 --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/home-narrow.webp diff --git a/public/images/portfolio/mapa-ferrol/planner-narrow.png b/public/images/portfolio/mapa-ferrol/planner-narrow.png Binary files differnew file mode 100644 index 0000000..62386ba --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/planner-narrow.png diff --git a/public/images/portfolio/mapa-ferrol/planner-narrow.webp b/public/images/portfolio/mapa-ferrol/planner-narrow.webp Binary files differnew file mode 100644 index 0000000..3644a8e --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/planner-narrow.webp diff --git a/public/images/portfolio/mapa-ferrol/route-id-narrow.png b/public/images/portfolio/mapa-ferrol/route-id-narrow.png Binary files differnew file mode 100644 index 0000000..92ec224 --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/route-id-narrow.png diff --git a/public/images/portfolio/mapa-ferrol/route-id-narrow.webp b/public/images/portfolio/mapa-ferrol/route-id-narrow.webp Binary files differnew file mode 100644 index 0000000..d78622e --- /dev/null +++ b/public/images/portfolio/mapa-ferrol/route-id-narrow.webp diff --git a/src/content.config.ts b/src/content.config.ts index f3d7755..acaaf8a 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -20,7 +20,9 @@ const portfolio = defineCollection({ githubLink: z.string().url().optional(), onlineLink: z.string().url().optional(), demoLink: z.string().url().optional(), - images: z.array(z.string()).default([]) + images: z.array( + z.object({ src: z.string(), alt: z.string() }) + ).default([]) }), }); diff --git a/src/data/portfolio/mapa-ferrol.mdx b/src/data/portfolio/mapa-ferrol.mdx index 144ac62..6152ced 100644 --- a/src/data/portfolio/mapa-ferrol.mdx +++ b/src/data/portfolio/mapa-ferrol.mdx @@ -3,16 +3,43 @@ title: "Mapa de patrimonio da Costa Ártabra" description: "Desarrollo de una aplicación completa para el patrimonio cultural y militar de la Costa Ártabra." technologies: ["dotnet", "react", "mysql", "ubuntu"] onlineLink: "https://mapacostaartabramilitar.com" +images: +- src: "/images/portfolio/mapa-ferrol/home-narrow" + alt: "Vista principal del mapa con los elementos del patrimonio" +- src: "/images/portfolio/mapa-ferrol/home-info-narrow" + alt: "Sheet con información de un elemento patrimonial" +- src: "/images/portfolio/mapa-ferrol/route-id-narrow" + alt: "Vista de una ruta predefinida" +- src: "/images/portfolio/mapa-ferrol/planner-narrow" + alt: "Planificador de rutas de senderismo" --- -Se desarrolló una aplicación web completa para la gestión del patrimonio cultural y militar de la Costa Ártabra, en Galicia, España. Esta aplicación permite a los usuarios explorar y descubrir el patrimonio de la región (Ferrol, Ares y Valdoviño) incluyendo las baterías militares, faros, iglesias, miradores, playas, etc. +Desarrollo de una **aplicación web integral** para la exploración del patrimonio cultural y militar de la Costa Ártabra (Ferrol, Ares, Valdoviño). La plataforma incluye baterías costeras, faros, rutas de senderismo y puntos de interés natural, ofreciendo una experiencia adaptada principalmente a dispositivos móviles. -La aplicación está desarrollada con ASP.NET Core y React, utilizando una base de datos MySQL para almacenar la información del patrimonio y permitir al personal de la administración añadir, editar y eliminar elementos del patrimonio. +Tecnologías clave: -Para la parte del frontend, se utilizó React con TypeScript, creando una interfaz de usuario intuitiva y fluida, adaptándose primordialmente a dispositivos móviles. Además, se implementó un mapa interactivo utilizando MapLibre y capas de OpenStreetMap (mapa base) y el PNOA (Satélite del IGN) para mostrar la ubicación de los elementos del patrimonio. +* Backend con ASP.NET Core y base de datos MySQL. +* Frontend en React (TypeScript) y mapas interactivos con MapLibre. +* Teselas vectoriales de OpenStreetMap con [Protomaps](https://protomaps.com/) para un mapa de alta calidad y buen rendimiento. +* Calculador de rutas autoalojado con [OSRM](https://project-osrm.org/) para optimización de rutas. -La aplicación también incluye un sistema de rutas de senderismo, tanto proporcionadas por la administración como generadas a medida por los usuarios, permitiendo a los visitantes explorar la región a su manera. +Diseñada para autonomía y privacidad: -Una complejidad destacable fue hacer la aplicación rápida y fluida para el usuario, para garantizar la mejor experiencia posible al navegar por el patrimonio, sobre todo desde dispositivos móviles en redes móviles. +* Infraestructura autoalojada (Ubuntu) sin dependencia de APIs comerciales. +* Optimización de rutas con motor de cálculo interno (OSRM). +* Panel de administración para gestión centralizada del patrimonio. + +## Características clave + +1. **Tecnologías autónomas**: Implementación sin dependencia de servicios externos (como Google Maps), garantizando privacidad del usuario y reducción de costos. + +2. **Gestión de recursos**: Solución personalizada para iconografía y capas de mapa, asegurando consistencia visual y eficiencia. + +3. **Planificación de rutas inteligente**: Sistema de optimización para senderismo basado en puntos patrimoniales, con énfasis en rendimiento y estabilidad. + +4. **Panel de administración**: Herramienta interna para gestión de contenido por personal no técnico. + + +--- Desarrollado en 2025 en colaboración con [Kendra](https://kendra.es/). diff --git a/src/layouts/BlogSingleLayout.astro b/src/layouts/BlogSingleLayout.astro new file mode 100644 index 0000000..0c3b934 --- /dev/null +++ b/src/layouts/BlogSingleLayout.astro @@ -0,0 +1,134 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import { getCollection, render } from "astro:content"; +import { type GetStaticPaths } from "astro"; + +interface Props { + entry: any; +} + +export const getStaticPaths: GetStaticPaths = async () => { + const entries = await getCollection("blog"); + return entries.map((entry: any) => ({ + params: { id: entry.id }, + props: { entry }, + })); +}; + +const { entry } = Astro.props; +const { Content } = await render(entry); +const formattedDate = new Date(entry.data.publishedAt).toLocaleDateString( + "es-ES", + { + year: "numeric", + month: "long", + day: "numeric", + weekday: "long", + }, +); + +const schema = { + "@context": "https://schema.org", + "@type": "BlogPosting", + headline: entry.data.title, + datePublished: entry.data.publishedAt.toISOString(), + keywords: entry.data.tags || [], + author: { + "@type": "Person", + name: "Ariel Costas Guerrero", + }, + publisher: { + "@type": "Person", + name: "Ariel Costas Guerrero", + url: "https://www.costas.dev", + image: { + "@type": "ImageObject", + url: "https://www.costas.dev/favicon.png", + }, + }, +}; +--- + +<Layout title={entry.data.title} description={entry.data.metaDescription}> + <script + is:inline + type="application/ld+json" + slot="head-jsonld" + set:html={JSON.stringify(schema)} + /> + + <h1>{entry.data.title}</h1> + <small> + Publicado el + <time datetime={entry.data.publishedAt.toISOString()}> + {formattedDate} + </time> + {entry.data.tags && entry.data.tags.length > 0 && ( + <> + • Etiquetas: + <ul class="tags"> + {entry.data.tags.map((tag: string) => ( + <li><a href={`/blog/?tag=${encodeURIComponent(tag)}`}>{tag}</a></li> + ))} + </ul> + </> + )} + </small> + + <Content /> + + <p> + <a href="/blog">Volver al blog</a> + </p> +</Layout> + +<style lang="scss"> + @use "../../styles/variables" as v; + @use "sass:color"; + + .tags { + display: inline-flex; + list-style: none; + margin: 0; + padding: 0; + gap: 0.75rem; + } + + .tags li { + display: inline; + } + + .tags a { + // Estilo de enlace normal, siguiendo los estilos predefinidos en Layout.astro + color: v.$accentDark; + font-size: 0.85rem; + font-family: v.$monoFontStack; + text-decoration: none; + box-shadow: 0 1px v.$accent; + transition: all 0.2s ease; + + &:hover { + box-shadow: 0 2px v.$accentDark; + } + + &:focus { + color: v.$accentDark; + outline: none; + background-color: v.$secondary; + box-shadow: 0 4px #0b0c0c; + } + } + + /* Estilos para la información de la publicación */ + small { + display: block; + margin-top: -1rem; + margin-bottom: 1.5rem; + font-size: 0.85rem; + color: color.adjust(v.$dark, $lightness: 30%); + } + + time { + font-style: italic; + } +</style> diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index d23d212..20dca59 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -181,7 +181,6 @@ const { title, description, empty } = Astro.props; main a, footer a { text-decoration: none; - padding: 0.1rem; box-shadow: 0 1px $accent; &:hover { diff --git a/src/layouts/PortfolioItemLayout.astro b/src/layouts/PortfolioItemLayout.astro deleted file mode 100644 index 95715cb..0000000 --- a/src/layouts/PortfolioItemLayout.astro +++ /dev/null @@ -1,77 +0,0 @@ ---- -import Layout from "@/layouts/Layout.astro"; -import { render } from "astro:content"; -import TechnologyBadge from "@/components/TechnologyBadge.astro"; -import type { InferEntrySchema } from "astro:content"; -import { Icon } from "astro-icon/components"; - -interface Props { - entry: any; -} - -const { entry } = Astro.props; -const data = entry.data as InferEntrySchema<"portfolio">; -const { Content } = await render(entry); ---- - -<Layout title={data.title} description={data.description}> - <a id="link-back" href="/portfolio"> - <svg - xmlns="http://www.w3.org/2000/svg" - viewBox="0 0 24 24" - fill="none" - stroke="currentColor" - stroke-width="2" - stroke-linecap="round" - stroke-linejoin="round" - class="w-6 h-6 inline-block mr-2" - > - <polyline points="15 18 9 12 15 6"></polyline> - </svg> - Volver al portfolio - </a> - - <h1>{data.title}</h1> - - <Content /> - - <div> - {data.githubLink && <a href={data.githubLink}> - <Icon name="tabler:brand-github"/> - GitHub - </a>} - - {data.onlineLink && <a href={data.onlineLink} target="_blank" rel="noopener noreferrer"> - <Icon name="tabler:link"/> - En línea - </a>} - - {data.demoLink && <a href={data.demoLink} target="_blank" rel="noopener noreferrer"> - <Icon name="tabler:link"/> - Demo - </a>} - </div> - - <h2>Tecnologías utilizadas</h2> - - { - data.technologies.map((technology: string) => ( - <TechnologyBadge size="small" code={technology} /> - )) - } -</Layout> - -<style> - a#link-back { - display: inline-flex; - align-items: center; - gap: 0.5rem; - text-decoration: none; - text-transform: uppercase; - transition: color 0.2s ease-in-out; - } - - a#link-back svg { - height: 1em; - } -</style> diff --git a/src/layouts/PortfolioPageLayout.astro b/src/layouts/PortfolioListLayout.astro index b894f9f..b894f9f 100644 --- a/src/layouts/PortfolioPageLayout.astro +++ b/src/layouts/PortfolioListLayout.astro diff --git a/src/layouts/PortfolioSingleLayout.astro b/src/layouts/PortfolioSingleLayout.astro new file mode 100644 index 0000000..8ca8cbb --- /dev/null +++ b/src/layouts/PortfolioSingleLayout.astro @@ -0,0 +1,370 @@ +--- +import Layout from "@/layouts/Layout.astro"; +import { render } from "astro:content"; +import TechnologyBadge from "@/components/TechnologyBadge.astro"; +import type { InferEntrySchema } from "astro:content"; +import { Icon } from "astro-icon/components"; + +interface Props { + entry: any; +} + +const { entry } = Astro.props; +const data = entry.data as InferEntrySchema<"portfolio">; +const { Content } = await render(entry); +--- + +<Layout title={data.title} description={data.description}> + <a id="link-back" href="/portfolio"> + <svg + xmlns="http://www.w3.org/2000/svg" + viewBox="0 0 24 24" + fill="none" + stroke="currentColor" + stroke-width="2" + stroke-linecap="round" + stroke-linejoin="round" + class="w-6 h-6 inline-block mr-2" + > + <polyline points="15 18 9 12 15 6"></polyline> + </svg> + Volver al portfolio + </a> + + <h1>{data.title}</h1> + + <small>Hecho con {data.technologies.map((technology: string) => ( + <TechnologyBadge size="small" code={technology} /> + ))}</small> + + <Content /> + + <div class="project-links"> + {data.githubLink && <a href={data.githubLink} target="_blank" rel="noopener noreferrer" class="project-link"> + <Icon name="tabler:brand-github" class="link-icon"/> + <span>Código en GitHub</span> + </a>} + + {data.onlineLink && <a href={data.onlineLink} target="_blank" rel="noopener noreferrer" class="project-link"> + <Icon name="tabler:external-link" class="link-icon"/> + <span>Ver en línea</span> + </a>} + + {data.demoLink && <a href={data.demoLink} target="_blank" rel="noopener noreferrer" class="project-link"> + <Icon name="tabler:device-laptop" class="link-icon"/> + <span>Ver demo</span> + </a>} + </div> + + {data.images.length > 0 && ( + <h2>Galería</h2> + <section id="project-images"> + {data.images.map((image) => ( + <a href={`${image.src}.png`} target="_blank" rel="noopener noreferrer"> + <picture> + <source + srcset={`${image.src}.webp`} + type="image/webp" + /> + <img src={`${image.src}.png`} alt={image.alt} loading="lazy" /> + </picture> + </a> + ))} + </section> + )} + + <dialog id="largeimage-dialog"> + <div id="largeimage-dialogcontainer"> + <button class="largeimage__nav" aria-label="Previous image" id="largeimage__nav-left"> + <Icon name="tabler:chevron-left" /> + </button> + <div id="largeimage-imagecontainer"> + <img id="largeimage-image" alt="Some alt" /> + </div> + <div id="largeimage-caption">Some caption</div> + <button class="largeimage__nav" aria-label="Next image" id="largeimage__nav-right"> + <Icon name="tabler:chevron-right" /> + </button> + <button id="largeimage-close"><Icon name="tabler:x" /></button> + </div> + </dialog> + +</Layout> + +<script> + document.addEventListener("DOMContentLoaded", () => { + const dialog = document.getElementById("largeimage-dialog") as HTMLDialogElement; + const closeButton = document.getElementById("largeimage-close") as HTMLButtonElement; + const imageElement = document.getElementById("largeimage-image") as HTMLImageElement; + const captionElement = document.getElementById("largeimage-caption") as HTMLDivElement; + const navLeft = document.getElementById("largeimage__nav-left") as HTMLButtonElement; + const navRight = document.getElementById("largeimage__nav-right") as HTMLButtonElement; + const imageLinks = Array.from(document.querySelectorAll("#project-images a")) as HTMLAnchorElement[]; + + const images = imageLinks.map(link => { + const img = link.querySelector("img"); + return { + src: img?.src, + alt: img?.alt + }; + }); + let currentIndex = 0; + + function showImage(index: number) { + if (index < 0 || index >= images.length) return; + currentIndex = index; + const { src, alt } = images[currentIndex]; + if (!imageElement || !captionElement) { + console.error("Image or caption element not found"); + return; + } + imageElement.src = src!; + imageElement.alt = alt!; + captionElement.textContent = alt || "Imagen del proyecto"; + } + + if (!dialog || !closeButton || !imageElement || !captionElement) { + console.error("Dialog or elements not found"); + return; + } + + imageLinks.forEach((link, idx) => { + link.addEventListener("click", (e) => { + e.preventDefault(); + showImage(idx); + dialog.showModal(); + }); + }); + + closeButton.addEventListener("click", () => { + dialog.close(); + }); + + if (navLeft) { + navLeft.addEventListener("click", (e) => { + e.preventDefault(); + showImage((currentIndex - 1 + images.length) % images.length); + }); + } + if (navRight) { + navRight.addEventListener("click", (e) => { + e.preventDefault(); + showImage((currentIndex + 1) % images.length); + }); + } + + dialog.addEventListener("keydown", (e) => { + if (e.key === "ArrowLeft") { + showImage((currentIndex - 1 + images.length) % images.length); + } else if (e.key === "ArrowRight") { + showImage((currentIndex + 1) % images.length); + } else if (e.key === "Escape") { + dialog.close(); + } + }); + + dialog.addEventListener("shown", () => { + dialog.focus(); + }); + + dialog.addEventListener("open", () => { + dialog.focus(); + }); + + dialog.addEventListener("click", (e) => { + if (e.target === dialog) { + dialog.close(); + } + }); + }); +</script> + +<style> + a#link-back { + display: inline-flex; + align-items: center; + gap: 0.5rem; + text-decoration: none; + text-transform: uppercase; + transition: color 0.2s ease-in-out; + } + + a#link-back svg { + height: 1em; + } + + #project-images { + display: flex; + flex-direction: row; + gap: 1.5rem; + margin: 1.5rem 0 2rem; + overflow-x: auto; + padding-bottom: 1rem; + -webkit-overflow-scrolling: touch; + scrollbar-width: thin; + } + + #project-images a { + display: block; + flex: 0 0 auto; + box-shadow: none; + text-decoration: none; + padding: 0; + } + + #project-images picture { + display: block; + overflow: hidden; + border-radius: 0.25rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + height: max(20vh, 400px); + } + + #project-images img { + height: 100%; + object-fit: cover; + } + + #project-images a { + position: relative; + } + + .project-links { + display: flex; + gap: 1rem; + flex-wrap: wrap; + margin: 1.5rem 0 2.5rem; + } + + .project-link { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 1.25rem; + border-radius: 2rem; + background-color: #f3f4f6; + color: #333; + font-weight: 600; + text-decoration: none; + box-shadow: none; + transition: all 0.2s ease-in-out; + + &:hover { + background-color: #e5e7eb; + transform: translateY(-2px); + box-shadow: none; + } + + &:focus { + outline: 2px solid $secondary; + background-color: #e5e7eb; + box-shadow: none; + } + + .link-icon { + font-size: 1.2rem; + } + } + + #largeimage-dialog { + padding: 0; + border: none; + background: transparent; + max-width: 100vw; + max-height: 100vh; + margin: auto; + } + + #largeimage-dialog::backdrop { + background: #000c; + } + + #largeimage-dialogcontainer { + position: relative; + display: flex; + flex-direction: column; + gap: 1rem; + height: 100%; + padding: 1.5rem; + } + + #largeimage-imagecontainer { + max-width: 100%; + max-height: calc(100vh - 2rem); + overflow: hidden; + position: relative; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + #largeimage-image { + object-fit: cover; + max-width: 100%; + max-height: calc(100vh - 9rem); + + border-radius: 0.5rem; + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); + } + + #largeimage-caption { + position: static; + background: #FFFC; + color: #000; + font-size: 1rem; + text-align: center; + border-radius: 0.5rem; + padding: 0.75rem 1rem; + max-width: 100%; + } + + #largeimage-close { + position: absolute; + top: 1rem; + right: 1rem; + width: 2rem; + height: 2rem; + border: none; + background: #fffc; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.5rem; + color: #000; + transition: background-color .2s; + } + + .largeimage__nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 2.5rem; + height: 2.5rem; + border: none; + background: #fffc; + border-radius: 50%; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 2rem; + z-index: 2; + color: #000; + transition: background-color .2s; + } + + #largeimage__nav-left { + left: 1rem; + } + #largeimage__nav-right { + right: 1rem; + } + + .largeimage__nav:hover, + #largeimage-close:hover { + background-color: #FFFFFF; + } +</style> diff --git a/src/pages/blog/[id].astro b/src/pages/blog/[id].astro index 3dc324a..8f02b65 100644 --- a/src/pages/blog/[id].astro +++ b/src/pages/blog/[id].astro @@ -1,11 +1,7 @@ --- -import Layout from "@/layouts/Layout.astro"; -import { getCollection, render } from "astro:content"; -import { type GetStaticPaths } from "astro"; - -interface Props { - entry: any; -} +import type { GetStaticPaths } from "astro"; +import { getCollection } from "astro:content"; +import BlogSingleLayout from "@/layouts/BlogSingleLayout.astro"; export const getStaticPaths: GetStaticPaths = async () => { const entries = await getCollection("blog"); @@ -16,119 +12,6 @@ export const getStaticPaths: GetStaticPaths = async () => { }; const { entry } = Astro.props; -const { Content } = await render(entry); -const formattedDate = new Date(entry.data.publishedAt).toLocaleDateString( - "es-ES", - { - year: "numeric", - month: "long", - day: "numeric", - weekday: "long", - }, -); - -const schema = { - "@context": "https://schema.org", - "@type": "BlogPosting", - headline: entry.data.title, - datePublished: entry.data.publishedAt.toISOString(), - keywords: entry.data.tags || [], - author: { - "@type": "Person", - name: "Ariel Costas Guerrero", - }, - publisher: { - "@type": "Person", - name: "Ariel Costas Guerrero", - url: "https://www.costas.dev", - image: { - "@type": "ImageObject", - url: "https://www.costas.dev/favicon.png", - }, - }, -}; --- -<Layout title={entry.data.title} description={entry.data.metaDescription}> - <script - is:inline - type="application/ld+json" - slot="head-jsonld" - set:html={JSON.stringify(schema)} - /> - - <h1>{entry.data.title}</h1> - <small> - Publicado el - <time datetime={entry.data.publishedAt.toISOString()}> - {formattedDate} - </time> - {entry.data.tags && entry.data.tags.length > 0 && ( - <> - • Etiquetas: - <ul class="tags"> - {entry.data.tags.map((tag: string) => ( - <li><a href={`/blog/?tag=${encodeURIComponent(tag)}`}>{tag}</a></li> - ))} - </ul> - </> - )} - </small> - - <Content /> - - <p> - <a href="/blog">Volver al blog</a> - </p> -</Layout> - -<style lang="scss"> - @use "../../../styles/variables" as v; - @use "sass:color"; - - .tags { - display: inline-flex; - list-style: none; - margin: 0; - padding: 0; - gap: 0.75rem; - } - - .tags li { - display: inline; - } - - .tags a { - // Estilo de enlace normal, siguiendo los estilos predefinidos en Layout.astro - color: v.$accentDark; - font-size: 0.85rem; - font-family: v.$monoFontStack; - text-decoration: none; - box-shadow: 0 1px v.$accent; - transition: all 0.2s ease; - - &:hover { - box-shadow: 0 2px v.$accentDark; - } - - &:focus { - color: v.$accentDark; - outline: none; - background-color: v.$secondary; - box-shadow: 0 4px #0b0c0c; - } - } - - /* Estilos para la información de la publicación */ - small { - display: block; - margin-top: -1rem; - margin-bottom: 1.5rem; - font-size: 0.85rem; - color: color.adjust(v.$dark, $lightness: 30%); - } - - time { - font-style: italic; - } -</style> +<BlogSingleLayout entry={entry} /> diff --git a/src/pages/portfolio/[id].astro b/src/pages/portfolio/[id].astro index 601ff84..7424b91 100644 --- a/src/pages/portfolio/[id].astro +++ b/src/pages/portfolio/[id].astro @@ -1,7 +1,7 @@ --- import type { GetStaticPaths } from "astro"; import { getCollection } from "astro:content"; -import PortfolioItemLayout from "@/layouts/PortfolioItemLayout.astro"; +import PortfolioSingleLayout from "@/layouts/PortfolioSingleLayout.astro"; export const getStaticPaths: GetStaticPaths = async () => { const entries = await getCollection("portfolio"); @@ -14,4 +14,4 @@ export const getStaticPaths: GetStaticPaths = async () => { const { entry } = Astro.props; --- -<PortfolioItemLayout entry={entry} /> +<PortfolioSingleLayout entry={entry} /> diff --git a/src/pages/portfolio/index.astro b/src/pages/portfolio/index.astro index f5f1250..c12ab23 100644 --- a/src/pages/portfolio/index.astro +++ b/src/pages/portfolio/index.astro @@ -1,5 +1,5 @@ --- -import PortfolioPageLayout from "@/layouts/PortfolioPageLayout.astro"; +import PortfolioListLayout from "@/layouts/PortfolioListLayout.astro"; --- -<PortfolioPageLayout /> +<PortfolioListLayout /> diff --git a/styles/shared.scss b/styles/shared.scss index 5844332..6078053 100644 --- a/styles/shared.scss +++ b/styles/shared.scss @@ -7,7 +7,6 @@ %heading { font-family: $titleFontStack; - line-height: 1.55; margin-block-start: 0.75em; margin-block-end: 0.25em; } @@ -15,19 +14,23 @@ h1 { @extend %heading; font-size: 3.55rem; + line-height: 1.3; } h2 { @extend %heading; font-size: 2.75rem; + line-height: 1.55; } h3 { @extend %heading; font-size: 2rem; + line-height: 1.55; } h4 { @extend %heading; font-size: 1.25rem; + line-height: 1.55; } |
