diff --git a/.astro-i18n/generated.d.ts b/.astro-i18n/generated.d.ts new file mode 100644 index 0000000..b6ce77b --- /dev/null +++ b/.astro-i18n/generated.d.ts @@ -0,0 +1,23 @@ +type LangCode = "fr" | "en" +type RouteUri = | "/articles" | "/tags/[tag]" | "/tags" | "/" +type RouteParams = {"/articles": undefined; "/tags/[tag]": { "tag": string; }; "/tags": undefined; "/": undefined; } +type TranslationPath = "accueil" | "tagline" | "copyright" | "contact" | "contactLien" | "contactTel" | "contenuVide" | "header.skipLink" | "header.mainNav" | "header.homeLink" | "sitemap" | "prevNext.contenus" | "prevNext.precedent" | "prevNext.suivant" | "article.titre" | "article.tagline" | "meta.publication" | "meta.modification" | "meta.credit" | "fragments.titre" | "fragments.tagline" | "projet.titre" | "projet.tagline" | "projet.cta" | "projet.lienTitle" | "projet.fenetre" | "erreur.introuvable" | "erreur.autre" | "erreur.lienRetour" | "seo.article.title" | "seo.article.description" | "seo.projet.title" | "seo.projet.description" | "seo.code.title" | "seo.code.description" | "index.articles" | "index.title" | "index.quoi" | "index.comment" | "index.opensource" | "index.projetsRecents" | "index.articlesRecents" +type TranslationOptions = { "accueil": {} | undefined; "tagline": {} | undefined; "copyright": {} | undefined; "contact": {} | undefined; "contactLien": {} | undefined; "contactTel": {} | undefined; "contenuVide": {} | undefined; "header.skipLink": {} | undefined; "header.mainNav": {} | undefined; "header.homeLink": {} | undefined; "sitemap": {} | undefined; "prevNext.contenus": {} | undefined; "prevNext.precedent": {} | undefined; "prevNext.suivant": {} | undefined; "article.titre": {} | undefined; "article.tagline": {} | undefined; "meta.publication": {} | undefined; "meta.modification": {} | undefined; "meta.credit": {} | undefined; "fragments.titre": {} | undefined; "fragments.tagline": {} | undefined; "projet.titre": {} | undefined; "projet.tagline": {} | undefined; "projet.cta": {} | undefined; "projet.lienTitle": {} | undefined; "projet.fenetre": {} | undefined; "erreur.introuvable": {} | undefined; "erreur.autre": {} | undefined; "erreur.lienRetour": {} | undefined; "seo.article.title": {} | undefined; "seo.article.description": {} | undefined; "seo.projet.title": {} | undefined; "seo.projet.description": {} | undefined; "seo.code.title": {} | undefined; "seo.code.description": {} | undefined; "index.articles": {} | undefined; "index.title": {} | undefined; "index.quoi": {} | undefined; "index.comment": {} | undefined; "index.opensource": {} | undefined; "index.projetsRecents": {} | undefined; "index.articlesRecents": {} | undefined; } + +declare module "astro-i18n" { + export * from "astro-i18n/" + + export function l( + route: Uri, + ...args: undefined extends RouteParams[Uri] + ? [params?: RouteParams[Uri], query?: Record, langCode?: LangCode] + : [params: RouteParams[Uri], query?: Record, langCode?: LangCode] + ): string + + export function t( + path: Path, + ...args: undefined extends TranslationOptions[Path] + ? [options?: TranslationOptions[Path], langCode?: LangCode] + : [options: TranslationOptions[Path], langCode?: LangCode] + ): string +} diff --git a/astro.config.mjs b/astro.config.mjs index f50b6e5..843acd2 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,12 +1,13 @@ import { defineConfig } from "astro/config"; +// https://github.com/alexandre-fernandez/astro-i18n +import i18n from "astro-i18n"; + // https://astro.build/config import image from "@astrojs/image"; - -// https://astro.build/config import mdx from "@astrojs/mdx"; // https://astro.build/config export default defineConfig({ - integrations: [image(), mdx()] -}); \ No newline at end of file + integrations: [i18n(), image(), mdx()], +}); diff --git a/astro.i18n.config.ts b/astro.i18n.config.ts new file mode 100644 index 0000000..b3e529f --- /dev/null +++ b/astro.i18n.config.ts @@ -0,0 +1,12 @@ +import { defineAstroI18nConfig } from "astro-i18n"; + +export default defineAstroI18nConfig({ + defaultLangCode: "fr", + supportedLangCodes: ["en"], + showDefaultLangCode: false, + translations: { + fr: "src/i18n/fr.json", + en: "src/i18n/en.json", + }, + routeTranslations: {}, +}); diff --git a/package.json b/package.json index 5196099..fc6b92e 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,16 @@ "start": "astro dev", "build": "astro build", "preview": "astro preview", - "astro": "astro" + "astro": "astro", + "i18n:install": "astro-i18n install", + "i18n:sync": "astro-i18n sync" }, "dependencies": { "@astrojs/image": "^0.11.2", "@astrojs/mdx": "^0.11.5", "@astrojs/rss": "^1.0.3", "astro": "^1.6.0", + "astro-i18n": "^1.1.7", "open-props": "^1.4.24" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0870ac3..10f1e83 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,10 +1,11 @@ -lockfileVersion: 5.3 +lockfileVersion: 5.4 specifiers: '@astrojs/image': ^0.11.2 '@astrojs/mdx': ^0.11.5 '@astrojs/rss': ^1.0.3 astro: ^1.6.0 + astro-i18n: ^1.1.7 open-props: ^1.4.24 dependencies: @@ -12,6 +13,7 @@ dependencies: '@astrojs/mdx': 0.11.5 '@astrojs/rss': 1.0.3 astro: 1.6.5 + astro-i18n: 1.1.7 open-props: 1.4.24 packages: @@ -779,6 +781,13 @@ packages: hasBin: true dev: false + /astro-i18n/1.1.7: + resolution: {integrity: sha512-ejqCg44R6NGsEJiqMRgDgIZAdFzGI+Oy0xDdii14GK/Aclwx41Zf7N+oysZwHGiXVFz62CZLim4VS5ndCtnmfQ==} + hasBin: true + dependencies: + get-file-exports: 1.2.1 + dev: false + /astro/1.6.5: resolution: {integrity: sha512-PBjtMJeCRTkvG2ExMpfDUEc7FbwpJ/pxixe7Kt1Z9dfggofGLXnNa5JxzvacuotI1u35wb9nwQ7aI4Uyk5Ellg==} engines: {node: ^14.18.0 || >=16.12.0, npm: '>=6.14.0'} @@ -1764,6 +1773,13 @@ packages: engines: {node: '>=6.9.0'} dev: false + /get-file-exports/1.2.1: + resolution: {integrity: sha512-wkhgR++d7jTAFq0f8UEyOojvtMn/EOduoTvHhp2h5OnyT+GoC4PqfKCrfyzzzrHcmKD/7sadsYWqO/tNuBHkfw==} + dependencies: + esbuild: 0.15.13 + node-eval: 2.0.0 + dev: false + /get-intrinsic/1.1.3: resolution: {integrity: sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==} dependencies: @@ -2849,6 +2865,13 @@ packages: engines: {node: '>=10.5.0'} dev: false + /node-eval/2.0.0: + resolution: {integrity: sha512-Ap+L9HznXAVeJj3TJ1op6M6bg5xtTq8L5CU/PJxtkhea/DrIxdTknGKIECKd/v/Lgql95iuMAYvIzBNd0pmcMg==} + engines: {node: '>= 4'} + dependencies: + path-is-absolute: 1.0.1 + dev: false + /node-fetch/3.2.10: resolution: {integrity: sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -2983,6 +3006,11 @@ packages: engines: {node: '>=8'} dev: false + /path-is-absolute/1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} diff --git a/postcss.config.cjs b/postcss.config.cjs new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Header.astro b/src/components/Header.astro index 4a2cb17..089585b 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -1,7 +1,52 @@ --- -import Navigation from '../components/Navigation.astro'; +import { t, l } from "astro-i18n"; + +import Navigation from "../components/Navigation.astro"; --- -
+ \ No newline at end of file +
+ + diff --git a/src/components/LanguageSwitcher.astro b/src/components/LanguageSwitcher.astro new file mode 100644 index 0000000..391c25c --- /dev/null +++ b/src/components/LanguageSwitcher.astro @@ -0,0 +1,21 @@ +--- +import { l, astroI18n } from "astro-i18n"; + +// get the locale currently in use +const currentLocale = astroI18n.langCode; +// get all the locales available on the website and remove the one currently in use +const availableLocales = astroI18n.langCodes.filter( + (locale) => locale !== currentLocale +); +--- + +
    + { + // create a list of available alternative locale + availableLocales.map((locale) => ( +
  • + {locale} +
  • + )) + } +
