chore: cleanup, shadcn

This commit is contained in:
enscribe 2024-09-10 14:24:09 -07:00
parent 230dca64ca
commit ea68d4f02f
No known key found for this signature in database
GPG key ID: 9BBD5C4114E25322
38 changed files with 1073 additions and 1378 deletions

668
package-lock.json generated
View file

@ -17,7 +17,9 @@
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"@fontsource/geist-mono": "^5.0.3", "@fontsource/geist-mono": "^5.0.3",
"@fontsource/geist-sans": "^5.0.3", "@fontsource/geist-sans": "^5.0.3",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-slot": "^1.1.0",
"@types/react": "^18.3.5", "@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"astro": "^4.11.3", "astro": "^4.11.3",
@ -1130,6 +1132,40 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@floating-ui/core": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz",
"integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==",
"dependencies": {
"@floating-ui/utils": "^0.2.7"
}
},
"node_modules/@floating-ui/dom": {
"version": "1.6.10",
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz",
"integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==",
"dependencies": {
"@floating-ui/core": "^1.6.0",
"@floating-ui/utils": "^0.2.7"
}
},
"node_modules/@floating-ui/react-dom": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz",
"integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==",
"dependencies": {
"@floating-ui/dom": "^1.0.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@floating-ui/utils": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz",
"integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA=="
},
"node_modules/@fontsource/geist-mono": { "node_modules/@fontsource/geist-mono": {
"version": "5.0.3", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/@fontsource/geist-mono/-/geist-mono-5.0.3.tgz", "resolved": "https://registry.npmjs.org/@fontsource/geist-mono/-/geist-mono-5.0.3.tgz",
@ -1760,6 +1796,192 @@
"node": ">=14" "node": ">=14"
} }
}, },
"node_modules/@radix-ui/primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz",
"integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA=="
},
"node_modules/@radix-ui/react-arrow": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz",
"integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-collection": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz",
"integrity": "sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-slot": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-compose-refs": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz",
"integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-context": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz",
"integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-direction": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz",
"integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dismissable-layer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz",
"integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-escape-keydown": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-dropdown-menu": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz",
"integrity": "sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-menu": "2.1.1",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-guards": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz",
"integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-focus-scope": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz",
"integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-icons": { "node_modules/@radix-ui/react-icons": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz",
@ -1768,6 +1990,309 @@
"react": "^16.x || ^17.x || ^18.x" "react": "^16.x || ^17.x || ^18.x"
} }
}, },
"node_modules/@radix-ui/react-id": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz",
"integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-menu": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.1.tgz",
"integrity": "sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-dismissable-layer": "1.1.0",
"@radix-ui/react-focus-guards": "1.1.0",
"@radix-ui/react-focus-scope": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-popper": "1.2.0",
"@radix-ui/react-portal": "1.1.1",
"@radix-ui/react-presence": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-roving-focus": "1.1.0",
"@radix-ui/react-slot": "1.1.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"aria-hidden": "^1.1.1",
"react-remove-scroll": "2.5.7"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-popper": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz",
"integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==",
"dependencies": {
"@floating-ui/react-dom": "^2.0.0",
"@radix-ui/react-arrow": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0",
"@radix-ui/react-use-rect": "1.1.0",
"@radix-ui/react-use-size": "1.1.0",
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-portal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz",
"integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==",
"dependencies": {
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-presence": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz",
"integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz",
"integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==",
"dependencies": {
"@radix-ui/react-slot": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-roving-focus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz",
"integrity": "sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==",
"dependencies": {
"@radix-ui/primitive": "1.1.0",
"@radix-ui/react-collection": "1.1.0",
"@radix-ui/react-compose-refs": "1.1.0",
"@radix-ui/react-context": "1.1.0",
"@radix-ui/react-direction": "1.1.0",
"@radix-ui/react-id": "1.1.0",
"@radix-ui/react-primitive": "2.0.0",
"@radix-ui/react-use-callback-ref": "1.1.0",
"@radix-ui/react-use-controllable-state": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"@types/react-dom": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-slot": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz",
"integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==",
"dependencies": {
"@radix-ui/react-compose-refs": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-callback-ref": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz",
"integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-controllable-state": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz",
"integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-escape-keydown": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz",
"integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==",
"dependencies": {
"@radix-ui/react-use-callback-ref": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-layout-effect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz",
"integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==",
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz",
"integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==",
"dependencies": {
"@radix-ui/rect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/react-use-size": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz",
"integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==",
"dependencies": {
"@radix-ui/react-use-layout-effect": "1.1.0"
},
"peerDependencies": {
"@types/react": "*",
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@radix-ui/rect": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz",
"integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="
},
"node_modules/@rollup/rollup-android-arm-eabi": { "node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.18.1", "version": "4.18.1",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz",
@ -2444,6 +2969,17 @@
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"license": "Python-2.0" "license": "Python-2.0"
}, },
"node_modules/aria-hidden": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz",
"integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/aria-query": { "node_modules/aria-query": {
"version": "5.3.0", "version": "5.3.0",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
@ -3296,6 +3832,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/detect-node-es": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
},
"node_modules/deterministic-object-hash": { "node_modules/deterministic-object-hash": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz",
@ -3792,6 +4333,14 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/get-nonce": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
"engines": {
"node": ">=6"
}
},
"node_modules/get-stream": { "node_modules/get-stream": {
"version": "8.0.1", "version": "8.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
@ -4242,6 +4791,14 @@
"integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==", "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/is-alphabetical": { "node_modules/is-alphabetical": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
@ -6869,6 +7426,73 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-remove-scroll": {
"version": "2.5.7",
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz",
"integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==",
"dependencies": {
"react-remove-scroll-bar": "^2.3.4",
"react-style-singleton": "^2.2.1",
"tslib": "^2.1.0",
"use-callback-ref": "^1.3.0",
"use-sidecar": "^1.1.2"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-remove-scroll-bar": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz",
"integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==",
"dependencies": {
"react-style-singleton": "^2.2.1",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-style-singleton": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz",
"integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==",
"dependencies": {
"get-nonce": "^1.0.0",
"invariant": "^2.2.4",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/read-cache": { "node_modules/read-cache": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@ -7949,8 +8573,7 @@
"version": "2.6.3", "version": "2.6.3",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
"integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
"license": "0BSD", "license": "0BSD"
"optional": true
}, },
"node_modules/type-fest": { "node_modules/type-fest": {
"version": "2.19.0", "version": "2.19.0",
@ -8196,6 +8819,47 @@
"browserslist": ">= 4.21.0" "browserslist": ">= 4.21.0"
} }
}, },
"node_modules/use-callback-ref": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz",
"integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==",
"dependencies": {
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/use-sidecar": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz",
"integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==",
"dependencies": {
"detect-node-es": "^1.1.0",
"tslib": "^2.0.0"
},
"engines": {
"node": ">=10"
},
"peerDependencies": {
"@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0",
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/util-deprecate": { "node_modules/util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",

View file

@ -21,7 +21,9 @@
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"@fontsource/geist-mono": "^5.0.3", "@fontsource/geist-mono": "^5.0.3",
"@fontsource/geist-sans": "^5.0.3", "@fontsource/geist-sans": "^5.0.3",
"@radix-ui/react-dropdown-menu": "^2.1.1",
"@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-slot": "^1.1.0",
"@types/react": "^18.3.5", "@types/react": "^18.3.5",
"@types/react-dom": "^18.3.0", "@types/react-dom": "^18.3.0",
"astro": "^4.11.3", "astro": "^4.11.3",

View file

@ -12,7 +12,7 @@ const { entry } = Astro.props as {
<a <a
href={`/${entry.collection}/${entry.slug}`} href={`/${entry.collection}/${entry.slug}`}
class="not-prose group relative flex flex-nowrap rounded-lg border border-black/15 px-4 py-3 pr-10 transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white" class="not-prose group relative flex flex-nowrap rounded-lg border px-4 py-3 pr-10 transition-colors duration-300 ease-in-out"
> >
<div class="flex flex-1 flex-col truncate"> <div class="flex flex-1 flex-col truncate">
<div class="font-semibold"> <div class="font-semibold">
@ -32,11 +32,11 @@ const { entry } = Astro.props as {
y1="12" y1="12"
x2="19" x2="19"
y2="12" y2="12"
class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-hover:scale-x-100 group-focus-visible:translate-x-0 group-focus-visible:scale-x-100" class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out group-focus-visible:translate-x-0 group-focus-visible:scale-x-100"
></line> ></line>
<polyline <polyline
points="12 5 19 12 12 19" points="12 5 19 12 12 19"
class="-translate-x-1 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-focus-visible:translate-x-0" class="-translate-x-1 transition-transform duration-300 ease-in-out group-focus-visible:translate-x-0"
></polyline> ></polyline>
</svg> </svg>
</a> </a>

View file

@ -8,7 +8,7 @@ const { href } = Astro.props
<a <a
href={href} href={href}
class="not-prose group relative flex w-fit flex-nowrap rounded border border-black/15 py-1.5 pl-7 pr-3 transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white" class="not-prose group relative flex w-fit flex-nowrap rounded border py-1.5 pl-7 pr-3 transition-colors duration-300 ease-in-out"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -20,11 +20,11 @@ const { href } = Astro.props
y1="12" y1="12"
x2="19" x2="19"
y2="12" y2="12"
class="translate-x-2 scale-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-hover:scale-x-100 group-focus-visible:translate-x-0 group-focus-visible:scale-x-100" class="translate-x-2 scale-x-0 transition-transform duration-300 ease-in-out"
></line> ></line>
<polyline <polyline
points="12 5 5 12 12 19" points="12 5 5 12 12 19"
class="translate-x-1 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-focus-visible:translate-x-0" class="translate-x-1 transition-transform duration-300 ease-in-out"
></polyline> ></polyline>
</svg> </svg>
<div class="text-sm"> <div class="text-sm">

View file

@ -1,27 +0,0 @@
---
---
<button
id="back-to-top"
class="group relative flex w-fit flex-nowrap rounded border border-black/15 py-1.5 pl-8 pr-3 transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
class="absolute left-2 top-1/2 size-4 -translate-y-1/2 rotate-90 fill-none stroke-current stroke-2"
>
<line
x1="5"
y1="12"
x2="19"
y2="12"
class="translate-x-2 scale-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-hover:scale-x-100 group-focus-visible:translate-x-0 group-focus-visible:scale-x-100"
></line>
<polyline
points="12 5 5 12 12 19"
class="translate-x-1 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-focus-visible:translate-x-0"
></polyline>
</svg>
<div class="text-sm">Back to top</div>
</button>

View file

@ -1,44 +0,0 @@
---
interface Component {
type: 'default' | 'info' | 'warning' | 'error'
}
const { type = 'default' } = Astro.props
let emoji = '💡'
if (type === 'info') {
emoji = ''
} else if (type === 'warning') {
emoji = '⚠️'
} else if (type === 'error') {
emoji = '🚨'
}
---
<div class={`not-prose callout callout-${type}`}>
<span class="emoji pointer-events-none select-none">{emoji}</span>
<slot />
</div>
<style>
.callout {
@apply relative my-4 flex rounded border border-orange-800 bg-orange-100 p-3 text-orange-950 dark:border-orange-200/20 dark:bg-orange-950/20 dark:text-orange-200;
}
.emoji {
@apply pr-3 text-xl;
}
.callout-info {
@apply border-blue-800 bg-blue-100 text-blue-950 dark:border-blue-200/20 dark:bg-blue-950/20 dark:text-blue-200;
}
.callout-warning {
@apply border-yellow-800 bg-yellow-100 text-yellow-950 dark:border-yellow-200/20 dark:bg-yellow-950/20 dark:text-yellow-200;
}
.callout-error {
@apply border-red-800 bg-red-100 text-red-950 dark:border-red-200/20 dark:bg-red-950/20 dark:text-red-200;
}
</style>

View file

@ -1,21 +1,17 @@
--- ---
import Container from '@components/Container.astro' import Container from '@components/Container.astro'
import { SITE } from '@consts'
import BackToTop from '@components/BackToTop.astro'
import SocialIcons from './SocialIcons.astro' import SocialIcons from './SocialIcons.astro'
import { ModeToggle } from '@components/ui/mode-toggle'
--- ---
<footer> <footer class="py-8">
<Container> <Container>
<div class="my-2 flex justify-between"> <div class="flex justify-between items-center">
<SocialIcons icon_size={'text-xl'} /> <div class="flex items-center space-x-4">
<BackToTop /> <ModeToggle client:load />
</div> <p class="text-sm text-muted-foreground">&copy; {new Date().getFullYear()} All rights reserved.</p>
<div class="flex items-center justify-between">
<div>
&copy; {new Date().getFullYear()} • {SITE.TITLE} 👀<br />
Built with Astro
</div> </div>
<SocialIcons />
</div> </div>
</Container> </Container>
</footer> </footer>

View file

@ -4,6 +4,8 @@ import '../styles/global.css'
import '@fontsource/geist-sans' import '@fontsource/geist-sans'
import '@fontsource/geist-mono' import '@fontsource/geist-mono'
import { ViewTransitions } from 'astro:transitions'
interface Props { interface Props {
title: string title: string
description: string description: string
@ -37,73 +39,40 @@ const { title, description, image = '/blog-placeholder-1.jpg' } = Astro.props
<meta property="twitter:description" content={description} /> <meta property="twitter:description" content={description} />
<meta property="twitter:image" content={new URL(image, Astro.url)} /> <meta property="twitter:image" content={new URL(image, Astro.url)} />
<ViewTransitions />
<script is:inline> <script is:inline>
function init() { function setDarkMode(document) {
onScroll() const getThemePreference = () => {
addCopyCodeButtons() if (
typeof localStorage !== 'undefined' &&
const backToTop = document.getElementById('back-to-top') localStorage.getItem('theme')
backToTop?.addEventListener('click', (event) => scrollToTop(event)) ) {
return localStorage.getItem('theme')
const backToPrev = document.getElementById('back-to-prev') }
backToPrev?.addEventListener('click', () => window.history.back()) return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
document.addEventListener('scroll', onScroll) : 'theme-light'
}
function onScroll() {
if (window.scrollY > 0) {
document.documentElement.classList.add('scrolled')
} else {
document.documentElement.classList.remove('scrolled')
} }
} const isDark = getThemePreference() === 'dark'
document.documentElement.classList[isDark ? 'add' : 'remove']('dark')
function scrollToTop(event) { if (typeof localStorage !== 'undefined') {
event.preventDefault() const observer = new MutationObserver(() => {
window.scrollTo({ const isDark = document.documentElement.classList.contains('dark')
top: 0, localStorage.setItem('theme', isDark ? 'dark' : 'theme-light')
behavior: 'smooth', })
}) observer.observe(document.documentElement, {
} attributes: true,
attributeFilter: ['class'],
function addCopyCodeButtons() {
let copyButtonLabel = '📋'
let codeBlocks = Array.from(document.querySelectorAll('pre'))
async function copyCode(codeBlock, copyButton) {
const codeText = codeBlock.innerText
const buttonText = copyButton.innerText
const textToCopy = codeText.replace(buttonText, '')
await navigator.clipboard.writeText(textToCopy)
copyButton.innerText = '✅'
setTimeout(() => {
copyButton.innerText = copyButtonLabel
}, 2000)
}
for (let codeBlock of codeBlocks) {
const wrapper = document.createElement('div')
wrapper.style.position = 'relative'
const copyButton = document.createElement('button')
copyButton.innerText = copyButtonLabel
copyButton.classList = 'copy-code'
codeBlock.setAttribute('tabindex', '0')
codeBlock.appendChild(copyButton)
codeBlock.parentNode.insertBefore(wrapper, codeBlock)
wrapper.appendChild(codeBlock)
copyButton?.addEventListener('click', async () => {
await copyCode(codeBlock, copyButton)
}) })
} }
} }
document.addEventListener('DOMContentLoaded', () => init()) setDarkMode(document)
document.addEventListener('astro:after-swap', () => init())
document.addEventListener('astro:before-swap', (ev) => {
// Pass the incoming document to set the theme on it
setDarkMode(ev.newDocument)
})
</script> </script>

View file

@ -15,7 +15,7 @@ const { href, external, underline = true, group = false, ...rest } = Astro.props
href={href} href={href}
target={external ? '_blank' : '_self'} target={external ? '_blank' : '_self'}
class={cn( class={cn(
'inline-block decoration-black/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:decoration-white/30 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out', 'inline-block transition-colors duration-300 ease-in-out',
underline && 'underline underline-offset-[3px]', underline && 'underline underline-offset-[3px]',
group && 'group', group && 'group',
)} )}

View file

@ -11,7 +11,7 @@ const { name, avatar, bio } = member.data
--- ---
<div <div
class="not-prose flex size-full flex-col gap-4 overflow-hidden rounded-xl border border-foreground bg-background p-6 hover:bg-secondary sm:flex-row sm:items-center" class="not-prose flex size-full flex-col gap-4 overflow-hidden rounded-xl border p-6 hover:bg-secondary sm:flex-row sm:items-center"
> >
<Image <Image
src={avatar} src={avatar}

View file

@ -7,7 +7,7 @@ const { prevPost, nextPost } = Astro.props
prevPost?.slug ? ( prevPost?.slug ? (
<a <a
href={`/blog/${prevPost?.slug}`} href={`/blog/${prevPost?.slug}`}
class="group relative flex flex-nowrap rounded-lg border border-black/15 px-4 py-3 pl-10 no-underline transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white" class="group relative flex flex-nowrap rounded-lg border px-4 py-3 pl-10 no-underline transition-colors duration-300 ease-in-out"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -19,11 +19,11 @@ const { prevPost, nextPost } = Astro.props
y1="12" y1="12"
x2="19" x2="19"
y2="12" y2="12"
class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-hover:scale-x-100 group-focus-visible:translate-x-0 group-focus-visible:scale-x-100" class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out"
/> />
<polyline <polyline
points="12 5 5 12 12 19" points="12 5 5 12 12 19"
class="translate-x-1 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-focus-visible:translate-x-0" class="translate-x-1 transition-transform duration-300 ease-in-out"
/> />
</svg> </svg>
<div class="flex items-center text-sm">{prevPost?.data.title}</div> <div class="flex items-center text-sm">{prevPost?.data.title}</div>
@ -37,7 +37,7 @@ const { prevPost, nextPost } = Astro.props
nextPost?.slug ? ( nextPost?.slug ? (
<a <a
href={`/blog/${nextPost?.slug}`} href={`/blog/${nextPost?.slug}`}
class="group relative flex flex-grow flex-row-reverse flex-nowrap rounded-lg border border-black/15 px-4 py-4 pr-10 no-underline transition-colors duration-300 ease-in-out hover:bg-black/5 hover:text-black focus-visible:bg-black/5 focus-visible:text-black dark:border-white/20 dark:hover:bg-white/5 dark:hover:text-white dark:focus-visible:bg-white/5 dark:focus-visible:text-white" class="group relative flex flex-grow flex-row-reverse flex-nowrap rounded-lg border px-4 py-4 pr-10 no-underline transition-colors duration-300 ease-in-out"
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
@ -49,11 +49,11 @@ const { prevPost, nextPost } = Astro.props
y1="12" y1="12"
x2="19" x2="19"
y2="12" y2="12"
class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-hover:scale-x-100 group-focus-visible:translate-x-0 group-focus-visible:scale-x-100" class="translate-x-3 scale-x-0 transition-transform duration-300 ease-in-out"
/> />
<polyline <polyline
points="12 5 19 12 12 19" points="12 5 19 12 12 19"
class="-translate-x-1 transition-transform duration-300 ease-in-out group-hover:translate-x-0 group-focus-visible:translate-x-0" class="-translate-x-1 transition-transform duration-300 ease-in-out"
/> />
</svg> </svg>
<div class="flex items-center text-sm">{nextPost?.data.title}</div> <div class="flex items-center text-sm">{nextPost?.data.title}</div>

View file

@ -13,7 +13,7 @@ const { URL, icon, icon_size } = Astro.props
<a <a
href={URL} href={URL}
target={'_blank'} target={'_blank'}
class={`inline-block ${icon_size} decoration-black/30 dark:decoration-white/30 hover:decoration-black/50 focus-visible:decoration-black/50 dark:hover:decoration-white/50 dark:focus-visible:decoration-white/50 text-current hover:text-cyan-500 focus-visible:text-black dark:hover:text-orange-500 dark:focus-visible:text-white transition-colors duration-300 ease-in-out`} class={`inline-block ${icon_size}`}
> >
<i class={`bi bi-${icon}`}></i> <i class={`bi bi-${icon}`}></i>
</a> </a>

View file

@ -1,23 +1,14 @@
--- ---
import SocialIcon from '@components/SocialIcon.astro' import { Twitter, Github, Linkedin, Mail, GraduationCap, Rss } from 'lucide-react'
import { SITE } from '@consts' import { SITE } from '@consts'
export interface Props {
icon_size: string
}
const { icon_size } = Astro.props
--- ---
<ul class="not-prose flex flex-wrap gap-2"> <ul class="not-prose flex flex-wrap gap-2">
<SocialIcon icon_size={icon_size} URL="#" icon="twitter-x" /> <a href="#" class="inline-block"><Twitter /></a>
<SocialIcon icon_size={icon_size} URL="#" icon="github" /> <a href="#" class="inline-block"><Github /></a>
<SocialIcon icon_size={icon_size} URL="#" icon="linkedin" /> <a href="#" class="inline-block"><Linkedin /></a>
<SocialIcon icon_size={icon_size} URL="#" icon="envelope-fill" /> <a href="#" class="inline-block"><Mail /></a>
<SocialIcon icon_size={icon_size} URL="#" icon="mortarboard-fill" /> <a href="#" class="inline-block"><GraduationCap /></a>
<SocialIcon <a href={`${SITE.SITEURL}/rss.xml`} class="inline-block"><Rss /></a>
icon_size={icon_size}
URL={`${SITE.SITEURL}/rss.xml`}
icon="rss-fill"
/>
</ul> </ul>

View file

@ -27,9 +27,9 @@ function buildToc(headings: Heading[]) {
} }
--- ---
<details open class="rounded-lg border border-black/15 dark:border-white/20"> <details open class="rounded-lg border">
<summary>Table of Contents</summary> <summary>Table of Contents</summary>
<nav class=""> <nav>
<ul class="py-3"> <ul class="py-3">
{toc.map((heading) => <TableOfContentsHeading heading={heading} />)} {toc.map((heading) => <TableOfContentsHeading heading={heading} />)}
</ul> </ul>
@ -40,12 +40,4 @@ function buildToc(headings: Heading[]) {
summary { summary {
@apply cursor-pointer rounded-t-lg px-3 py-1.5 font-medium transition-colors; @apply cursor-pointer rounded-t-lg px-3 py-1.5 font-medium transition-colors;
} }
summary:hover {
@apply bg-black/5 dark:bg-white/5;
}
details[open] summary {
@apply bg-black/5 dark:bg-white/5;
}
</style> </style>

View file

@ -0,0 +1,57 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"
export { Button, buttonVariants }

View file

@ -0,0 +1,203 @@
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
} from "@radix-ui/react-icons"
import { cn } from "@/lib/utils"
const DropdownMenu = DropdownMenuPrimitive.Root
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
const DropdownMenuGroup = DropdownMenuPrimitive.Group
const DropdownMenuPortal = DropdownMenuPrimitive.Portal
const DropdownMenuSub = DropdownMenuPrimitive.Sub
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
const DropdownMenuSubTrigger = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}
>(({ className, inset, children, ...props }, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent",
inset && "pl-8",
className
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto h-4 w-4" />
</DropdownMenuPrimitive.SubTrigger>
))
DropdownMenuSubTrigger.displayName =
DropdownMenuPrimitive.SubTrigger.displayName
const DropdownMenuSubContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
))
DropdownMenuSubContent.displayName =
DropdownMenuPrimitive.SubContent.displayName
const DropdownMenuContent = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
sideOffset={sideOffset}
className={cn(
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md",
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
))
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
const DropdownMenuItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
)}
{...props}
/>
))
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
const DropdownMenuCheckboxItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
checked={checked}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CheckIcon className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
))
DropdownMenuCheckboxItem.displayName =
DropdownMenuPrimitive.CheckboxItem.displayName
const DropdownMenuRadioItem = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<DotFilledIcon className="h-4 w-4 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
))
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
const DropdownMenuLabel = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
"px-2 py-1.5 text-sm font-semibold",
inset && "pl-8",
className
)}
{...props}
/>
))
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
const DropdownMenuSeparator = React.forwardRef<
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn("-mx-1 my-1 h-px bg-muted", className)}
{...props}
/>
))
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
const DropdownMenuShortcut = ({
className,
...props
}: React.HTMLAttributes<HTMLSpanElement>) => {
return (
<span
className={cn("ml-auto text-xs tracking-widest opacity-60", className)}
{...props}
/>
)
}
DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
export {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuGroup,
DropdownMenuPortal,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuRadioGroup,
}

