feat: implement common components

feat: implement sidebar

feat: implement footer

feat: implement breadcrumb

chore: add typography styles

chore: add heading anchor link

chore: add postcss-nested
This commit is contained in:
Xin 2023-07-27 00:05:47 +01:00
parent e0bfaf0467
commit c8eb404fe6
10 changed files with 190 additions and 11 deletions

View File

@ -2,6 +2,8 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@import "typography.css";
html { html {
@apply text-base antialiased; @apply text-base antialiased;

85
assets/css/typography.css Normal file
View File

@ -0,0 +1,85 @@
.content {
h1 {
@apply mt-2 text-4xl font-bold tracking-tight text-slate-900 dark:text-slate-100;
}
h2 {
@apply font-semibold tracking-tight text-slate-900 dark:text-slate-100 mt-10 border-b pb-1 text-3xl border-neutral-200/70 contrast-more:border-neutral-400 dark:border-primary-100/10 contrast-more:dark:border-neutral-400;
}
h3 {
@apply font-semibold tracking-tight text-slate-900 dark:text-slate-100 mt-8 text-2xl;
}
h4 {
@apply font-semibold tracking-tight text-slate-900 dark:text-slate-100 mt-8 text-xl;
}
h5 {
@apply font-semibold tracking-tight text-slate-900 dark:text-slate-100 mt-8 text-lg;
}
h6 {
@apply font-semibold tracking-tight text-slate-900 dark:text-slate-100 mt-8 text-base;
}
p {
@apply mt-6 leading-7 first:mt-0;
}
a {
@apply text-primary-600 underline decoration-from-font [text-underline-position:from-font];
}
blockquote {
@apply mt-6 border-gray-300 italic text-gray-700 dark:border-gray-700 dark:text-gray-400 first:mt-0 ltr:border-l-2 ltr:pl-6 rtl:border-r-2 rtl:pr-6;
}
pre {
@apply bg-primary-700/5 mb-4 overflow-x-auto rounded-xl font-medium subpixel-antialiased dark:bg-primary-300/10 text-[.9em] contrast-more:border contrast-more:border-primary-900/20 contrast-more:contrast-150 contrast-more:dark:border-primary-100/40 py-4;
}
code {
@apply border-black border-opacity-[0.04] bg-opacity-[0.03] bg-black break-words rounded-md border py-0.5 px-[.25em] text-[.9em] dark:border-white/10 dark:bg-white/10;
}
table {
@apply block overflow-x-auto mt-6 p-0 first:mt-0;
tr {
@apply m-0 border-t border-gray-300 p-0 dark:border-gray-600 even:bg-gray-100 even:dark:bg-gray-600/20;
}
th {
@apply m-0 border border-gray-300 px-4 py-2 font-semibold dark:border-gray-600;
}
td {
@apply m-0 border border-gray-300 px-4 py-2 dark:border-gray-600;
}
}
ol {
@apply mt-6 list-decimal first:mt-0 ltr:ml-6 rtl:mr-6;
li {
@apply my-2;
}
}
ul {
@apply mt-6 list-disc first:mt-0 ltr:ml-6 rtl:mr-6;
li {
@apply my-2;
}
}
}
.subheading-anchor {
@apply opacity-0 transition-opacity ltr:ml-1 rtl:mr-1;
span:target + &,
:hover > &,
&:focus {
@apply opacity-100;
}
span + &,
:hover > & {
@apply !no-underline;
}
&:after {
@apply content-['#'] px-1;
@apply text-gray-300 dark:text-neutral-700;
span:target + & {
@apply text-gray-400;
@apply dark:text-neutral-500;
}
}
}

View File

@ -35,3 +35,8 @@ theme-dark: >
<svg fill="none" viewBox="2 2 20 20" stroke="currentColor"> <svg fill="none" viewBox="2 2 20 20" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" fill="currentColor" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path> <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" fill="currentColor" d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"></path>
</svg> </svg>
breadcrumb-delimiter: >
<svg fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
</svg>

View File

@ -0,0 +1,7 @@
<h{{ .Level }}>
{{ .Text | safeHTML }}
{{ if gt .Level 1 }}
<span class="absolute -mt-20" id="{{ .Anchor | safeURL }}"></span>
<a href="#{{ .Anchor | safeURL }}" class="subheading-anchor" aria-label="Permalink for this section"></a>
{{ end }}
</h{{ .Level }}>

View File

@ -0,0 +1,13 @@
<div class="mt-1.5 flex items-center gap-1 overflow-hidden text-sm text-gray-500 dark:text-gray-400 contrast-more:text-current">
{{ range .Ancestors.Reverse }}
{{ if not .IsHome }}
<div class="whitespace-nowrap transition-colors min-w-[24px] overflow-hidden text-ellipsis">
<a href="{{ .Permalink }}">{{ .LinkTitle }}</a>
</div>
{{ partial "utils/icon.html" (dict "context" . "name" "breadcrumb-delimiter" "attributes" "class=\"w-3.5 shrink-0\"") }}
{{ end }}
{{ end }}
<div class="whitespace-nowrap transition-colors font-medium text-gray-700 contrast-more:font-bold contrast-more:text-current dark:text-gray-100 contrast-more:dark:text-current">
{{ .LinkTitle }}
</div>
</div>

View File

@ -0,0 +1,14 @@
<footer class="bg-gray-100 pb-[env(safe-area-inset-bottom)] dark:bg-neutral-900 print:bg-transparent">
<hr class="dark:border-neutral-800" />
<div class="mx-auto flex max-w-[90rem] justify-center py-12 pl-[max(env(safe-area-inset-left),1.5rem)] pr-[max(env(safe-area-inset-right),1.5rem)] text-gray-600 dark:text-gray-400 md:justify-start">
<div class="flex w-full flex-col items-center sm:items-start">
<div>
<a class="flex items-center gap-1 text-current" target="_blank" rel="noopener noreferrer" title="Hugo homepage" href="https://gohugo.io/">
<span>Powered by</span>
{{ partial "utils/icon.html" (dict "context" . "name" "hugo-full" "attributes" "height=20") }}
</a>
</div>
<p class="mt-6 text-xs">© 2023 Hextra Project.</p>
</div>
</div>
</footer>

View File

@ -0,0 +1,49 @@
<aside class="flex flex-col print:hidden md:top-16 md:shrink-0 md:w-64 md:sticky md:self-start max-md:[transform:translate3d(0,-100%,0)]">
<div class="overflow-y-auto overflow-x-hidden p-4 grow md:h-[calc(100vh-4rem)]">
<ul class="flex flex-col gap-1 max-md:hidden">
{{ $s := .FirstSection }}
{{ $topLevelItems := union $s.RegularPages $s.Sections }}
{{ $currentUrl := .RelPermalink }}
{{ range $topLevelItems.ByWeight }}
{{ $isCurrent := eq $currentUrl .RelPermalink }}
<li class="open">
{{ if $isCurrent }}
<a
class="flex cursor-pointer items-center justify-between gap-2 rounded bg-primary-100 px-2 py-1.5 text-sm font-semibold text-primary-800 transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word] contrast-more:border contrast-more:border-primary-500 dark:bg-primary-400/10 dark:text-primary-600 contrast-more:dark:border-primary-500"
href="{{ .RelPermalink }}"
>{{ .LinkTitle }}</a
>
{{ else }}
<a
class="flex cursor-pointer items-center justify-between gap-2 rounded px-2 py-1.5 text-sm text-gray-500 transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word] hover:bg-gray-100 hover:text-gray-900 contrast-more:border contrast-more:border-transparent contrast-more:text-gray-900 contrast-more:hover:border-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:dark:text-gray-50 contrast-more:dark:hover:border-gray-50"
href="{{ .RelPermalink }}"
>{{ .LinkTitle }}
</a>
{{ end }}
</li>
<div class="pt-1 ltr:pr-0">
<ul class='relative flex flex-col gap-1 before:absolute before:inset-y-1 before:w-px before:bg-gray-200 before:content-[""] ltr:ml-3 ltr:pl-3 ltr:before:left-0 rtl:mr-3 rtl:pr-3 rtl:before:right-0 dark:before:bg-neutral-800'>
{{ $secondLevelItems := union .RegularPages .Sections }}
{{ range $secondLevelItems.ByWeight }}
{{ $isCurrent := eq $currentUrl .RelPermalink }}
<li class="flex flex-col gap-1">
<a
class="flex cursor-pointer rounded px-2 py-1.5 text-sm transition-colors [-webkit-tap-highlight-color:transparent] [-webkit-touch-callout:none] [word-break:break-word]
{{ if eq $currentUrl .RelPermalink }}
bg-primary-100 font-semibold text-primary-800 contrast-more:border contrast-more:border-primary-500 dark:bg-primary-400/10 dark:text-primary-600 contrast-more:dark:border-primary-500
{{ else }}
text-gray-500 hover:bg-gray-100 hover:text-gray-900 contrast-more:border contrast-more:border-transparent contrast-more:text-gray-900 contrast-more:hover:border-gray-900 dark:text-neutral-400 dark:hover:bg-primary-100/5 dark:hover:text-gray-50 contrast-more:dark:text-gray-50 contrast-more:dark:hover:border-gray-50
{{ end }}"
href="{{ .RelPermalink }}"
>
{{ .LinkTitle }}
</a>
</li>
{{ end }}
</ul>
</div>
{{ end }}
</ul>
</div>
</aside>

20
package-lock.json generated
View File

@ -9,6 +9,8 @@
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"postcss": "^8.4.23", "postcss": "^8.4.23",
"postcss-cli": "^10.1.0", "postcss-cli": "^10.1.0",
"postcss-import": "^15.1.0",
"postcss-nested": "^6.0.1",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-go-template": "^0.0.13", "prettier-plugin-go-template": "^0.0.13",
"tailwindcss": "^3.3.2" "tailwindcss": "^3.3.2"
@ -430,9 +432,9 @@
"dev": true "dev": true
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.465", "version": "1.4.474",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.465.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.474.tgz",
"integrity": "sha512-XQcuHvEJRMU97UJ75e170mgcITZoz0lIyiaVjk6R+NMTJ8KBIvUHYd1779swgOppUlzxR+JsLpq59PumaXS1jQ==", "integrity": "sha512-GsFT9gtxkFMkpHf13UeN/RFbWdLQVs4DMxA1aQv4xdUAT2qyXEoAQ0hodl2sUvWmztOlicM1UYnNPcoMdzQB5A==",
"dev": true "dev": true
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
@ -451,9 +453,9 @@
} }
}, },
"node_modules/fast-glob": { "node_modules/fast-glob": {
"version": "3.3.0", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz",
"integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.stat": "^2.0.2",
@ -959,9 +961,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.26", "version": "8.4.27",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.26.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz",
"integrity": "sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==", "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {

View File

@ -4,6 +4,8 @@
"autoprefixer": "^10.4.14", "autoprefixer": "^10.4.14",
"postcss": "^8.4.23", "postcss": "^8.4.23",
"postcss-cli": "^10.1.0", "postcss-cli": "^10.1.0",
"postcss-import": "^15.1.0",
"postcss-nested": "^6.0.1",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"prettier-plugin-go-template": "^0.0.13", "prettier-plugin-go-template": "^0.0.13",
"tailwindcss": "^3.3.2" "tailwindcss": "^3.3.2"

View File

@ -1,8 +1,8 @@
let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js'; let tailwindConfig = process.env.HUGO_FILE_TAILWIND_CONFIG_JS || './tailwind.config.js';
const tailwind = require('tailwindcss')(tailwindConfig); const tailwind = require('tailwindcss')(tailwindConfig);
const autoprefixer = require('autoprefixer'); const autoprefixer = require('autoprefixer');
const nested = require('postcss-nested')
module.exports = { module.exports = {
// eslint-disable-next-line no-process-env plugins: [tailwind, nested, ...(process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : [])], // add nesting to the plugins array
plugins: [tailwind, ...(process.env.HUGO_ENVIRONMENT === 'production' ? [autoprefixer] : [])],
}; };