diff --git a/src/components/Navigation.astro b/src/components/Navigation.astro index d56d0b5..f3df1ad 100644 --- a/src/components/Navigation.astro +++ b/src/components/Navigation.astro @@ -1,10 +1,44 @@ --- +import { t, l } from "astro-i18n"; +import LanguageSwitcher from "./LanguageSwitcher.astro"; +--- ---- - + + diff --git a/src/env.d.ts b/src/env.d.ts index 9231795..bb78a58 100644 --- a/src/env.d.ts +++ b/src/env.d.ts @@ -1 +1,3 @@ /// + +/// diff --git a/src/fonts/recoleta/Recoleta-Bold.woff2 b/src/fonts/recoleta/Recoleta-Bold.woff2 new file mode 100644 index 0000000..d80c6a9 Binary files /dev/null and b/src/fonts/recoleta/Recoleta-Bold.woff2 differ diff --git a/src/fonts/recoleta/Recoleta-SemiBold.woff2 b/src/fonts/recoleta/Recoleta-SemiBold.woff2 new file mode 100644 index 0000000..80d7261 Binary files /dev/null and b/src/fonts/recoleta/Recoleta-SemiBold.woff2 differ diff --git a/src/fonts/wotfard/wotfard-medium-webfont.woff2 b/src/fonts/wotfard/wotfard-medium-webfont.woff2 new file mode 100644 index 0000000..4af2f23 Binary files /dev/null and b/src/fonts/wotfard/wotfard-medium-webfont.woff2 differ diff --git a/src/fonts/wotfard/wotfard-regular-webfont.woff2 b/src/fonts/wotfard/wotfard-regular-webfont.woff2 new file mode 100644 index 0000000..1730a04 Binary files /dev/null and b/src/fonts/wotfard/wotfard-regular-webfont.woff2 differ diff --git a/src/fonts/wotfard/wotfard-semibold-webfont.woff2 b/src/fonts/wotfard/wotfard-semibold-webfont.woff2 new file mode 100644 index 0000000..a9bc559 Binary files /dev/null and b/src/fonts/wotfard/wotfard-semibold-webfont.woff2 differ diff --git a/src/i18n/en.json b/src/i18n/en.json new file mode 100644 index 0000000..fba134f --- /dev/null +++ b/src/i18n/en.json @@ -0,0 +1,59 @@ +{ + "accueil": "home", + "tagline": "Freelance web designer and front-end developer.", + "copyright": "(re)Made with Astro", + "contact": "contact", + "contactLien": "Send me an email (open in application).", + "contactTel": "Call or text me (open in application).", + "contenuVide": "Soon: really nice content.", + "header": { + "skipLink": "Skip to content", + "mainNav": "Main menu", + "homeLink": "Back to homepage" + }, + "sitemap": "Site map", + "prevNext": { + "contenus": "Similar content", + "precedent": "Previous", + "suivant": "Next" + }, + "article": { + "titre": "articles", + "tagline": "I blog, sometimes." + }, + "meta": { + "publication": "Published on", + "modification": "Last updated on", + "credit": "Image by" + }, + "fragments": { + "titre": "Snippets", + "tagline": "School with Nicool." + }, + "projet": { + "titre": "Projects", + "tagline": "Freelance work", + "cta": "Visit website", + "lienTitle": "Website of", + "fenetre": "(new window)" + }, + "erreur": { + "introuvable": "Sorry, page not found.", + "autre": "Oups… sorry about that.", + "lienRetour": "Back to the home page" + }, + "seo": { + "article": { + "title": "Articles", + "description": "A few articles about graphic design and front-end development." + }, + "projet": { + "title": "Projects", + "description": "Some of my work as a freelance web designer and developer." + }, + "code": { + "title": "Snippets", + "description": "Snippets of fresh, easy and accessible code." + } + } +} diff --git a/src/i18n/fr.json b/src/i18n/fr.json new file mode 100644 index 0000000..cd7dea5 --- /dev/null +++ b/src/i18n/fr.json @@ -0,0 +1,59 @@ +{ + "accueil": "accueil", + "tagline": "Designer et developpeur web freelance à Toulouse.", + "copyright": "Fait avec un 🖥️ circa 2020", + "contact": "contact", + "contactLien": "Envoyez-moi un mail (ouverture du logiciel automatique).", + "contactTel": "Contactez-moi par téléphone (ouverture du logiciel automatique).", + "contenuVide": "Bientôt ici : du contenu de qualité", + "header": { + "skipLink": "Accéder au contenu", + "mainNav": "Menu principal", + "homeLink": "Accueil du site" + }, + "sitemap": "Plan du site", + "prevNext": { + "contenus": "Contenus similaires", + "precedent": "Précédent", + "suivant": "Suivant" + }, + "article": { + "titre": "articles", + "tagline": "Je blog, un peu." + }, + "meta": { + "publication": "Publié le", + "modification": "Mis à jour le", + "credit": "Image par" + }, + "fragments": { + "titre": "Fragments", + "tagline": "Les tutos de Nico mdr." + }, + "projet": { + "titre": "Projets", + "tagline": "Mon travail en freelance", + "cta": "Consulter le site", + "lienTitle": "Site web de", + "fenetre": "(nouvelle fenêtre)" + }, + "erreur": { + "introuvable": "Page introuvable", + "autre": "Oups… désolé pour cette erreur.", + "lienRetour": "Retour à l’accueil" + }, + "seo": { + "article": { + "title": "Articles", + "description": "Quelques articles en tant que graphiste et développeur front-end à Toulouse." + }, + "projet": { + "title": "Projets", + "description": "Mon travail en tant que graphiste et développeur front-end à Toulouse." + }, + "code": { + "title": "Fragments", + "description": "Fragments de codes stylés, faciles et accessibles." + } + } +} diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index a67c1ef..397516b 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,12 +1,15 @@ --- +import { astroI18n } from "astro-i18n"; +import { I18nProvider } from "astro-i18n/components" import '../styles/style.css'; import Header from '../components/Header.astro'; +const currentLocale = astroI18n.langCode; const { pageTitle, titleColor } = Astro.props; --- - - + + @@ -16,8 +19,7 @@ const { pageTitle, titleColor } = Astro.props;
-
-