View file

@ -0,0 +1,52 @@
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export function ModeToggle() {
const [theme, setThemeState] = React.useState<
"theme-light" | "dark" | "system"
>("theme-light")
React.useEffect(() => {
const isDarkMode = document.documentElement.classList.contains("dark")
setThemeState(isDarkMode ? "dark" : "theme-light")
}, [])
React.useEffect(() => {
const isDark =
theme === "dark" ||
(theme === "system" &&
window.matchMedia("(prefers-color-scheme: dark)").matches)
document.documentElement.classList[isDark ? "add" : "remove"]("dark")
}, [theme])
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" size="icon">
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setThemeState("theme-light")}>
Light
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setThemeState("dark")}>
Dark
</DropdownMenuItem>
<DropdownMenuItem onClick={() => setThemeState("system")}>
System
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}

View file

@ -1,270 +0,0 @@
---
title: '[Tutorial] Getting started with Astro-Micro-Academics'
description: 'Hit the ground running.'
date: '2024-07-26'
tags: ['guide', 'tutorial']
---
:exclamation: Also refer to [Old] posts to see examples and changes. Some changes are removed in this version, which are marked.
## Install Astro-Micro-Academics
Clone the [repository](https://github.com/jingwu2121/astro-micro-academic).
```sh
git clone https://github.com/jingwu2121/astro-micro-academic.git
```
```sh
cd astro-micro-academic
```
```sh
npm i
```
Run local server
```sh
npm run dev
```
## Update the Homepage
Update your home page in `src/pages/index.astro`.
## CV & About
Update your CV and About page in `src/pages/cv.astro` and `src/pages/about.astro`.
```ts
const works = [
{
company: 'Company A',
time: '2022-Present',
job_title: 'Research Scientist',
location: 'London, UK',
description: 'Your Notes about the job',
},
{
company: 'Company A',
time: '2022-Present',
job_title: 'Research Scientist',
location: 'London, UK',
description: 'Your Notes about the job',
},
]
const educations = [
{
school: 'University 1',
time: '2022-Present',
job_title: 'BEng in Electronic Information Engineering',
location: 'London, UK',
description: 'Your Notes about the study',
},
]
```
## Social Links
Update the social links in `src/components/SocialIcons.astro`, simply replace the `URL`.
## Publications metadata
Metadata is required for each post. Add a new `publication.md` to automartically add a publication on the website. Publications are sorted by date.
```astro
---
title: 'Diffusion Models Beat GANs on Image Synthesis'
description: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestias earum quod quo repellat blanditiis est iste eos dolorem! Voluptatibus corporis totam sed unde est iusto neque iure natus adipisci omnis.'
date: '2024-07-26'
authors: 'John B*, Jon A*, Frank C, John B, Jon A, Frank C'
paperURL: 'Paper: https://astro-sphere-demo.vercel.app'
codeURL: 'Code: '
webURL: 'Web: https://github.com/markhorn-dev/astro-sphere'
dataURL: 'Data: https://github.com/markhorn-dev/astro-sphere'
img: '/rupert-cat.gif'
imgAlt: 'Paper Teaser'
pub: 'ECCV2024'
---
```
| Field | Req | Type | Remarks |
| :--------------------------------- | :-- | :----- | :--------------------------------------------------------------------------------------------------------------- |
| title | Yes | string | Title of the content. Used in SEO and RSS. |
| description | Yes | string | Description of the content. Used in SEO and RSS. |
| date | Yes | string | Must be a valid date string (able to be parsed). |
| authors | Yes | string | A string seperated by comma. |
| paperURL, codeURL, webURL, dataURL | Yes | string | A string seperated by ": ". If you don't have a link to add, leave the link part blank, e.g. `codeURL: "Code: "` |
| img | Yes | string | Path to teaser image. |
| imgAlt | Yes | string | Description of the image. |
| pub | Yes | string | The conference or journal |
## Blog metadata
Metadata is required for each post.
```astro
---
title: 'Blog Collection'
description: 'How to add posts to the blog.'
date: '2024-03-21'
tags: ['guide', 'tutorial']
draft: false
---
```
| Field | Req | Type | Remarks |
| :---------- | :-- | :------ | :----------------------------------------------- |
| title | Yes | string | Title of the content. Used in SEO and RSS. |
| description | Yes | string | Description of the content. Used in SEO and RSS. |
| date | Yes | string | Must be a valid date string (able to be parsed). |
| tags | Yes | list | A list of strings |
| draft | No | boolean | If draft: true, content will not be published. |
## Customize the website metadata and set up RSS
To change the website metadata, edit `src/consts.ts`.
```ts
// src/consts.ts
export const SITE: Site = {
TITLE: 'Astro Micro Academics',
DESCRIPTION: 'Astro Micro Academics is for academic user.',
EMAIL: 'youremial@gmail.com',
NUM_POSTS_ON_HOMEPAGE: 2,
NUM_PUBLICATIONS_ON_HOMEPAGE: 3,
SITEURL: 'https://astro-micro-academic.vercel.app', // Update here to link the RSS icon to your website RSS
}
```
| Field | Req | Description |
| :--------------- | :-- | :--------------------------------------------------- |
| TITLE | Yes | Displayed in header and footer. Used in SEO and RSS. |
| DESCRIPTION | Yes | Used in SEO and RSS. |
| EMAIL | Yes | Displayed in contact section. |
| NUM_POSTS | Yes | Limit number of posts on home page. |
| NUM_PUBLICATIONS | Yes | Limit number of research on home page. |
| SITEURL | Yes | Your website URL |
### RSS Post
Please tag the post of RSS feed with tag `"rss-feed"`, other posts are not included in the RSS.
---
## Custom metadata for highlighted author in your paper
```ts
// src/consts.ts
export const HIGHLIGHTAUTHOR = 'John B'
```
## Customize metadata for individual pages
```ts
// src/consts.ts
export const HOME: Metadata = {
TITLE: 'Home',
DESCRIPTION: 'Astro Micro is an accessible theme for Astro.',
}
export const BLOG: Metadata = {
TITLE: 'Blog',
DESCRIPTION: 'A collection of articles on topics I am passionate about.',
}
export const RESEARCH: Metadata = {
TITLE: 'Publications',
DESCRIPTION:
'A collection of my publications with links to paper, repositories and live demos.',
}
export const CV: Metadata = {
TITLE: 'CV',
DESCRIPTION: 'your cv',
}
export const TAGS: Metadata = {
TITLE: 'TAGS',
DESCRIPTION: 'blog tag filter',
}
export const ABOUT: Metadata = {
TITLE: 'ABOUT',
DESCRIPTION: 'A self-intro',
}
```
| Field | Req | Description |
| :---------- | :-- | :--------------------------------------------- |
| TITLE | Yes | Displayed in browser tab. Used in SEO and RSS. |
| DESCRIPTION | Yes | Used in SEO and RSS. |
---
## Deploy the site
To set up RSS and Giscus, it's easier if the site is deployed and has a URL for you to use. Instantly deploy to Vercel or Netlify by clicking the buttons below.
<div class="flex gap-2">
<a target="_blank" aria-label="Deploy with Vercel" href="https://vercel.com/new/clone?repository-url=https://github.com/trevortylerlee/astro-micro">
<img src="/deploy_vercel.svg" />
</a>
<a target="_blank" aria-label="Deploy with Netlify" href="https://app.netlify.com/start/deploy?repository=https://github.com/trevortylerlee/astro-micro">
<img src="/deploy_netlify.svg" />
</a>
</div>
To deploy manually see [Astro's docs](https://docs.astro.build/en/guides/deploy/).
To deploy to Github, see [here](https://docs.astro.build/en/guides/deploy/github/).
## Set up Giscus (from Astro Micro)
Follow the steps at [giscus.app](https://giscus.app). Once you get your custom Giscus script from that site, go to `Giscus.astro` and replace that script with your own.
```js
// src/components/Giscus.astro
<script
is:inline
src="https://giscus.app/client.js"
data-repo="trevortylerlee/astro-micro"
data-repo-id="R_kgDOL_6l9Q"
data-category="Announcements"
data-category-id="DIC_kwDOL_6l9c4Cfk55"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="en"
data-loading="lazy"
crossorigin="anonymous"
async
></script>
```
To change the Giscus themes used, edit the `setGiscusTheme` function in `Head.astro`.
```js
// src/components/Head.astro
const setGiscusTheme = () => {
const giscus = document.querySelector('.giscus-frame')
const isDark = document.documentElement.classList.contains('dark')
if (giscus) {
const url = new URL(giscus.src)
// Change "dark" and "light" to other Giscus themes
url.searchParams.set('theme', isDark ? 'dark' : 'light')
giscus.src = url.toString()
}
}
```

View file

@ -1,105 +0,0 @@
---
title: '[Old] Everything new in Astro Micro'
description: 'Features, enhancements, and changes.'
date: '2024-05-09'
tags: ['astro-micro']
---
import Callout from '@/components/Callout.astro'
---
## Pagefind search 🔎
[Pagefind](https://pagefind.app) is a search library for static websites. Micro uses [Sergey Shishkin's](https://github.com/shishkin) [astro-pagefind](https://github.com/shishkin/astro-pagefind) integration. This integration simplifies development and does not require any changes to the default build script.
Press <kbd>/</kbd> or <kbd>CTRL</kbd> + <kbd>K</kbd> to open the search dialog. For Mac users, <kbd>⌘</kbd> + <kbd>K</kbd> can also be used. To dismiss the search dialog, press <kbd>Esc</kbd> or click on an area outside the component.
### Build and develop
<Callout type="error">
The site **must** be built at least once so Pagefind can index the content.
</Callout>
```bash
# Pagefind must index the site to function
npm run build
```
When developing you can continue to use `npm run dev` and Pagefind will use the index from the last available build.
---
## Giscus comments 💬
[Giscus](https://giscus.app) leverages Github discussions to act as a comments system. To get Giscus working on your own website, see [here](/blog/01-getting-started#deploy-the-site).
---
## Callout component 🆕
<Callout>
Adipisicing et officia reprehenderit fugiat occaecat cupidatat exercitation
labore consequat ullamco nostrud non.
</Callout>
<Callout type="info">
Adipisicing et officia reprehenderit fugiat occaecat cupidatat exercitation
labore consequat ullamco nostrud non.
</Callout>
<Callout type="warning">
Adipisicing et officia reprehenderit fugiat occaecat cupidatat exercitation
labore consequat ullamco nostrud non.
</Callout>
<Callout type="error">
Adipisicing et officia reprehenderit fugiat occaecat cupidatat exercitation
labore consequat ullamco nostrud non.
</Callout>
---
## UI enhancements 🎨
- Elements are styled and on focus
- Increased contrast in light mode
- Active theme is indicated by theme buttons
- Separate syntax highlight themes for light and dark mode
- Code blocks have a copy button
- Add pagination to the bottom of blog posts
- Create 404 page
- Add ToC component to posts
---
## Other changes
- Change fonts to Geist Sans and Geist Mono
- Switch base color from "stone" to "neutral"
- Change formatted date to use "long" option for month
- Minor spacing changes throughout
- Remove "work" collection and components
- If desired, you can get the code from [Astro Nano](https://github.com/markhorn-dev/astro-nano)
- Slightly increased link decoration offset
- Slightly sped-up animations
- Reversed animation
- Ensure posts use an h1 tag for post titles
- Tweaked typography
---
## Issues ⚠️
### Active issues
- [PostNavigation.astro is broken when deployed with Cloudflare Pages](https://github.com/trevortylerlee/astro-micro/issues/39)
### Closed issues
- Fixed by [blopker](https://github.com/blopker): [Pagefind requires a refresh to function when ViewTransitions is enabled](https://github.com/trevortylerlee/astro-micro/issues/7)
- Fixed by [blopker](https://github.com/blopker): [ToC links are obscured by Header when scrolled to](https://github.com/trevortylerlee/astro-micro/issues/4)
- Fixed by [cgranier](https://github.com/cgranier): [Pagination links advance by slug/folder](https://github.com/trevortylerlee/astro-micro/issues/26)
- Fixed by [cgranier](https://github.com/cgranier): [Hides Table of Contents when there are no headings](https://github.com/trevortylerlee/astro-micro/pull/30)
- Fixed by [arastoonet](https://github.com/arastoonet): [Fix typo in README](https://github.com/trevortylerlee/astro-micro/pull/19)
- Fixed by [luciancah](https://github.com/luciancah): [Prevent Pagefind from double-indexing results](https://github.com/trevortylerlee/astro-micro/issues/40)

View file

@ -1,181 +0,0 @@
---
title: '[Old] Getting started with Astro-Micro'
description: 'Hit the ground running.'
date: '2024-03-22'
tags: ['guide', 'start']
---
---
## Install astro-micro
Clone the [Astro Micro repository](https://github.com/trevortylerlee/astro-micro.git).
```sh
git clone https://github.com/trevortylerlee/astro-micro.git my-astro-micro
```
```sh
cd my-astro-micro
```
```sh
npm i
```
```sh
npm run build
```
```sh
npm run dev
```
## Customize the website metadata
To change the website metadata, edit `src/consts.ts`.
```ts
// src/consts.ts
export const SITE: Site = {
NAME: 'Astro Micro',
DESCRIPTION: 'Astro Micro is an accessible theme for Astro.',
EMAIL: 'trevortylerlee@gmail.com',
NUM_POSTS_ON_HOMEPAGE: 3,
NUM_PUBLICATIONS_ON_HOMEPAGE: 3,
}
```
| Field | Req | Description |
| :--------------- | :-- | :--------------------------------------------------- |
| TITLE | Yes | Displayed in header and footer. Used in SEO and RSS. |
| DESCRIPTION | Yes | Used in SEO and RSS. |
| EMAIL | Yes | Displayed in contact section. |
| NUM_POSTS | Yes | Limit number of posts on home page. |
| NUM_PUBLICATIONS | Yes | Limit number of research on home page. |
---
## Customize metadata for individual pages
```ts
// src/consts.ts
export const ABOUT: Metadata = {
TITLE: 'About',
DESCRIPTION: 'Astro Micro is a fork of Astro Nano.',
}
```
| Field | Req | Description |
| :---------- | :-- | :--------------------------------------------- |
| TITLE | Yes | Displayed in browser tab. Used in SEO and RSS. |
| DESCRIPTION | Yes | Used in SEO and RSS. |
---
## ~~Add your social media links~~ Removed in Micro Academics
```ts
// src/consts.ts
export const SOCIALS: Socials = [
{
NAME: 'twitter-x',
HREF: 'https://twitter.com/boogerbuttcheeks',
},
{
NAME: 'github',
HREF: 'https://github.com/trevortylerlee',
},
{
NAME: 'linkedin',
HREF: 'https://www.linkedin.com/in/trevortylerlee',
},
]
```
| Field | Req | Description |
| :---- | :-- | :-------------------------------------- |
| NAME | Yes | Displayed in contact section as a link. |
| HREF | Yes | External url to social media profile. |
## Deploy the site
To set up RSS and Giscus, it's easier if the site is deployed and has a URL for you to use. Instantly deploy to Vercel or Netlify by clicking the buttons below.
<div class="flex gap-2">
<a target="_blank" aria-label="Deploy with Vercel" href="https://vercel.com/new/clone?repository-url=https://github.com/trevortylerlee/astro-micro">
<img src="/deploy_vercel.svg" />
</a>
<a target="_blank" aria-label="Deploy with Netlify" href="https://app.netlify.com/start/deploy?repository=https://github.com/trevortylerlee/astro-micro">
<img src="/deploy_netlify.svg" />
</a>
</div>
To deploy manually see [Astro's docs](https://docs.astro.build/en/guides/deploy/).
## ~~Set up RSS~~ New config in Astro Micro Academics
Change the `site` option to the deployed site's URL.
```js
// astro.config.mjs
export default defineConfig({
site: 'https://astro-micro.vercel.app',
integrations: [tailwind(), sitemap(), mdx(), pagefind()],
markdown: {
shikiConfig: {
theme: 'css-variables',
},
},
})
```
## Set up Giscus
Follow the steps at [giscus.app](https://giscus.app). Once you get your custom Giscus script from that site, go to `Giscus.astro` and replace that script with your own.
```js
// src/components/Giscus.astro
<script
is:inline
src="https://giscus.app/client.js"
data-repo="trevortylerlee/astro-micro"
data-repo-id="R_kgDOL_6l9Q"
data-category="Announcements"
data-category-id="DIC_kwDOL_6l9c4Cfk55"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="en"
data-loading="lazy"
crossorigin="anonymous"
async
></script>
```
To change the Giscus themes used, edit the `setGiscusTheme` function in `Head.astro`.
```js
// src/components/Head.astro
const setGiscusTheme = () => {
const giscus = document.querySelector('.giscus-frame')
const isDark = document.documentElement.classList.contains('dark')
if (giscus) {
const url = new URL(giscus.src)
// Change "dark" and "light" to other Giscus themes
url.searchParams.set('theme', isDark ? 'dark' : 'light')
giscus.src = url.toString()
}
}
```

View file

@ -1,63 +0,0 @@
---
title: '[Old] Blog Collection'
description: 'How to add posts to the blog.'
date: '2024-03-21'
tags: ['aa']
---
---
## Working with the `blog` collection:
The `blog` collection is found in `src/content/blog`.
```
📁 /src/content/blog
└── 📁 post-1
└── 📄 index.md
└── 📁 post-2
└── 📄 index.mdx
```
In the above example, two blog posts will be generated with the folder name representing the slug.
- `https://example.com/blog/post-1`
- `https://example.com/blog/post-2`
---
## Provide metadata
Metadata is required for each post.
```astro
---
title: 'Blog Collection'
description: 'How to add posts to the blog.'
date: '2024-03-21'
draft: false
---
```
| Field | Req | Type | Remarks |
| :---------- | :-- | :------ | :----------------------------------------------- |
| title | Yes | string | Title of the content. Used in SEO and RSS. |
| description | Yes | string | Description of the content. Used in SEO and RSS. |
| date | Yes | string | Must be a valid date string (able to be parsed). |
| draft | No | boolean | If draft: true, content will not be published. |
---
All that's left to do is write the content under the metadata.
```astro
---
title: 'Blog Collection'
description: 'How to add posts to the blog.'
date: '2024-03-21'
draft: false
---
## Working with the blog collection
<!-- content -->
```

View file

@ -1,398 +0,0 @@
---
title: '[Old] Markdown syntax guide'
description: 'Get started writing content in Markdown.'
date: '2024-03-17'
---
import Callout from '@/components/Callout.astro'
---
## Headings
To create headings, use hash symbols (#) followed by a space. The number of hash symbols indicates the heading level.
<Callout>
Use `h2` tags instead of `h1` tags in the post. Too many `h1` tags on a single
page can impact SEO. The post title serves as the `h1`.
</Callout>
```md
# Heading 1
## Heading 2
### Heading 3
#### Heading 4
##### Heading 5
###### Heading 6
```
<h1>Heading 1</h1>
<h2>Heading 2</h2>
<h3>Heading 3</h3>
<h4>Heading 4</h4>
<h5>Heading 5</h5>
<h6>Heading 6</h6>
---
## Paragraphs
To create paragraphs, use a blank line to separate one or more lines of text.
{/* prettier-ignore */}
```md
<!-- empty line -->
I love Star Wars.
<!-- empty line -->
My favourite is Episode III Revenge of the Sith.
<!-- empty line -->
```
I love Star Wars.
My favourite is Episode III Revenge of the Sith.
---
## Italic
Use one asterisk \(\*\) or underscore \(\_\) to italicize text.
{/* prettier-ignore */}
```md
I *love* Star Wars.
My _favourite_ is Episode III Revenge of the Sith.
```
I _love_ Star Wars.
My _favourite_ is Episode III Revenge of the Sith.
---
## Bold
Use two asterisks \(\*\) or underscores \(\_\) to bold text.
{/* prettier-ignore */}
```md
I **love** Star Wars.
My __favourite__ is Episode III Revenge of the Sith.
```
I **love** Star Wars.
My **favourite** is Episode III Revenge of the Sith.
---
## Italic and Bold
Use three asterisks \(\*\) or underscores \(\_\) to both bold and italicize text.
{/* prettier-ignore */}
```md
I ***love*** Star Wars.
My ___favourite___ is Episode III Revenge of the Sith.
```
I **_love_** Star Wars.
My **_favourite_** is Episode III Revenge of the Sith.
---
## Horizontal Rule
Use three hyphens \(\-\), asterisks \(\*\), or underscores \(\_\) to create a horizontal rule.
{/* prettier-ignore */}
```md
<!-- empty line -->
---
<!-- empty line -->
***
<!-- empty line -->
___
<!-- empty line -->
```
---
---
---
## Links
To create a link, the link text in brackets \(\[\]\) and then follow it immediately with the URL in parentheses \(\(\)\).
```md
Micro is a fork of [astro-nano](https://github.com/markhorn-dev/astro-nano).
```
Micro is a fork of [astro-nano](https://github.com/markhorn-dev/astro-nano).
---
## Ordered Lists
To create an ordered list, add line items with numbers followed by periods. Use an indent to create a nested list.
```md
1. Item 1
2. Item 2
1. Sub item 1
2. Sub item 2
3. Item 3
```
1. Item 1
2. Item 2
1. Sub item 1
2. Sub item 2
3. Item 3
---
## Unordered List
To create an unordered list, add a hyphen \(\-\), an asterisk \(\*\), or a plus sign \(\+\) in front of line items. Don't mix. Use an indent to create a nested list.
```md
- Item 1
- Item 2
- Sub item 1
- Sub item 2
- Item 3
```
- Item 1
- Item 2
- Sub item 1
- Sub item 2
- Item 3
---
## Images
To add an image, add an exclamation mark (!), followed by alt text in brackets ([]), and the path or URL to the image asset in parentheses.
```md
![altText](pathToImage)
```
### Relative
Use the `![altText](./image.*)` pattern relative to the same folder as the markdown file. Notice the period.
```md
![X-Wing Starfighter](./x-wing.jpeg)
```
![X-Wing Starfighter](./x-wing.jpeg)
### Public Image
Use the `![altText](/image.*)` pattern relative to the public folder. No period.
```md
![Y-Wing Starfighter](/y-wing.jpeg)
```
![Y-Wing Starfighter](/y-wing.jpeg)
### External Image
Use the `![altText](url)` pattern.
```md
![Naboo N-1 Starfighter](https://raw.githubusercontent.com/trevortylerlee/n1/main/n1.jpeg)
```
![Naboo N-1 Starfighter](https://raw.githubusercontent.com/trevortylerlee/n1/main/n1.jpeg)
---
## Blockquotes
To add a blockquote add the greater-than character \(\>\) before a paragraph. For multi-line blockquotes, add additional greater-than character for each line and include an empty spacer line.
```md
> So this is how liberty dies...
>
> with thunderous applause.
```
> So this is how liberty dies...
>
> with thunderous applause.
---
## Strikethrough
Use a tilde \(\~\) symbol to strikethrough text.
```md
~I don't like sand.~ It's coarse and rough and irritating.
```
~I don't like sand.~ It's coarse and rough and irritating.
---
## Subscript
Use the `<sub>` tag to denote subscript.
```md
H<sub>2</sub>O
```
H<sub>2</sub>O
---
## Superscript
Use the `<sup>` tag to denote superscript.
```md
E=mc<sup>2</sup>
```
E=mc<sup>2</sup>
---
## Keyboard
Use the `<kbd>` tag to denote keys on the keyboard.
```md
<kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd>
```
<kbd>CTRL</kbd> + <kbd>ALT</kbd> + <kbd>Delete</kbd>
---
## Abbreviate
Use the `<abbr>` tag to denote abbreviation.
```md
<abbr title="Graphics Interchange Format">GIF</abbr>
```
<abbr title="Graphics Interchange Format">GIF</abbr>
---
### Highlight
Use the `<mark>` tag to denote highlighted text.
```md
Do or do not. <mark>There is no try.</mark>
```
Do or do not. <mark>There is no try.</mark>
---
## Task Lists
Combine a list with square brackets ([]) representing a checkbox. Typing `x` inside the brackets marks the task as complete.
```md
- [x] Build a lightsaber
- [ ] Pass the Jedi Trials
- [ ] Train a padawan
```
- [x] Build a lightsaber
- [ ] Pass the Jedi Trials
- [ ] Train a padawan
---
## Tables
Use three or more hyphens (-) for the column headers and use pipes (|) to separate each column. You can align text in the columns to the left, right, or center by adding a colon (:) to the left, right, or on both side of the hyphens.
```md
| Item | Count |
| :----- | ----: |
| X-Wing | 1 |
| Y-Wing | 2 |
| A-Wing | 3 |
```
| Item | Count |
| :----- | ----: |
| X-Wing | 1 |
| Y-Wing | 2 |
| A-Wing | 3 |
---
## Footnotes
Add a caret (^) and an identifier inside brackets \(\[\^1\]\). Identifiers can be numbers or words but can't contain spaces or tabs.
```md
Here's a footnote, [^1] and here's another one. [^2]
[^1]: This is the first footnote.
[^2]: This is the second footnote.
```
Here's a footnote, [^1] and here's another one. [^2]
[^1]: This is the first footnote.
[^2]: This is the second footnote.
See the bottom of this page to view the footnotes.
---
## Code
To denote a word or phrase as code, enclose it in backticks (`).
```md
`package.json`
```
`package.json`
---
## Code Blocks
Denote a code block by wrapping a section of valid code in triple backticks (`). To enable syntax highlighting, type the shorthand symbol for the language after the first three backticks. [Reference for shorthand symbols](https://shiki.style/languages).
````
```js
function hello() {
console.log("hello world");
}
```
````
```js
function hello() {
console.log('hello world')
}
```
---
## Conclusion
Refer to [markdownguide.org](https://www.markdownguide.org/) for best practices as well as extended syntax.
---

Binary file not shown.

Before

Width:  |  Height:  |  Size: 203 KiB

View file

@ -1,10 +0,0 @@
---
---
<button
onclick="alert(`You clicked the button!`)"
class="border border-black/10 p-2 transition-colors duration-300 ease-in-out hover:bg-black/5 dark:border-white/10 dark:hover:bg-white/10"
>
Relative Button
</button>

View file

@ -1,71 +0,0 @@
---
title: '[Old] MDX syntax guide'
description: 'Use interactive components in Markdown.'
date: '2024-03-16'
---
import Callout from '@/components/Callout.astro'
---
MDX is an extension of Markdown with the ability to import `.astro`,
`.jsx`, `.tsx` and other framework components you have integrated.
This guide covers the basics of MDX syntax and how to use it, as well as a few examples.
## Example 1
Importing a component from the `/components` directory.
This component accepts a Javascript date object and format it as a string.
```astro
import DateComp from "../../../components/FormattedDate.astro";
<DateComp date={new Date()} />
```
import FormattedDate from '../../../components/FormattedDate.astro'
<FormattedDate date={new Date()} />
---
## Example 2
Importing a component from a relative path to your content.
This component displays an alert when the button is clicked.
```astro
import RelativeComponent from "./component.astro";
<RelativeComponent />
```
import RelativeComponent from './component.astro'
<RelativeComponent />
---
By default Micro has zero frameworks installed. If you install a framework, components of that framework can be used in MDX files.
<Callout>
Don't forget to use [client
directives](https://docs.astro.build/en/reference/directives-reference/#client-directives)
to make framework components interactive.
</Callout>
```astro
<ReactComponent client:load />
```
---
## More Links
- [MDX Syntax Documentation](https://mdxjs.com/docs/what-is-mdx)
- [Astro Framework Integrations](https://docs.astro.build/en/guides/integrations-guide)
- [Astro Usage Documentation](https://docs.astro.build/en/guides/markdown-content/#markdown-and-mdx-pages)
- [Client Directives](https://docs.astro.build/en/reference/directives-reference/#client-directives)

View file

@ -1,7 +0,0 @@
---
title: '[Old] Year sorting example'
description: 'Nano groups posts by year.'
date: '2023-12-31'
---
This post is to demonstrate the year sorting capabilities.

View file

@ -1,10 +0,0 @@
---
title: '[Old] Draft example'
description: 'Setting draft flag to true to hide this post.'
date: '2022-12-31'
draft: false
---
This post also demonstrates the year sorting capabilities.
Try setting this file's metadata to `draft: true`.

View file

@ -1,10 +0,0 @@
---
title: '[Old] Chronological pagination example'
description: 'Pagination works regardless of folder name.'
date: '2024-03-21'
draft: false
---
This post should show up in proper chronological order even though its folder comes last in the `content/blog` directory.
The `Previous Post` and `Next Post` buttons under each blog post should also keep the proper chronological order, based on the frontmatter `date` field.

View file

@ -4,7 +4,6 @@ import Header from '@components/Header.astro'
import Footer from '@components/Footer.astro' import Footer from '@components/Footer.astro'
import { SITE } from '@consts' import { SITE } from '@consts'
import '../styles/katex.css' import '../styles/katex.css'
import { ViewTransitions } from 'astro:transitions'
type Props = { type Props = {
title: string title: string
@ -18,10 +17,9 @@ const { title, description } = Astro.props
<html lang="en"> <html lang="en">
<head> <head>
<Head title={`${title} | ${SITE.TITLE}`} description={description} /> <Head title={`${title} | ${SITE.TITLE}`} description={description} />
<ViewTransitions />
</head> </head>
<body <body
class="box-border flex h-fit min-h-screen flex-col px-4 font-sans antialiased" class="box-border flex h-fit min-h-screen flex-col px-4 font-sans bg-background text-foreground antialiased"
> >
<Header /> <Header />
<main class="flex-grow"> <main class="flex-grow">

View file

@ -9,7 +9,7 @@ import { SITE } from '@consts'
<Layout title="404" description={SITE.DESCRIPTION}> <Layout title="404" description={SITE.DESCRIPTION}>
<Container> <Container>
<div class="mt-16 grid place-items-center gap-3"> <div class="mt-16 grid place-items-center gap-3">
<h4 class="text-2xl font-semibold text-black dark:text-white"> <h4 class="text-2xl font-semibold">
404: Page not found 404: Page not found
</h4> </h4>
<span> <span>

View file

@ -8,7 +8,7 @@ import { Image } from 'astro:assets'
<Layout title="About" description="About"> <Layout title="About" description="About">
<Container> <Container>
<div class="space-y-10"> <div class="space-y-10">
<div class="font-semibold text-black dark:text-white">About</div> <div class="font-semibold">About</div>
<section class="not-prose flex flex-col gap-4 text-justify"> <section class="not-prose flex flex-col gap-4 text-justify">
<p class="text-justify"> <p class="text-justify">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores porro Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolores porro
@ -26,7 +26,7 @@ import { Image } from 'astro:assets'
<div class="flex flex-col justify-center md:flex-row"> <div class="flex flex-col justify-center md:flex-row">
<div class="my-10 text-center"> <div class="my-10 text-center">
<div <div
class="h-[250px] w-[350px] -rotate-6 overflow-hidden rounded-xl bg-neutral-300 object-cover" class="h-[250px] w-[350px] -rotate-6 overflow-hidden rounded-xl object-cover"
> >
<Image <Image
src={'/astro-nano.png'} src={'/astro-nano.png'}
@ -42,7 +42,7 @@ import { Image } from 'astro:assets'
</div> </div>
<div class="mx-10 my-10 text-center"> <div class="mx-10 my-10 text-center">
<div <div
class="mx-auto h-[250px] w-[150px] rotate-6 rounded-xl bg-neutral-300 object-cover sm:ml-auto" class="mx-auto h-[250px] w-[150px] rotate-6 rounded-xl object-cover sm:ml-auto"
> >
<Image <Image
src={'/astro-micro.jpg'} src={'/astro-micro.jpg'}

View file

@ -62,7 +62,7 @@ const { Content, headings } = await post.render()
{readingTime(post.body)} {readingTime(post.body)}
</div> </div>
</div> </div>
<h1 class="text-4xl font-semibold text-black dark:text-white"> <h1 class="text-4xl font-semibold">
{post.data.title} {post.data.title}
</h1> </h1>
<div class="font-base text-sm"> <div class="font-base text-sm">
@ -72,7 +72,7 @@ const { Content, headings } = await post.render()
<div class="my-1 inline-block"> <div class="my-1 inline-block">
<a <a
href={`/tags/${tag}`} href={`/tags/${tag}`}
class="mx-1 rounded-full bg-orange-300 px-2 py-1 transition-colors duration-300 ease-in-out hover:bg-cyan-200 dark:bg-orange-500 dark:hover:bg-cyan-500" class="mx-1 rounded-full px-2 py-1 transition-colors duration-300 ease-in-out"
> >
#{tag} #{tag}
</a> </a>
@ -85,7 +85,7 @@ const { Content, headings } = await post.render()
</div> </div>
</div> </div>
{headings.length > 0 && <TableOfContents headings={headings} />} {headings.length > 0 && <TableOfContents headings={headings} />}
<article class="animate"> <article class="prose prose-neutral max-w-full dark:prose-invert prose-img:mx-auto prose-img:my-auto">
<Content /> <Content />
<div class="mt-24"> <div class="mt-24">
<PostNavigation prevPost={prevPost} nextPost={nextPost} /> <PostNavigation prevPost={prevPost} nextPost={nextPost} />

View file

@ -31,7 +31,7 @@ const years = Object.keys(posts).sort((a, b) => parseInt(b) - parseInt(a))
{ {
years.map((year) => ( years.map((year) => (
<section class="space-y-4"> <section class="space-y-4">
<div class="font-semibold text-black dark:text-white">{year}</div> <div class="font-semibold">{year}</div>
<div> <div>
<ul class="not-prose flex flex-col gap-4"> <ul class="not-prose flex flex-col gap-4">
{posts[year].map((post) => ( {posts[year].map((post) => (

View file

@ -7,6 +7,7 @@ import Link from '@components/Link.astro'
import { getCollection } from 'astro:content' import { getCollection } from 'astro:content'
import type { CollectionEntry } from 'astro:content' import type { CollectionEntry } from 'astro:content'
import SocialIcons from '@components/SocialIcons.astro' import SocialIcons from '@components/SocialIcons.astro'
import { ModeToggle } from '@components/ui/mode-toggle'
const blog = (await getCollection('blog')) const blog = (await getCollection('blog'))
.filter((post) => !post.data.draft) .filter((post) => !post.data.draft)
@ -17,8 +18,9 @@ const blog = (await getCollection('blog'))
<Layout title="Home" description="Home"> <Layout title="Home" description="Home">
<Container> <Container>
<section class="space-y-6"> <section class="space-y-6">
<ModeToggle client:load />
<div class="flex flex-wrap items-center justify-between gap-y-2"> <div class="flex flex-wrap items-center justify-between gap-y-2">
<h2 class="font-semibold text-black dark:text-white">Latest posts</h2> <h2 class="font-semibold">Latest posts</h2>
<Link href="/blog"> See all posts </Link> <Link href="/blog"> See all posts </Link>
</div> </div>
<ul class="not-prose flex flex-col gap-4"> <ul class="not-prose flex flex-col gap-4">

View file

@ -36,9 +36,9 @@ export async function getStaticPaths() {
> >
<Container> <Container>
<div class="space-y-10"> <div class="space-y-10">
<div class="font-semibold text-black dark:text-white"> <div class="font-semibold">
Tag: <span Tag: <span
class="mx-2 rounded-full bg-orange-300 px-3 py-2 transition-colors duration-300 ease-in-out hover:bg-cyan-200 dark:bg-orange-500 dark:hover:bg-cyan-500" class="mx-2 rounded-full px-3 py-2 transition-colors duration-300 ease-in-out"
>#{tag}</span >#{tag}</span
> >
</div> </div>

View file

@ -14,14 +14,14 @@ const tags = blog
<Layout title="Tags" description="Tags"> <Layout title="Tags" description="Tags">
<Container> <Container>
<div class="space-y-10"> <div class="space-y-10">
<div class="font-semibold text-black dark:text-white">Tags</div> <div class="font-semibold">Tags</div>
<ul class="flex flex-wrap"> <ul class="flex flex-wrap">
{ {
tags.map((tag) => ( tags.map((tag) => (
<li class="my-3"> <li class="my-3">
<a <a
href={`/tags/${tag}`} href={`/tags/${tag}`}
class="mx-2 rounded-full bg-orange-300 px-3 py-2 transition-colors duration-300 ease-in-out hover:bg-cyan-200 dark:bg-orange-500 dark:hover:bg-cyan-500" class="mx-2 rounded-full px-3 py-2 transition-colors duration-300 ease-in-out"
> >
#{tag} #{tag}
</a> </a>

View file

@ -2,42 +2,6 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
article {
@apply prose prose-neutral max-w-full dark:prose-invert prose-img:mx-auto prose-img:my-auto;
@apply prose-headings:font-semibold;
@apply prose-headings:text-black prose-headings:dark:text-white;
}
@layer utilities {
article a {
@apply font-sans text-current underline underline-offset-[3px];
@apply decoration-black/30 dark:decoration-white/30;
@apply transition-colors duration-300 ease-in-out;
}
article a:hover {
@apply text-black dark:text-white;
@apply decoration-black/50 dark:decoration-white/50;
}
}
.scroll_bar {
scrollbar-width: thin;
scrollbar-color: #1e293b #0f172a;
}
html #back-to-top {
@apply pointer-events-none opacity-0;
}
html.scrolled #back-to-top {
@apply pointer-events-auto opacity-100;
}
/* shiki config */
pre {
@apply border border-black/15 py-5 dark:border-white/20;
}
:root { :root {
--astro-code-color-text: #09090b; --astro-code-color-text: #09090b;
--astro-code-color-background: #fafafa; --astro-code-color-background: #fafafa;
@ -66,19 +30,6 @@ pre {
--astro-code-token-link: #8d85ff; --astro-code-token-link: #8d85ff;
} }
/* copy code button on codeblocks */
.copy-code {
@apply absolute right-3 top-3 grid size-9 place-content-center rounded border border-black/15 bg-neutral-100 text-center duration-300 ease-in-out dark:border-white/20 dark:bg-neutral-900;
}
.copy-code:hover {
@apply bg-[#E9E9E9] transition-colors dark:bg-[#232323];
}
.copy-code:active {
@apply scale-90 transition-transform;
}
@layer base { @layer base {
:root { :root {
--background: 0 0% 100%; --background: 0 0% 100%;
@ -139,4 +90,18 @@ pre {
* { * {
@apply border-border; @apply border-border;
} }
html {
color-scheme: light;
}
html.dark {
color-scheme: dark;
}
}
@layer utilities {
.disable-transitions * {
@apply !transition-none;
}
} }

View file

@ -2,7 +2,7 @@ import type { Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss/defaultTheme' import defaultTheme from 'tailwindcss/defaultTheme'
const config: Config = { const config: Config = {
darkMode: ['class', 'class'], darkMode: ['selector'],
content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'], content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
theme: { theme: {
extend: { extend: {