{pageTitle}

+
@@ -27,3 +29,4 @@ const { pageTitle, titleColor } = Astro.props; } + \ No newline at end of file diff --git a/src/pages/articles/i18n/en.json b/src/pages/articles/i18n/en.json new file mode 100644 index 0000000..1907417 --- /dev/null +++ b/src/pages/articles/i18n/en.json @@ -0,0 +1,7 @@ +{ + "{route}": "blog", + "pageName": "Blog", + "pageName{cool:'yes'}": "Blog cools", + "pageName{cool:'no'}": "Blog nuls", + "trad": "hello english" +} diff --git a/src/pages/articles/i18n/fr.json b/src/pages/articles/i18n/fr.json new file mode 100644 index 0000000..3dea151 --- /dev/null +++ b/src/pages/articles/i18n/fr.json @@ -0,0 +1,6 @@ +{ + "pageName": "Articles", + "pageName{cool:'yes'}": "Articles cools", + "pageName{cool:'no'}": "Articles nuls", + "trad": "slt sava" +} diff --git a/src/pages/articles/index.astro b/src/pages/articles/index.astro index f6fe67a..612aeb9 100644 --- a/src/pages/articles/index.astro +++ b/src/pages/articles/index.astro @@ -1,4 +1,6 @@ --- +import { t, l } from "astro-i18n"; + import "../../styles/style.css"; import BaseLayout from "../../layouts/BaseLayout.astro"; @@ -6,11 +8,15 @@ import ContentPost from "../../components/ContentPost.astro"; const allPosts = await Astro.glob("./*.mdx"); -const pageTitle = "Articles"; +console.log(t("index.articles.pageName", { cool: "yes" })); + +const pageTitle = t("index.articles.pageName"); const titleColor = "hotpink"; --- +

{t("index.articles.pageName", { cool: "yes" }, "fr")}

+

{t("index.articles.trad")}

    { allPosts.map((post) => ( diff --git a/src/pages/en/blog/index.astro b/src/pages/en/blog/index.astro new file mode 100644 index 0000000..a9cff9e --- /dev/null +++ b/src/pages/en/blog/index.astro @@ -0,0 +1,7 @@ +--- +import Page from "../../articles/index.astro" + +const { props } = Astro +--- + + \ No newline at end of file diff --git a/src/pages/en/index.astro b/src/pages/en/index.astro new file mode 100644 index 0000000..8671fc0 --- /dev/null +++ b/src/pages/en/index.astro @@ -0,0 +1,7 @@ +--- +import Page from "../index.astro" + +const { props } = Astro +--- + + \ No newline at end of file diff --git a/src/pages/en/tags/[tag].astro b/src/pages/en/tags/[tag].astro new file mode 100644 index 0000000..f50c609 --- /dev/null +++ b/src/pages/en/tags/[tag].astro @@ -0,0 +1,9 @@ +--- +import Page from "../../tags/[tag].astro" + +export { getStaticPaths } from "../../tags/[tag].astro" + +const { props } = Astro +--- + + \ No newline at end of file diff --git a/src/pages/en/tags/index.astro b/src/pages/en/tags/index.astro new file mode 100644 index 0000000..1ff13a8 --- /dev/null +++ b/src/pages/en/tags/index.astro @@ -0,0 +1,7 @@ +--- +import Page from "../../tags/index.astro" + +const { props } = Astro +--- + + \ No newline at end of file diff --git a/src/pages/i18n/en.json b/src/pages/i18n/en.json new file mode 100644 index 0000000..880c588 --- /dev/null +++ b/src/pages/i18n/en.json @@ -0,0 +1,9 @@ +{ + "title": "Crafting sober and accessible websites", + "quoi": "I design websites and web applications following accessibility best practices.", + "comment": "More precisely, I create web and mobile interfaces. From UX to UI, from development to deployment. I put digital accessibility standards, for which I have obtained the Opquast certification, forwards. I also keep eco-design in mind when working.", + "opensource": "I try to contribute to open source projects that I enjoy.", + "articles": "Oh and I write articles! Articles about design and the web in general.", + "projetsRecents": "Latest projects", + "articlesRecents": "Latest articles" +} diff --git a/src/pages/i18n/fr.json b/src/pages/i18n/fr.json new file mode 100644 index 0000000..6d849ff --- /dev/null +++ b/src/pages/i18n/fr.json @@ -0,0 +1,9 @@ +{ + "title": "Création de sites web sobres et accessibles", + "quoi": "Je crée des sites et des applications web en suivant les bonnes pratiques d’accessibilités.", + "comment": "Plus précisément, je crée des interfaces web et mobiles. De l’ergonomie jusqu’au design final, de l’intégration jusqu’à la mise en ligne. Je mets en avant les standards d’accessibilité numérique, pour lesquels j’ai obtenu la certification Opquast. Je m’inscris également dans une démarche d’éco-conception des services que je propose.", + "opensource": "J’essaie de contribuer à des projets open source qui me tiennent à cœur.", + "articles": "Ah et j’écris des articles aussi ! Des articles sur le graphisme et l’informatique.", + "projetsRecents": "Derniers projets", + "articlesRecents": "Derniers articles" +} diff --git a/src/pages/index.astro b/src/pages/index.astro index 02614ff..aff8754 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,9 +1,10 @@ --- -import BaseLayout from '../layouts/BaseLayout.astro'; +import { t, l } from "astro-i18n"; +import BaseLayout from "../layouts/BaseLayout.astro"; -const pageTitle = "Accueil" +const pageTitle = t("accueil"); --- -

    devvvvv

    +

    diff --git a/src/styles/blocks/section.css b/src/styles/blocks/section.css new file mode 100644 index 0000000..e6fffeb --- /dev/null +++ b/src/styles/blocks/section.css @@ -0,0 +1,18 @@ +.section > .curve { + transform: translateY(-1px); +} + +.section > .curve:first-child { + transform: rotate(180deg) translateY(-1px); +} + +.section__inner { + background: var(--spot-bg-color, transparent); + color: var(--spot-text-color, var(--color-dark)); +} + +.section blockquote { + font-weight: 700; + line-height: 1; + font-size: var(--size-4); +} diff --git a/src/styles/compositions/grid.css b/src/styles/compositions/grid.css new file mode 100644 index 0000000..3811fe5 --- /dev/null +++ b/src/styles/compositions/grid.css @@ -0,0 +1,32 @@ +/* +CUSTOM PROPERTIES AND CONFIGURATION +--gutter (var(--space-s-m)): This defines the space +between each item. + +--grid-min-item-size (14rem): How large each item should be +ideally, as a minimum. + +--grid-placement (auto-fill): Set either auto-fit or auto-fill +to change how empty grid tracks are handled */ +.grid { + display: grid; + grid-template-columns: repeat( + var(--grid-placement, auto-fill), + minmax(var(--grid-min-item-size, 16rem), 1fr) + ); + gap: var(--gutter, var(--space-m-l)); +} + +.grid[data-rows='masonry'] { + grid-template-rows: masonry; + align-items: start; +} + +.grid[data-layout='50-50'] { + --grid-placement: auto-fit; + --grid-min-item-size: clamp(16rem, 50vw, 26rem); +} +.grid[data-layout='33-33-33'] { + --grid-placement: auto-fit; + --grid-min-item-size: clamp(18rem, 27vw, 26rem); +} diff --git a/src/styles/compositions/sidebar.css b/src/styles/compositions/sidebar.css new file mode 100644 index 0000000..aaad268 --- /dev/null +++ b/src/styles/compositions/sidebar.css @@ -0,0 +1,54 @@ +/* +CUSTOM PROPERTIES AND CONFIGURATION +--gutter (var(--space-size-1)): This defines the space +between the sidebar and main content. + +--sidebar-target-width (20rem): How large the sidebar should be + +--sidebar-content-min-width(50%): The minimum size of the main content area + +EXCEPTIONS +.sidebar[data-direction='rtl']: flips the sidebar to be on the right +*/ +.sidebar { + display: flex; + flex-wrap: wrap; + gap: var(--gutter, var(--space-xs-s)); +} + +.sidebar > :first-child { + flex-basis: var(--sidebar-target-width, 20rem); + flex-grow: 1; +} + +.sidebar > :last-child { + flex-basis: 0; + flex-grow: 999; + min-width: var(--sidebar-content-min-width, 50%); +} + +/* +A flipped version where the sidebar is on the right +*/ +.sidebar[data-direction='rtl'] { + flex-direction: row-reverse; +} + +/* REVERSE sidebar on right*/ + +.sidebar--reverse { + display: flex; + flex-wrap: wrap; + gap: var(--gutter, var(--space-xs-s)); +} + +.sidebar--reverse > :last-child { + flex-basis: var(--sidebar-target-width, 20rem); + flex-grow: 1; +} + +.sidebar--reverse > :first-child { + flex-basis: 0; + flex-grow: 999; + min-width: var(--sidebar-content-min-width, 50%); +} diff --git a/src/styles/global/fonts.css b/src/styles/global/fonts.css new file mode 100644 index 0000000..8741888 --- /dev/null +++ b/src/styles/global/fonts.css @@ -0,0 +1,42 @@ +@font-face { + font-family: "wotfard"; + src: url("../../fonts/wotfard/wotfard-medium-webfont.woff2") format("woff2"); + font-weight: 500; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "wotfard"; + src: url("../../fonts/wotfard/wotfard-semibold-webfont.woff2") format("woff2"); + font-weight: bold; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "wotfard"; + src: url("../../fonts/wotfard/wotfard-regular-webfont.woff2") format("woff2"); + font-weight: normal; + font-style: normal; + font-display: swap; +} +@font-face { + font-family: "recoleta"; + src: url("../../fonts/recoleta/Recoleta-SemiBold.woff2") format("woff2"); + font-weight: 600; + font-style: normal; + font-display: swap; +} + +/* +* reduces Cumulative Layout Shift +* https://www.24joursdeweb.fr/2021/performance-web-lintegrateur-ce-heros/ +*/ +@font-face { + font-family: "ArialReplace"; + src: local("Arial"); + font-weight: 400; + font-style: normal; + font-display: swap; + size-adjust: 96%; + letter-spacing: 1px; +} diff --git a/src/styles/global/global-styles.css b/src/styles/global/global-styles.css new file mode 100644 index 0000000..9e9dadc --- /dev/null +++ b/src/styles/global/global-styles.css @@ -0,0 +1,148 @@ +/* BASE */ +::placeholder { + color: var(--color-dark); + opacity: 0.8; +} +::selection { + color: var(--lightBlue); + background-color: var(--darkBlue); +} + +body { + font-family: var(--font-primary); + font-size: var(--size-0); + line-height: 1.4; + color: var(--color-dark); +} +.navIsOpenBody { + overflow: hidden; +} + +main { + min-block-size: 100vh; + background-color: var(--color-light-white); +} +:where(h1, h2, h3) { + font-family: var(--font-secondary); +} +h1 { + max-width: 20ch; + font-size: var(--size-7); + font-weight: bold; + color: var(--color-darkBlue); +} + +h2, +.h2 { + font-size: var(--size-4); + font-weight: bold; +} + +h3, +.h3 { + max-width: initial; + font-size: var(--size-2); + font-weight: bold; + letter-spacing: 0.05rem; +} + +h4, +.h4 { + font-size: var(--size-2); + font-weight: bold; + color: var(--color-dark); +} + +h5, +.h5 { + font-size: var(--size-1); + color: var(--color-darkBlue); +} + +a, +a:visited { + position: relative; + color: currentcolor; +} +a:hover { + text-decoration: none; +} + +hr { + margin-block: var(--space-m-l); + block-size: 4px; + background-color: var(--color-dark); +} +hr.small { + margin-block: var(--space-xs); + block-size: 2px; +} + +ul:not([role="list"]), +ol:not([role="list"]) { + padding-inline-start: 1rem; +} + +ul:not([role="list"]) > li + li, +ol:not([role="list"]) > li + li { + margin-block-start: var(--space-xs); +} + +.sr-only { + clip: rect(0 0 0 0); + clip-path: inset(50%); + height: 1px; + overflow: hidden; + position: absolute; + white-space: nowrap; + width: 1px; +} + +.clean-button { + appearance: none; + -webkit-appearance: none; + cursor: pointer; + border: none; + background: none; +} +.btn { + padding: var(--space-xs) var(--space-s); + margin-block: var(--space-s); + display: inline-block; + font-size: var(--size--1); + font-weight: bold; + text-decoration: none; + border: 2px solid var(--color-red); + border-radius: 14px; + color: var(--color-red); + background-color: transparent; + transition-property: color, background-color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; +} +.btn:hover { + color: var(--color-light); + background-color: var(--color-red); +} + +.reset-button { + padding: var(--space-3xs) var(--space-2xs); + /* margin-inline-start: auto; */ + font-size: var(--size--1); + color: var(--color-light); + border: 1px solid transparent; + background-color: var(--color-dark); + border-radius: var(--radius); +} +.reset-button:not([disabled]):hover { + color: var(--color-dark); + border: 1px solid var(--color-dark); + background-color: var(--color-white); +} + +button[disabled] { + cursor: not-allowed; + color: var(--color-grey-dark); + border-color: var(--color-grey); + background-color: var(--color-white); +} diff --git a/src/styles/global/reset.css b/src/styles/global/reset.css new file mode 100644 index 0000000..9f09313 --- /dev/null +++ b/src/styles/global/reset.css @@ -0,0 +1,166 @@ +/* RESET */ + +:root { + --font-tnum: "tnum" on; +} + +* { + /* Remove default margin on everything */ + margin: 0; + /* Remove default padding on everything */ + padding: 0; + /* Calc `em` based line height, bigger line height for smaller font size and smaller line height for bigger font size: https://kittygiraudel.com/2020/05/18/using-calc-to-figure-out-optimal-line-height/ */ + line-height: calc(0.25rem + 1em + 0.25rem); +} + +/* Use a more-intuitive box-sizing model on everything */ +*, +::before, +::after { + box-sizing: border-box; +} + +/* Remove border and set sensible defaults for backgrounds, on all elements except fieldset progress and meter */ +*:where(:not(fieldset, progress, meter)) { + border-width: 0; + border-style: solid; + background-origin: border-box; + background-repeat: no-repeat; +} +@supports (font-variant-numeric: tabular-nums) { + html { + --font-tnum: "____"; + font-variant-numeric: tabular-nums; + } +} +html { + /* Allow percentage-based heights in the application */ + block-size: 100%; + /* Making sure text size is only controlled by font-size */ + -webkit-text-size-adjust: none; + /* Improve text rendering */ + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; + font-feature-settings: var(--font-tnum); +} + +/* Smooth scrolling for users that don't prefer reduced motion */ +@media (prefers-reduced-motion: no-preference) { + html:focus-within { + scroll-behavior: smooth; + } +} + +body { + overflow-x: hidden; + font-weight: normal; + /* Allow percentage-based heights in the application */ + min-block-size: 100%; + /* https://www.sarasoueidan.com/blog/safari-fluid-typography-bug-fix/ */ + -webkit-marquee-increment: 0vw; +} + +/* Improve media defaults */ +:where(img, svg, video, canvas, audio, iframe, embed, object) { + display: block; +} +:where(img, svg, video) { + block-size: auto; + max-inline-size: 100%; +} + +:where(details) { + cursor: pointer; +} + +/* Remove stroke and set fill colour to the inherited font colour */ +:where(svg) { + stroke: none; + fill: currentColor; +} + +/* Set a size for SVG's without a width attribute */ +:where(svg):where(:not([width])) { + inline-size: 5rem; +} + +/* Remove built-in form typography styles */ +:where(input, button, textarea, select), +:where(input[type="file"])::-webkit-file-upload-button { + color: inherit; + font: inherit; + font-size: inherit; + letter-spacing: inherit; +} + +/* Change textarea resize to vertical only and block only if the browser supports that */ +:where(textarea) { + resize: vertical; +} +@supports (resize: block) { + :where(textarea) { + resize: block; + } +} + +/* Avoid text overflows */ +:where(h1, h2, h3) { + line-height: 1.1; +} +:where(p, h1, h2, h3, h4, h5, h6) { + overflow-wrap: break-word; +} + +/* Remove list styles on ul, ol elements with a list role, which suggests default styling will be removed */ +:where(ul, ol)[role="list"] { + list-style: none; +} + +/* More readable underline style for anchor tags without a class. This could be set on anchor tags globally, but it can cause conflicts. */ +a:not([class]) { + text-decoration-skip-ink: auto; +} + +/* Make it clear that interactive elements are interactive */ +:where(a[href], area, button, input, label[for], select, summary, textarea, [tabindex]:not([tabindex*="-"])) { + cursor: pointer; + touch-action: manipulation; +} +:where(input[type="file"]) { + cursor: auto; +} +:where(input[type="file"])::-webkit-file-upload-button, +:where(input[type="file"])::file-selector-button { + cursor: pointer; +} + +/* 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; + } +} +:where(:not(:active)):focus-visible { + outline-offset: 5px; +} + +/* Make sure users can't select button text */ +:where(button, button[type], input[type="button"], input[type="submit"], input[type="reset"]), +:where(input[type="file"])::-webkit-file-upload-button, +:where(input[type="file"])::file-selector-button { + -webkit-tap-highlight-color: transparent; + -webkit-touch-callout: none; + user-select: none; + text-align: center; +} + +/* Disabled cursor for disabled buttons */ +:where(button, button[type], input[type="button"], input[type="submit"], input[type="reset"])[disabled] { + cursor: not-allowed; +} + +/* END RESET */ diff --git a/src/styles/global/variables.css b/src/styles/global/variables.css new file mode 100644 index 0000000..f3758a4 --- /dev/null +++ b/src/styles/global/variables.css @@ -0,0 +1,89 @@ +/* VARIABLES */ + +:root { + /* font sizes */ + --size--1: clamp(0.94rem, calc(0.91rem + 0.14vw), 1rem); + --size-0: clamp(1.13rem, calc(1.07rem + 0.28vw), 1.25rem); + --size-1: clamp(1.35rem, calc(1.26rem + 0.47vw), 1.56rem); + --size-2: clamp(1.62rem, calc(1.47rem + 0.74vw), 1.95rem); + --size-3: clamp(1.94rem, calc(1.72rem + 1.11vw), 2.44rem); + --size-4: clamp(2.33rem, calc(2.01rem + 1.6vw), 3.05rem); + --size-5: clamp(2.8rem, calc(2.35rem + 2.26vw), 3.82rem); + --size-6: clamp(3.36rem, calc(2.73rem + 3.13vw), 4.77rem); + --size-7: clamp(4.03rem, calc(3.17rem + 4.29vw), 5.96rem); + --size-8: clamp(4.84rem, calc(3.68rem + 5.81vw), 7.45rem); + + /* spaces */ + --space-3xs: clamp(0.31rem, calc(0.31rem + 0vw), 0.31rem); + --space-2xs: clamp(0.56rem, calc(0.53rem + 0.14vw), 0.63rem); + --space-xs: clamp(0.88rem, calc(0.85rem + 0.14vw), 0.94rem); + --space-s: clamp(1.13rem, calc(1.07rem + 0.28vw), 1.25rem); + --space-m: clamp(1.69rem, calc(1.6rem + 0.42vw), 1.88rem); + --space-l: clamp(2.25rem, calc(2.14rem + 0.56vw), 2.5rem); + --space-xl: clamp(3.38rem, calc(3.21rem + 0.83vw), 3.75rem); + --space-2xl: clamp(4.5rem, calc(4.28rem + 1.11vw), 5rem); + --space-3xl: clamp(6.75rem, calc(6.42rem + 1.67vw), 7.5rem); + + /* One-up pairs */ + --space-3xs-2xs: clamp(0.31rem, calc(0.17rem + 0.69vw), 0.63rem); + --space-2xs-xs: clamp(0.56rem, calc(0.4rem + 0.83vw), 0.94rem); + --space-xs-s: clamp(0.88rem, calc(0.71rem + 0.83vw), 1.25rem); + --space-s-m: clamp(1.13rem, calc(0.79rem + 1.67vw), 1.88rem); + --space-m-l: clamp(1.69rem, calc(1.33rem + 1.81vw), 2.5rem); + --space-l-xl: clamp(2.25rem, calc(1.58rem + 3.33vw), 3.75rem); + --space-xl-2xl: clamp(3.38rem, calc(2.65rem + 3.61vw), 5rem); + --space-2xl-3xl: clamp(4.5rem, calc(3.17rem + 6.67vw), 7.5rem); + + /* multi steps */ + --space-3xs-s: clamp(0.31rem, calc(-0.1rem + 2.08vw), 1.25rem); + --space-2xs-s: clamp(0.56rem, calc(0.26rem + 1.53vw), 1.25rem); + --space-2xs-m: clamp(0.56rem, calc(-0.02rem + 2.92vw), 1.88rem); + --space-xs-m: clamp(0.88rem, calc(0.43rem + 2.22vw), 1.88rem); + --space-xs-l: clamp(0.88rem, calc(0.15rem + 3.61vw), 2.5rem); + --space-s-l: clamp(1.13rem, calc(0.51rem + 3.06vw), 2.5rem); + --space-s-xl: clamp(1.13rem, calc(-0.04rem + 5.83vw), 3.75rem); + --space-l-2xl: clamp(2.25rem, calc(1.03rem + 6.11vw), 5rem); + + /* fonts */ + --font-primary: "wotfard", "ArialReplace", sans-serif; + --font-secondary: "recoleta", Palatino, serif; + --font-code: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace; + --font-tnum: "tnum" on; + + /* colors */ + --color-dark: hsl(239, 57%, 15%); + --color-grey: hsl(211, 12%, 35%); + --color-greyLight: hsl(0, 0%, 94%); + --color-blue: hsl(253, 98%, 41%); + --color-darkBlue: hsl(218, 60%, 21%); + --color-lightBlue: hsl(194, 54%, 89%); + --color-blendBlue: hsl(253, 100%, 32%); + --color-softBlue: hsl(210, 73%, 94%); + --color-violet: hsl(248, 73%, 52%); + --color-brique: hsl(358, 54%, 54%); + --color-white: hsl(0, 0%, 100%); + --color-lightWhite: hsl(240, 50%, 98%); + --color-black: hsl(0, 0%, 0%); + + /* shadows */ + --shadow-color: 0deg 0% 80%; + --shadow-elevation-medium: 0px 0.7px 0.7px hsl(var(--shadow-color) / 0.28), + 0px 1.5px 1.6px -0.7px hsl(var(--shadow-color) / 0.26), + 0px 2.9px 3px -1.5px hsl(var(--shadow-color) / 0.24), + 0px 6px 6.3px -2.2px hsl(var(--shadow-color) / 0.22), + 0px 11.8px 12.4px -3px hsl(var(--shadow-color) / 0.2); + --shadow-elevation-high: 0px 0.5px 0.5px hsl(var(--shadow-color) / 0.18), + 0px 1.4px 1.5px -0.3px hsl(var(--shadow-color) / 0.18), + 0px 2.3px 2.4px -0.7px hsl(var(--shadow-color) / 0.17), + 0px 3.4px 3.6px -1px hsl(var(--shadow-color) / 0.16), + 0px 5.1px 5.4px -1.3px hsl(var(--shadow-color) / 0.16), + 0px 7.5px 7.9px -1.7px hsl(var(--shadow-color) / 0.15), + 0px 10.8px 11.3px -2px hsl(var(--shadow-color) / 0.15), + -0.1px 15.4px 16.2px -2.3px hsl(var(--shadow-color) / 0.14), + -0.1px 21.3px 22.4px -2.7px hsl(var(--shadow-color) / 0.13), + -0.1px 28.9px 30.3px -3px hsl(var(--shadow-color) / 0.13); + + /* radius */ + --radius: 20px; + --radius-small: 10px; +} diff --git a/src/styles/style.css b/src/styles/style.css index 20335b3..89aa667 100644 --- a/src/styles/style.css +++ b/src/styles/style.css @@ -1,11 +1,12 @@ -@import "open-props/style"; -@import "open-props/normalize"; +/* @import "open-props/style"; */ +/* @import "open-props/normalize"; */ -/* *, *::before, *::after { - box-sizing: border-box; -} +@import "./global/reset.css"; +@import "./global/fonts.css"; -* { - margin: 0; - padding: 0; -} */ \ No newline at end of file +@import "./global/variables.css"; +@import "./global/global-styles.css"; + +@import-glob './blocks/*.css'; +@import-glob './compositions/*.css'; +@import-glob './utilities/*.css'; diff --git a/src/styles/utilities/flow.css b/src/styles/utilities/flow.css new file mode 100644 index 0000000..a7fbe6f --- /dev/null +++ b/src/styles/utilities/flow.css @@ -0,0 +1,7 @@ +.flow > * + * { + margin-block-start: var(--flow-space, var(--space-m-l)); +} + +.flow > :where(h1, h2, h3) + * { + margin-block-start: var(--flow-space-title, var(--space-s-m)); +} diff --git a/src/styles/utilities/region.css b/src/styles/utilities/region.css new file mode 100644 index 0000000..bfba7f3 --- /dev/null +++ b/src/styles/utilities/region.css @@ -0,0 +1,4 @@ +.region { + padding-block-start: var(--region-space, var(--space-l-2xl)); + padding-block-end: var(--region-space, var(--space-l-2xl)); +} diff --git a/src/styles/utilities/waves.css b/src/styles/utilities/waves.css new file mode 100644 index 0000000..40bf28b --- /dev/null +++ b/src/styles/utilities/waves.css @@ -0,0 +1,71 @@ +.waves { + background: transparent; + height: 4px; + position: relative; +} +.waves::before { + content: ''; + position: absolute; + left: 0; + bottom: 0; + right: 0; + background-repeat: repeat; + height: 10px; + background-size: 20px 20px; + background-image: radial-gradient( + circle at 10px -5px, + transparent 12px, + var(--waves-color, var(--color-white)) 13px + ); +} +.waves::after { + content: ''; + position: absolute; + left: 0; + bottom: 0; + right: 0; + background-repeat: repeat; + height: 15px; + background-size: 40px 20px; + background-image: radial-gradient( + circle at 10px 15px, + var(--waves-color, var(--color-white)) 12px, + transparent 13px + ); +} + +/* LARGE */ +.waves-container { + block-size: 30px; + position: relative; +} +.waves--large { + position: absolute; + height: 30px; + width: 100%; + background: var(--waves-color, var(--color-light)); + bottom: 0; +} + +.waves--large::before, +.waves--large::after { + content: ''; + display: block; + position: absolute; + border-radius: 100% 50%; +} + +.waves--large::before { + width: 55%; + height: 100%; + background-color: var(--waves-color, var(--color-light)); + left: -1.5%; + top: 40%; +} +.waves--large::after { + width: 55%; + height: 109%; + background-color: var(--waves-bg-color, var(--color-white)); + right: -1.5%; + top: 60%; +} diff --git a/src/styles/utilities/wrapper.css b/src/styles/utilities/wrapper.css new file mode 100644 index 0000000..ff515ce --- /dev/null +++ b/src/styles/utilities/wrapper.css @@ -0,0 +1,39 @@ +.wrapper { + /* CLASSIC WRAPPER */ + /* max-width: var(--wrapper-max-width, 80rem); + margin-inline-start: auto; + margin-inline-end: auto; + --_content-padding: var(--content-padding, var(--space-s)); + padding-inline-start: var(--_content-padding); + padding-inline-end: var(--_content-padding); + position: relative; */ + --content-width: 80rem; + --grid-wrapper: [full-start] 1fr [wrapper-start] + minmax(0, var(--content-width)) [wrapper-end] 1fr [full-end]; + + /* GRID WRAPPER */ + display: grid; + grid-template-columns: var(--grid-wrapper); + --_content-padding: var(--content-padding, var(--space-s)); + column-gap: var(--_content-padding); +} +/* set content inside wrapper column */ +.wrapper > * { + grid-column: wrapper; +} + +/* set full width content to full grid */ +.wrapper.full-width { + /* calculate inline padding based on available space minus content space to align full-width content with wrapper content */ + padding-inline: max( + calc((100vw - var(--content-width)) / 2), + var(--_content-padding) + ); + grid-column: full; +} +/* set full width color to full grid */ +.wrapper.full-width-color { + /* https://codepen.io/t_afif/pen/oNEaqQX */ + border-image: conic-gradient(var(--color-full-width, var(--color-light)) 0 0) + fill 0 //0 100vw;; +}