Compare commits
5 Commits
feature/ui
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 4c5c7d7e31 | |||
| af7a72d174 | |||
| abb694bf5b | |||
| ae1cabeb97 | |||
| b30b77e6fd |
@@ -2,7 +2,7 @@ name: Build and Deploy DAVE | DMGs Site
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ main ]
|
branches: [main]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
deploy:
|
deploy:
|
||||||
|
|||||||
33
.idea/inspectionProfiles/Project_Default.xml
generated
33
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,39 +1,6 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
<component name="InspectionProjectProfileManager">
|
||||||
<profile version="1.0">
|
<profile version="1.0">
|
||||||
<option name="myName" value="Project Default" />
|
<option name="myName" value="Project Default" />
|
||||||
<inspection_tool class="CssDeprecatedValue" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidAtRule" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidCharsetRule" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidCustomPropertyAtRuleDeclaration" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidCustomPropertyAtRuleName" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidFunction" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidHtmlTagReference" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidImport" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidMediaFeature" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssInvalidPropertyValue" enabled="false" level="WARNING" enabled_by_default="false" editorAttributes="WARNING_ATTRIBUTES" />
|
|
||||||
<inspection_tool class="CssInvalidPseudoSelector" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssMissingComma" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssNegativeValue" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssNoGenericFontName" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssNonIntegerLengthInPixels" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssOverwrittenProperties" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssRedundantUnit" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssReplaceWithShorthandSafely" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssReplaceWithShorthandUnsafely" enabled="false" level="INFORMATION" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssUnknownProperty" enabled="false" level="WARNING" enabled_by_default="false">
|
|
||||||
<option name="myCustomPropertiesEnabled" value="false" />
|
|
||||||
<option name="myIgnoreVendorSpecificProperties" value="false" />
|
|
||||||
<option name="myCustomPropertiesList">
|
|
||||||
<value>
|
|
||||||
<list size="0" />
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
</inspection_tool>
|
|
||||||
<inspection_tool class="CssUnknownTarget" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssUnknownUnit" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssUnresolvedClassInComposesRule" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssUnresolvedCustomProperty" enabled="false" level="ERROR" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="CssUnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
|
|
||||||
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
|
<inspection_tool class="Stylelint" enabled="true" level="ERROR" enabled_by_default="true" />
|
||||||
</profile>
|
</profile>
|
||||||
|
|||||||
6
.idea/stylesheetLinters/stylelint.xml
generated
6
.idea/stylesheetLinters/stylelint.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="StylelintConfiguration">
|
|
||||||
<option name="fix-on-save" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
{
|
|
||||||
"items": [
|
|
||||||
{
|
|
||||||
"name": "Metatron",
|
|
||||||
"path": "/meta",
|
|
||||||
"gridPosition": "area_1",
|
|
||||||
"variant": "meta",
|
|
||||||
"sublinks": {
|
|
||||||
"discriminant": false
|
|
||||||
},
|
|
||||||
"subtitle": {
|
|
||||||
"discriminant": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Kitchensink",
|
|
||||||
"path": "/",
|
|
||||||
"gridPosition": "area_2",
|
|
||||||
"variant": "kitchensink",
|
|
||||||
"sublinks": {
|
|
||||||
"discriminant": true,
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
"name": "The Pomarj",
|
|
||||||
"path": "/kitchensink/the-pomarj"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Burning Pavis",
|
|
||||||
"path": "/kitchensink/burning-pavis"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "SLA Armies",
|
|
||||||
"path": "/kitchensink/sla-armies"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"subtitle": {
|
|
||||||
"discriminant": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "AWQ",
|
|
||||||
"path": "/awq",
|
|
||||||
"gridPosition": "area_3",
|
|
||||||
"variant": "awq",
|
|
||||||
"sublinks": {
|
|
||||||
"discriminant": true,
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
"name": "The Crunch",
|
|
||||||
"path": "/awq/core-rules"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Sigmar's Heirs",
|
|
||||||
"path": "/awq/character"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Armory",
|
|
||||||
"path": "/awq/equipment"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "The Winds of Magic",
|
|
||||||
"path": "/awq/magic"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Beastiary",
|
|
||||||
"path": "/awq/bestiary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Duveldal",
|
|
||||||
"path": "/awq/pregens"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Plundered Vaults",
|
|
||||||
"path": "/awq/expansions"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Tools",
|
|
||||||
"path": "/awq/tools"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"subtitle": {
|
|
||||||
"discriminant": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Worldburner",
|
|
||||||
"path": "/worldburner",
|
|
||||||
"gridPosition": "area_4",
|
|
||||||
"variant": "worldburner",
|
|
||||||
"sublinks": {
|
|
||||||
"discriminant": true,
|
|
||||||
"value": [
|
|
||||||
{
|
|
||||||
"name": "Burning Lands",
|
|
||||||
"path": "/worldburner/geography"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Burning People",
|
|
||||||
"path": "/worldburner/cultures"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Burning Faiths",
|
|
||||||
"path": "/worldburner/religion"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Burning Witches",
|
|
||||||
"path": "/worldburner/magic"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Burning Realms",
|
|
||||||
"path": "/worldburner/states"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"subtitle": {
|
|
||||||
"discriminant": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Chainbreaker",
|
|
||||||
"path": "/chainbreaker",
|
|
||||||
"gridPosition": "area_5",
|
|
||||||
"variant": "chainbreaker",
|
|
||||||
"background": "/images/categories/items/4/background.png",
|
|
||||||
"sublinks": {
|
|
||||||
"discriminant": false
|
|
||||||
},
|
|
||||||
"subtitle": {
|
|
||||||
"discriminant": true,
|
|
||||||
"value": {
|
|
||||||
"content": "Spear & Animism",
|
|
||||||
"divider": {
|
|
||||||
"discriminant": true,
|
|
||||||
"value": "⎊"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
import { config } from '@keystatic/core';
|
import { config } from '@keystatic/core';
|
||||||
|
|
||||||
import navigation from '@/keystatic/singletons/navigation';
|
import AuthorsCollection from '@/keystatic/collections/taxonomy/authors';
|
||||||
|
import TagsCollection from '@/keystatic/collections/taxonomy/tags';
|
||||||
|
|
||||||
export default config({
|
export default config({
|
||||||
storage: {
|
storage: {
|
||||||
kind: 'local',
|
kind: 'local',
|
||||||
},
|
},
|
||||||
collections: {},
|
collections: {
|
||||||
singletons: { navigation },
|
authors: AuthorsCollection,
|
||||||
|
tags: TagsCollection,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
17
package.json
17
package.json
@@ -13,14 +13,15 @@
|
|||||||
"@keystatic/core": "^0.5.48",
|
"@keystatic/core": "^0.5.48",
|
||||||
"@keystatic/next": "^5.0.4",
|
"@keystatic/next": "^5.0.4",
|
||||||
"@markdoc/markdoc": "^0.5.4",
|
"@markdoc/markdoc": "^0.5.4",
|
||||||
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"next": "15.5.3",
|
"next": "15.5.3",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
"react": "19.1.0",
|
"react": "19.1.0",
|
||||||
"react-dom": "19.1.0"
|
"react-dom": "19.1.0",
|
||||||
|
"tailwindcss": "^4.1.13"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@csstools/postcss-global-data": "^3.1.0",
|
|
||||||
"@eslint/eslintrc": "^3",
|
"@eslint/eslintrc": "^3",
|
||||||
"@fullhuman/postcss-purgecss": "^7.0.2",
|
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
@@ -30,20 +31,12 @@
|
|||||||
"eslint-config-next": "15.5.3",
|
"eslint-config-next": "15.5.3",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"eslint-plugin-mdx": "^3.6.2",
|
"eslint-plugin-mdx": "^3.6.2",
|
||||||
"glob-all": "^3.3.1",
|
|
||||||
"postcss": "^8.5.6",
|
|
||||||
"postcss-easings": "^4.0.0",
|
|
||||||
"postcss-functions": "^4.0.2",
|
|
||||||
"postcss-import": "^16.1.1",
|
|
||||||
"postcss-mixins": "^12.1.2",
|
|
||||||
"postcss-nesting": "^13.0.2",
|
|
||||||
"postcss-preset-env": "^10.3.1",
|
|
||||||
"postcss-utilities": "^0.8.4",
|
|
||||||
"prettier": "^3.6.2",
|
"prettier": "^3.6.2",
|
||||||
"stylelint": "^16.24.0",
|
"stylelint": "^16.24.0",
|
||||||
"stylelint-config-clean-order": "^7.0.0",
|
"stylelint-config-clean-order": "^7.0.0",
|
||||||
"stylelint-config-html": "^1.1.0",
|
"stylelint-config-html": "^1.1.0",
|
||||||
"stylelint-config-standard": "^39.0.0",
|
"stylelint-config-standard": "^39.0.0",
|
||||||
|
"stylelint-config-tailwindcss": "^1.0.0",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6882
pnpm-lock.yaml
generated
6882
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,54 +1,6 @@
|
|||||||
// postcss.config.js
|
const config = {
|
||||||
import { purgeCSSPlugin } from '@fullhuman/postcss-purgecss';
|
plugins: {
|
||||||
import glob from 'glob-all';
|
'@tailwindcss/postcss': {},
|
||||||
import path from 'path';
|
|
||||||
import postcssGlobalData from '@csstools/postcss-global-data';
|
|
||||||
import postcssEasing from 'postcss-easings';
|
|
||||||
import postcssImport from 'postcss-import';
|
|
||||||
import postcssMixins from 'postcss-mixins';
|
|
||||||
import postcssNesting from 'postcss-nesting';
|
|
||||||
import postcssPresetEnv from 'postcss-preset-env';
|
|
||||||
import postcssUtilities from 'postcss-utilities';
|
|
||||||
import postcssFunctions from 'postcss-functions';
|
|
||||||
import customFunctions from './src/lib/postcss/functions';
|
|
||||||
|
|
||||||
const plugins = [
|
|
||||||
postcssGlobalData({
|
|
||||||
files: ['./src/styles/globals/custom-media.css'],
|
|
||||||
}),
|
|
||||||
postcssMixins({
|
|
||||||
mixinsDir: './src/styles/mixins/',
|
|
||||||
}),
|
|
||||||
postcssImport(),
|
|
||||||
postcssPresetEnv({
|
|
||||||
stage: 1,
|
|
||||||
features: {
|
|
||||||
'nesting-rules': false,
|
|
||||||
'media-query-ranges': {
|
|
||||||
preserve: true,
|
|
||||||
},
|
},
|
||||||
},
|
|
||||||
}),
|
|
||||||
postcssEasing(),
|
|
||||||
postcssUtilities(),
|
|
||||||
postcssNesting(),
|
|
||||||
postcssFunctions({
|
|
||||||
functions: customFunctions,
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === 'production') {
|
|
||||||
plugins.push(
|
|
||||||
purgeCSSPlugin({
|
|
||||||
content: glob.sync([
|
|
||||||
path.join(process.cwd(), 'src/**/*.{js,jsx,ts,tsx,css}'),
|
|
||||||
path.join(process.cwd(), 'content/**/*.{md,mdx}'),
|
|
||||||
]),
|
|
||||||
safelist: ['html', 'body'],
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
|
||||||
plugins,
|
|
||||||
};
|
};
|
||||||
|
export default config;
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 5.9 MiB |
@@ -1,15 +1,5 @@
|
|||||||
import { MenuProvider } from '@/contexts/MenuContext';
|
|
||||||
import PageHeader from '@/components/Page/Header';
|
|
||||||
import PageMenu from '@/components/Page/Menu';
|
|
||||||
|
|
||||||
export default function SiteLayout({
|
export default function SiteLayout({
|
||||||
children,
|
children,
|
||||||
}: Readonly<{ children: React.ReactNode }>) {
|
}: Readonly<{ children: React.ReactNode }>) {
|
||||||
return (
|
return <main>{children}</main>;
|
||||||
<MenuProvider>
|
|
||||||
<PageHeader />
|
|
||||||
<PageMenu />
|
|
||||||
<main>{children}</main>
|
|
||||||
</MenuProvider>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
.wrapper {
|
|
||||||
@mixin responsive-wrapper;
|
|
||||||
|
|
||||||
& body {
|
|
||||||
margin: 0;
|
|
||||||
padding: 2rem;
|
|
||||||
|
|
||||||
font-family: monospace;
|
|
||||||
color: #1a1a1d;
|
|
||||||
|
|
||||||
background: #f7f9fb;
|
|
||||||
}
|
|
||||||
|
|
||||||
& h1 {
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
font-weight: 900;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
||||||
gap: 2rem;
|
|
||||||
margin-bottom: 3rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .demoCard {
|
|
||||||
border: 3px solid #1a1a1d;
|
|
||||||
background: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .demoTitle {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
|
|
||||||
font-size: 0.875rem;
|
|
||||||
font-weight: bold;
|
|
||||||
color: white;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.05em;
|
|
||||||
|
|
||||||
background: #1a1a1d;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .imageContainer {
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .demoImage {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
object-fit: cover;
|
|
||||||
filter: grayscale(100) contrast(150) brightness(100);
|
|
||||||
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .instructions {
|
|
||||||
margin-top: 2rem;
|
|
||||||
padding: 1rem;
|
|
||||||
|
|
||||||
font-family: monospace;
|
|
||||||
color: white;
|
|
||||||
|
|
||||||
background: #1a1a1d;
|
|
||||||
}
|
|
||||||
|
|
||||||
& .instructions h2 {
|
|
||||||
margin-top: 0;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 0.1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,493 +1,7 @@
|
|||||||
import styles from './page.module.css';
|
|
||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
return (
|
return (
|
||||||
<div className={styles.wrapper}>
|
<div className="text-3xl font-bold underline">
|
||||||
<h1>
|
Do not let us die in the dark night of this cold winter, Dave
|
||||||
DAVE! DAVE! Do Not Let Us Die In The Dark Night Of This Cold Winter!
|
|
||||||
</h1>
|
|
||||||
<h2>Background / Image effects</h2>
|
|
||||||
<div className={styles.grid}>
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Overexposure Blast</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-overexposure`}
|
|
||||||
src="https://images.pexels.com/photos/1096925/pexels-photo-1096925.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Contrast Slam</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-contrastslam`}
|
|
||||||
src="https://images.pexels.com/photos/119809/pexels-photo-119809.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Colorbleed</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-colorbleed`}
|
|
||||||
src="https://images.pexels.com/photos/12924931/pexels-photo-12924931.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Film Burn</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-filmburn`}
|
|
||||||
src="https://images.pexels.com/photos/1031357/pexels-photo-1031357.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Photocopier Malfunction</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-malfunction`}
|
|
||||||
src="https://images.pexels.com/photos/3054252/pexels-photo-3054252.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Toner Starvation</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-tonerstarvation`}
|
|
||||||
src="https://images.pexels.com/photos/3822728/pexels-photo-3822728.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Digital Corruption</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-corruption`}
|
|
||||||
src="https://images.pexels.com/photos/220793/pexels-photo-220793.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={`${styles.demoCard}`}>
|
|
||||||
<h3 className={styles.demoTitle}>Stark Flash</h3>
|
|
||||||
<div className={styles.imageContainer}>
|
|
||||||
<img
|
|
||||||
className={`${styles.demoImage} anim-starkflash`}
|
|
||||||
src="https://images.pexels.com/photos/13744675/pexels-photo-13744675.jpeg"
|
|
||||||
alt="Demo"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.instructions}>
|
|
||||||
<h2>Instructions</h2>
|
|
||||||
<p>
|
|
||||||
Hover over each image to see the effect. These are designed to work
|
|
||||||
with your base filter:
|
|
||||||
</p>
|
|
||||||
<code>filter: grayscale(1) contrast(150%) brightness(120%)</code>
|
|
||||||
<p>
|
|
||||||
You can replace the demo images with your own by changing the src
|
|
||||||
attributes. All effects use stepped animations or sharp transitions to
|
|
||||||
maintain that industrial, non-digital feel.
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
The effects range from subtle (Contrast Slam) to more dramatic
|
|
||||||
(Digital Corruption). Choose based on how aggressive you want the
|
|
||||||
interaction to feel.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<h2>Link Effects</h2>
|
|
||||||
<div className={styles.grid}>
|
|
||||||
{/* Your Ideas */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Strikethrough Mark (Marker)</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-strikethroughmarker">
|
|
||||||
strikethrough link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Strikethrough Mark (Industrial)</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-strikethroughindustrial">
|
|
||||||
strikethrough link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Marker Highlight [Industrial]</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-markerhighlightindustrial">
|
|
||||||
marker highlight link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Stamping/Punching Effects */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Label Maker</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-labelmaker">
|
|
||||||
label maker link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Rubber Stamp</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-rubberstamp">
|
|
||||||
rubber stamp link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Industrial/Mechanical */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Press/Stamp</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-pressstamp">
|
|
||||||
pressed link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Typewriter Underline</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-typewriter">
|
|
||||||
typewriter link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Hard Invert</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-hardInvert">
|
|
||||||
hard invert link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Marking/Annotation */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Bracket Annotation</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-pointer">
|
|
||||||
bracket link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Corner Box</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-cornerbox">
|
|
||||||
corner box link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Glitch/Digital */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Character Glitch</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-characterglitch">
|
|
||||||
glitch link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Pixel Shift</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-pixelshift">
|
|
||||||
shifting link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Extra Ideas */}
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>Redacted/Censored</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with a{' '}
|
|
||||||
<a href="#" className="anim-redacted">
|
|
||||||
redacted link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className={styles.demoCard}>
|
|
||||||
<h3 className={styles.demoTitle}>X-Ray/Negative</h3>
|
|
||||||
<p>
|
|
||||||
This is some text with an{' '}
|
|
||||||
<a href="#" className="anim-xray">
|
|
||||||
x-ray link
|
|
||||||
</a>{' '}
|
|
||||||
in the middle of it.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="content">
|
|
||||||
<h1>
|
|
||||||
Successful Isildur's brink again throttle flank tightening splash.
|
|
||||||
</h1>
|
|
||||||
<p>
|
|
||||||
Help illusion embrace liquor tightening intelligence Maggot's whips
|
|
||||||
bit forests. 17 sing impassable helps Southrons beheading. What's the
|
|
||||||
Elvish word for 'friend'?
|
|
||||||
</p>
|
|
||||||
<h2>Give Hobbitses lend yours lads picking uniting sometime.</h2>
|
|
||||||
<p>
|
|
||||||
Inferno shaken skin undo wars close circles verse suck Dwarves. I gave
|
|
||||||
you the chance of aiding me willingly, but you have elected the way of
|
|
||||||
pain! Precautions tower tied Rivendell everyone agents wouldn't?
|
|
||||||
</p>
|
|
||||||
<h3>Doorway Mithrandir clearing wielder strengths floor?</h3>
|
|
||||||
<p>
|
|
||||||
Pillaged pointy-eared mix charm Grond confounded able-bodied tact
|
|
||||||
glimpse instruction open dear. Suffering powerful capable gulls
|
|
||||||
famousest stroke breathes Bilbo squeaked pace chances. Let the
|
|
||||||
Ring-bearer decide.
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>Mirkwood.</li>
|
|
||||||
<li>Tom.</li>
|
|
||||||
<li>Bilbo's.</li>
|
|
||||||
<li>Gandalf's.</li>
|
|
||||||
<li>Dwarvish.</li>
|
|
||||||
</ul>
|
|
||||||
<ul>
|
|
||||||
<li>Queen wants Oin loose heads decay piety!</li>
|
|
||||||
<li>Large happening arrived owes legends wit war bled Durin's.</li>
|
|
||||||
<li>
|
|
||||||
Pursuit exactly during relief mission meats cause Noldorin ablaze
|
|
||||||
tracked.
|
|
||||||
</li>
|
|
||||||
<li>Darken knife midday meat Goblinses.</li>
|
|
||||||
<li>
|
|
||||||
Your Rabble-rousers greatest could beast thirty-four t wizards
|
|
||||||
slumbers reforge.
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>Late vagabond knowing Ent legends there flattened cultured?</h3>
|
|
||||||
<p>
|
|
||||||
Swords are no more use here. Deny Chubbs restored. Scare rebuild
|
|
||||||
Argonath tracked day's large.
|
|
||||||
</p>
|
|
||||||
<ol>
|
|
||||||
<li>Easterlings!</li>
|
|
||||||
<li>Bill.</li>
|
|
||||||
<li>Dúnedain!</li>
|
|
||||||
<li>Gandalf.</li>
|
|
||||||
<li>Orcrist.</li>
|
|
||||||
</ol>
|
|
||||||
<ol>
|
|
||||||
<li>Answers feelings Elrond conjurer runs.</li>
|
|
||||||
<li>Sul nudge powerless jelly dumping hair grows log forgave?</li>
|
|
||||||
<li>
|
|
||||||
Retaken succumbed funeral courtyard Glóin incident mere somewhere
|
|
||||||
commander assistance?
|
|
||||||
</li>
|
|
||||||
<li>Bore outrun stead fight Athelas guardroom willing contains.</li>
|
|
||||||
<li>Hunted Angmar wager noose arguing?</li>
|
|
||||||
</ol>
|
|
||||||
<h3>Elros next own wisp whence cakehole right!</h3>
|
|
||||||
<p>
|
|
||||||
Thank hid its lessened lined tells prefers were Stone-Giants thousand
|
|
||||||
troubles. Earendil staff pines bog finest mushroom consumption.
|
|
||||||
Mistaken streaming fates paths arts puppet Barad-dûr uniting? You
|
|
||||||
shall not pass!
|
|
||||||
</p>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th></th>
|
|
||||||
<th>Ales</th>
|
|
||||||
<th>Deeply</th>
|
|
||||||
<th>Mortality</th>
|
|
||||||
<th>Open</th>
|
|
||||||
<th>Single-handedly</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>Band</td>
|
|
||||||
<td>appeared</td>
|
|
||||||
<td>waited</td>
|
|
||||||
<td>whose</td>
|
|
||||||
<td>plate</td>
|
|
||||||
<td>marshaling</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Meat</td>
|
|
||||||
<td>nest</td>
|
|
||||||
<td>thatched</td>
|
|
||||||
<td>rallying</td>
|
|
||||||
<td>claimed</td>
|
|
||||||
<td>hungers</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Mouse</td>
|
|
||||||
<td>also</td>
|
|
||||||
<td>birdses</td>
|
|
||||||
<td>moons</td>
|
|
||||||
<td>strain</td>
|
|
||||||
<td>brightest</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Hate</td>
|
|
||||||
<td>different</td>
|
|
||||||
<td>arrangements</td>
|
|
||||||
<td>chiefest</td>
|
|
||||||
<td>think</td>
|
|
||||||
<td>try</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Something's</td>
|
|
||||||
<td>task</td>
|
|
||||||
<td>here's</td>
|
|
||||||
<td>decent</td>
|
|
||||||
<td>someone</td>
|
|
||||||
<td>uses</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Shirt</td>
|
|
||||||
<td>tonight</td>
|
|
||||||
<td>bay</td>
|
|
||||||
<td>beautifully</td>
|
|
||||||
<td>tad</td>
|
|
||||||
<td>cloaks</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td>revenge</td>
|
|
||||||
<td>teaching</td>
|
|
||||||
<td>mischief</td>
|
|
||||||
<td>shores</td>
|
|
||||||
<td>dreams</td>
|
|
||||||
<td>tested</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
</table>
|
|
||||||
<h4>Stage dishcloth 20 horses Tooks souls crawl crime.</h4>
|
|
||||||
<p>
|
|
||||||
Approve Sul wilderness grave embellishment greatly over these rack
|
|
||||||
struggle. End ringing bell Anor halls pairs thirst fortress curtain
|
|
||||||
cleared? Dwelt language 1296 Underhill nasty. I gave you the chance of
|
|
||||||
aiding me willingly, but you have elected the way of pain!
|
|
||||||
</p>
|
|
||||||
<blockquote>
|
|
||||||
<p>You are full of surprises, Master Baggins.</p>
|
|
||||||
<footer>
|
|
||||||
—Girion, <cite>warmongering appears</cite>
|
|
||||||
</footer>
|
|
||||||
</blockquote>
|
|
||||||
<h5>
|
|
||||||
Sung outscoring fingers Fundin reaction inquiries buggers deadliest.
|
|
||||||
</h5>
|
|
||||||
<p>
|
|
||||||
Mustn't powerless pierces Muil sorry crossing diamond brandy. Rip
|
|
||||||
rockets hinder Braga go had web ought sakes hail. A wizard is never
|
|
||||||
late, Frodo Baggins. Nor is he early. He arrives precisely when he
|
|
||||||
means to. Ashes tie Gamgee dicky!
|
|
||||||
</p>
|
|
||||||
<pre>
|
|
||||||
Rhudaur fancy tilled heart beggars. Dwarf nothing talked foot club.
|
|
||||||
Slaughtered flatten Hobbit journey's four-day?
|
|
||||||
</pre>
|
|
||||||
<h6>Pearl tact tomb bits Arwen Evenstar worry?</h6>
|
|
||||||
<p>
|
|
||||||
Times unspoiled <time>defenses</time> Silvan.{' '}
|
|
||||||
<del>Sigrid Pippin Gandalf</del> thin stubbornness noises easily
|
|
||||||
spread. Eldar warriors <code>won answered</code> filth yourself
|
|
||||||
pocket. Showing store consistency <kbd>M</kbd> crevice. Decision
|
|
||||||
feverfew <sup>giving</sup> Misty Mountain lord supplant. Gorgoroth{' '}
|
|
||||||
<dfn>load born fulfilled plenty</dfn> fates serpent. Doorstep Pippin's{' '}
|
|
||||||
<cite>pity bridge</cite> long weak weep? Brightest <abbr>Chubbs</abbr>{' '}
|
|
||||||
jewels understand. Somewhat Erebor <sub>noise</sub> squealing moved?
|
|
||||||
Pippin's <mark>feels overrun</mark> hours brown burns. <var>Anor</var>{' '}
|
|
||||||
turning pick prophecy. Surrounded <q>entered needlessly weary</q> vile
|
|
||||||
hmm Bagshot Row. Consent <ins>outwitted dotage slug</ins> Homely hear.
|
|
||||||
Parapet <strong>protected favored defied roam</strong> quiet Dori sick
|
|
||||||
bent. <samp>Homage store hurricane</samp> prove ferret Helm's Deep
|
|
||||||
lately? <small>Excellent regret fun often</small> returned Wood-elves
|
|
||||||
apocalypse. Théodred's rights rat drawing{' '}
|
|
||||||
<a>examine dared bygone residence deeply</a>.{' '}
|
|
||||||
<em>Greenway Girion Rohirrim</em> trammel waiting edge.
|
|
||||||
</p>
|
|
||||||
<hr />
|
|
||||||
<dl>
|
|
||||||
<dt>Turn</dt>
|
|
||||||
<dd>
|
|
||||||
Bare protuberance arrived forging funny salvage Cair except first
|
|
||||||
banners.
|
|
||||||
</dd>
|
|
||||||
<dt>Foes</dt>
|
|
||||||
<dd>Bore river large house shadows it's Tuckborough warn.</dd>
|
|
||||||
<dd>
|
|
||||||
Stirring Greenwood nest sapphire grant gob flagon famous mean!
|
|
||||||
</dd>
|
|
||||||
<dt>Unprepared</dt>
|
|
||||||
<dd>
|
|
||||||
Single-handed wriggling creatures lock canopy anytime horses defense
|
|
||||||
Hobbit's?
|
|
||||||
</dd>
|
|
||||||
<dd>
|
|
||||||
Nûmenor dungeons achieving encourage fretting dines believes
|
|
||||||
understand.
|
|
||||||
</dd>
|
|
||||||
<dd>Ease love shine legs wee harbor Udùn adventure tumble stays.</dd>
|
|
||||||
</dl>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1 @@
|
|||||||
@layer reset, tokens, base, layout, content, components, utilities, animations;
|
@import 'tailwindcss';
|
||||||
|
|
||||||
@import url("../styles/tokens.css");
|
|
||||||
@import url("../styles/globals/foundation.css");
|
|
||||||
@import url("../styles/globals/base.css");
|
|
||||||
@import url("../styles/globals/content.css");
|
|
||||||
|
|||||||
@@ -17,44 +17,42 @@ const blaka = Blaka({
|
|||||||
const iosevkaSlab = localFont({
|
const iosevkaSlab = localFont({
|
||||||
src: [
|
src: [
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSlabQp/IosevkaSlabQp-Regular.woff2',
|
path: '../fonts/IosevkaSlabQp/IosevkaSlabQp-Regular.woff2',
|
||||||
weight: '400',
|
weight: '400',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSlabQp/IosevkaSlabQp-Bold.woff2',
|
path: '../fonts/IosevkaSlabQp/IosevkaSlabQp-Bold.woff2',
|
||||||
weight: '700',
|
weight: '700',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSlabQp/IosevkaSlabQp-Heavy.woff2',
|
path: '../fonts/IosevkaSlabQp/IosevkaSlabQp-Heavy.woff2',
|
||||||
weight: '900',
|
weight: '900',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
variable: '--font-iosevka-slab',
|
variable: '--font-iosevka-slab',
|
||||||
display: 'swap',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const iosevkaMono = localFont({
|
const iosevkaSans = localFont({
|
||||||
src: [
|
src: [
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSansMono/IosevkaSansMono-Regular.woff2',
|
path: '../fonts/IosevkaSansMono/IosevkaSansMono-Regular.woff2',
|
||||||
weight: '400',
|
weight: '400',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSansMono/IosevkaSansMono-Bold.woff2',
|
path: '../fonts/IosevkaSansMono/IosevkaSansMono-Bold.woff2',
|
||||||
weight: '700',
|
weight: '700',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '../../public/fonts/IosevkaSansMono/IosevkaSansMono-Heavy.woff2',
|
path: '../fonts/IosevkaSansMono/IosevkaSansMono-Heavy.woff2',
|
||||||
weight: '900',
|
weight: '900',
|
||||||
style: 'normal',
|
style: 'normal',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
display: 'swap',
|
|
||||||
variable: '--font-iosevka-mono',
|
variable: '--font-iosevka-mono',
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -69,11 +67,12 @@ export default function RootLayout({
|
|||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html
|
<html lang="en">
|
||||||
lang="en"
|
<body
|
||||||
className={`${geistSans.variable} ${blaka.variable} ${iosevkaSlab.variable} ${iosevkaMono.variable}`}
|
className={`${geistSans.variable} ${blaka.variable} ${iosevkaSlab.variable} ${iosevkaSlab.variable} antialiased`}
|
||||||
>
|
>
|
||||||
<body>{children}</body>
|
{children}
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,77 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.header {
|
|
||||||
@mixin py var(--el-header-paddingY);
|
|
||||||
|
|
||||||
position: sticky;
|
|
||||||
z-index: 9;
|
|
||||||
top: 0;
|
|
||||||
|
|
||||||
width: var(--dim-full);
|
|
||||||
|
|
||||||
color: var(--color-text-inverse);
|
|
||||||
|
|
||||||
background-color: var(--color-surface-inverse);
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner {
|
|
||||||
@mixin responsive-wrapper;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
gap: var(--spacing-cozy);
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
|
|
||||||
font-size: var(--el-header-font-size);
|
|
||||||
line-height: var(--el-header-line-height);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.logo {
|
|
||||||
@mixin anim-txt-characterglitch;
|
|
||||||
|
|
||||||
font-family: var(--font-mono);
|
|
||||||
animation:
|
|
||||||
logo-pulse 5s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
transform: translate(0, 0);
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pagename {
|
|
||||||
font-family: var(--font-mono);
|
|
||||||
|
|
||||||
& .bracket {
|
|
||||||
color: var(--color-secondary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.menutoggle {
|
|
||||||
@mixin ml auto;
|
|
||||||
|
|
||||||
& button {
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: var(--font-mono);
|
|
||||||
transition: color 0.2s ease-out;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--color-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
transform: scale(0.95);
|
|
||||||
transition: transform 0.1s ease-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes logo-pulse {
|
|
||||||
0% { opacity: 1; }
|
|
||||||
25% { opacity: 0.66; }
|
|
||||||
50% { opacity: 0.33; }
|
|
||||||
75% { opacity: 0.66; }
|
|
||||||
100% { opacity: 1; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import { useMenu } from '@/contexts/MenuContext';
|
|
||||||
import styles from './Header.module.css';
|
|
||||||
|
|
||||||
export default function Header() {
|
|
||||||
const { isMenuOpen, closeMenu, openMenu, startClosing, resetClosing } =
|
|
||||||
useMenu();
|
|
||||||
|
|
||||||
const handleMenuToggle = () => {
|
|
||||||
if (isMenuOpen) {
|
|
||||||
startClosing();
|
|
||||||
setTimeout(() => {
|
|
||||||
closeMenu();
|
|
||||||
resetClosing();
|
|
||||||
}, 800);
|
|
||||||
} else {
|
|
||||||
openMenu();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<header className={styles.header}>
|
|
||||||
<div className={styles.inner}>
|
|
||||||
<div className={styles.logo}>
|
|
||||||
<Link href="/">◬</Link>
|
|
||||||
</div>
|
|
||||||
<div className={styles.pagename}>
|
|
||||||
<span>
|
|
||||||
dave <span className={styles.bracket}>[</span>dmg
|
|
||||||
<span className={styles.bracket}>]</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.menutoggle}>
|
|
||||||
<button
|
|
||||||
onClick={() => handleMenuToggle()}
|
|
||||||
aria-label={isMenuOpen ? 'Close menu' : 'Open menu'}
|
|
||||||
aria-expanded={isMenuOpen}
|
|
||||||
aria-controls="main-menu"
|
|
||||||
>
|
|
||||||
{isMenuOpen ? '[×]' : '[⚍]'}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
/* === MenuGrid === */
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
z-index: 9;
|
|
||||||
top: var(--el-header-height);
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-auto-columns: 1fr;
|
|
||||||
grid-template-areas:
|
|
||||||
"area_1"
|
|
||||||
"area_2"
|
|
||||||
"area_3"
|
|
||||||
"area_4"
|
|
||||||
"area_5";
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-template-rows: repeat(5, auto);
|
|
||||||
gap: 0;
|
|
||||||
gap: var(--spacing-cozy);
|
|
||||||
|
|
||||||
width: 100vw;
|
|
||||||
height: 100%;
|
|
||||||
max-height: calc(100vh - var(--el-header-height));
|
|
||||||
|
|
||||||
visibility: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
background-color: var(--color-palette-charcoal-gray);
|
|
||||||
|
|
||||||
transition: opacity 0.3s ease-out, visibility 0.3s ease-out;
|
|
||||||
|
|
||||||
&.isOpen {
|
|
||||||
pointer-events: auto;
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet) {
|
|
||||||
@mixin px var(--spacing-comfortable);
|
|
||||||
|
|
||||||
grid-template-areas:
|
|
||||||
"area_1"
|
|
||||||
"area_2"
|
|
||||||
"area_3"
|
|
||||||
"area_4"
|
|
||||||
"area_5";
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
grid-template-rows: repeat(2, 1fr);
|
|
||||||
gap: var(--spacing-comfortable);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
display: grid;
|
|
||||||
grid-template-areas:
|
|
||||||
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_1"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_1";
|
|
||||||
grid-template-columns: 2.5fr 1fr 3fr 1.5fr 1fr 1fr 4fr;
|
|
||||||
grid-template-rows: 3fr 1fr 2.5fr 1.5fr 2fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === MenuArea === */
|
|
||||||
.area {
|
|
||||||
/* === AREA VARIABLES === */
|
|
||||||
--area-bg: transparent;
|
|
||||||
--area-border: transparent;
|
|
||||||
--area-animation-keyframe: none;
|
|
||||||
--area-animation-duration: 0s;
|
|
||||||
--area-animation-timing: linear;
|
|
||||||
--area-bg-filter: grayscale(100%) contrast(150) brightness(150);
|
|
||||||
|
|
||||||
/** === TITLE VARIABLES === */
|
|
||||||
--title-color: var(--color-palette-light-silver);
|
|
||||||
--title-font: var(--font-header);
|
|
||||||
--title-font-size: var(--typo-size-2xl);
|
|
||||||
--title-font-weight: var(--typo-weight-black);
|
|
||||||
--title-line-height: 1;
|
|
||||||
--title-transform: uppercase;
|
|
||||||
--title-spacing: var(--typo-spacing-comfortable);
|
|
||||||
--title-hover-color: var(--color-tertiary);
|
|
||||||
--title-current-color: var(--color-primary);
|
|
||||||
--title-current-bg: var(--color-primary);
|
|
||||||
|
|
||||||
/** === SUBLINK VARIABLES === */;
|
|
||||||
--sublink-color: var(--color-palette-light-silver);
|
|
||||||
--sublink-font: var(--font-header);
|
|
||||||
--sublink-font-size: var(--typo-size-2xl);
|
|
||||||
--sublink-font-weight: var(--typo-weight-black);
|
|
||||||
--sublink-transform: uppercase;
|
|
||||||
--sublink-spacing: var(--typo-spacing-relaxed);
|
|
||||||
--sublink-line-height: var(--typo-leading-relaxed);
|
|
||||||
--sublink-letter-spacing: var(--typo-spacing-relaxed);
|
|
||||||
--sublink-current-color: var(--color-primary);
|
|
||||||
--sublink-current-bg: var(--color-primary);
|
|
||||||
|
|
||||||
/** === SUBTITLE VARIABLES === **/
|
|
||||||
--divider-color: var(--color-palette-light-silver);
|
|
||||||
--divider-width: var(--size-6);
|
|
||||||
--divider-height: var(--size-2);
|
|
||||||
--divider-font: var(--font-mono);
|
|
||||||
--divider-symbol: ⯆;
|
|
||||||
--divider-font-size: var(--typo-size-2xl);
|
|
||||||
--divider-padding: 0 var(--typo-spacing-cozy);
|
|
||||||
--subtitle-color: var(--color-palette-light-silver);
|
|
||||||
--subtitle-font: var(--font-mono);
|
|
||||||
--subtitle-font-size: var(--typo-size-2xl);
|
|
||||||
--subtitle-text-transform: uppercase;
|
|
||||||
--subtitle-letter-spacing: var(--typo-spacing-cozy);
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
border: var(--size-1) solid var(--area-border);
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
background: var(--area-bg);
|
|
||||||
|
|
||||||
transition: all 0.2s ease-in-out;
|
|
||||||
|
|
||||||
&:not(.current) {
|
|
||||||
&:hover {
|
|
||||||
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_1 { grid-area: area_1; }
|
|
||||||
.area_2 { grid-area: area_2; }
|
|
||||||
.area_3 { grid-area: area_3; }
|
|
||||||
.area_4 { grid-area: area_4; }
|
|
||||||
.area_5 { grid-area: area_5; }
|
|
||||||
|
|
||||||
.hasBGImg {
|
|
||||||
&:hover {
|
|
||||||
.bgImg {
|
|
||||||
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bgImg {
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
object-fit: cover;
|
|
||||||
filter: var(--area-bg-filter);
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === MenuTitle === */
|
|
||||||
.title {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mainlink {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
font-family: var(--title-font);
|
|
||||||
font-size: var(--title-font-size);
|
|
||||||
font-weight: var(--title-font-weight);
|
|
||||||
line-height: var(--title-line-height);
|
|
||||||
color: var(--title-color);
|
|
||||||
text-transform: var(--title-transform);
|
|
||||||
letter-spacing: var(--title-spacing);
|
|
||||||
|
|
||||||
transition: any 0.5s ease-in-out;
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
&:hover {
|
|
||||||
color: var(--title-current-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
outline: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--title-current-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
&:hover {
|
|
||||||
color: var(--title-current-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
transition: border 0.5s ease-in-out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === MenuSublinks === */
|
|
||||||
.list {
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sublink {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
font-family: var(--sublink-font);
|
|
||||||
font-size: var(--sublink-font-size);
|
|
||||||
font-weight: var(--sublink-font-weight);
|
|
||||||
line-height: var(--sublink-line-height);
|
|
||||||
color: var(--sublink-color);
|
|
||||||
text-transform: var(--sublink-transform);
|
|
||||||
letter-spacing: var(--sublink-spacing);;
|
|
||||||
|
|
||||||
&:not(.current),
|
|
||||||
&:not(.focus) {
|
|
||||||
transition: var(--sublink-hover-transition);
|
|
||||||
|
|
||||||
&::after,
|
|
||||||
&::before {
|
|
||||||
position: absolute;
|
|
||||||
font-family: var(--sublink-hover-decorator-font);
|
|
||||||
opacity: 0;
|
|
||||||
transition: var(--sublink-hover-decorator-transition);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: var(--sublink-hover-decorator-left-symbol);
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: var(--sublink-hover-decorator-right-symbol);
|
|
||||||
right: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--sublink-hover-color);
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
top: var(--sublink-hover-decorator-left-pos-y);
|
|
||||||
left: var(--sublink-hover-decorator-left-pos-x);
|
|
||||||
transform: var(--sublink-hover-decorator-left-transform);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
top: var(--sublink-hover-decorator-right-pos-y);
|
|
||||||
right: var(--sublink-hover-decorator-rightt-pos-x);
|
|
||||||
transform: var(--sublink-hover-decorator-right-transform);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
&:hover {
|
|
||||||
color: var(--sublink-current-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === MenuSubtitle === */
|
|
||||||
.wrapper {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === UTILITY Classes */
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
.pos_tr {
|
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
right: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_tc {
|
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_tl {
|
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_cr {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 1em;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_c {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, 50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_cl {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
right: 1em;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_br {
|
|
||||||
position: absolute;
|
|
||||||
right: 1em;
|
|
||||||
bottom: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_bc {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1em;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.pos_bl {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1em;
|
|
||||||
left: 1em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-rl {
|
|
||||||
writing-mode: vertical-rl;
|
|
||||||
|
|
||||||
& * {
|
|
||||||
writing-mode: vertical-rl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.vertical-lr {
|
|
||||||
writing-mode: vertical-lr;
|
|
||||||
|
|
||||||
& * {
|
|
||||||
writing-mode: vertical-lr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sideways-rl {
|
|
||||||
writing-mode: sideways-rl;
|
|
||||||
|
|
||||||
& * {
|
|
||||||
writing-mode: sideways-rl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.sideways-lr {
|
|
||||||
writing-mode: sideways-lr;
|
|
||||||
|
|
||||||
& * {
|
|
||||||
writing-mode: sideways-lr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* === CATEGORY Variants === */
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
.meta {}
|
|
||||||
.kitchensink {}
|
|
||||||
.awq {}
|
|
||||||
.worldburner {}
|
|
||||||
.chainbreaker {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.area {
|
|
||||||
--area-bg: transparent;
|
|
||||||
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
text-align: center;
|
|
||||||
|
|
||||||
background: var(--area-bg);
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
border-bottom: var(--size-1) solid var(--color-palette-gunmetal);
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_1 {
|
|
||||||
position: relative;
|
|
||||||
grid-area: area_1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_2 {
|
|
||||||
position: relative;
|
|
||||||
grid-area: area_2;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_3 {
|
|
||||||
position: relative;
|
|
||||||
grid-area: area_3;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_4 {
|
|
||||||
position: relative;
|
|
||||||
grid-area: area_4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.area_5 {
|
|
||||||
position: relative;
|
|
||||||
grid-area: area_5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hasBGImg {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
& .bgImg {
|
|
||||||
animation: var(--area-animation-keyframe) var(--area-animation-duration) var(--area-animation-timing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bgImg {
|
|
||||||
--area-bg-animation-keyframe: none;
|
|
||||||
--area-bg--animation-duration: 0s;
|
|
||||||
--area-bg--animation-timing: linear;
|
|
||||||
--area-bg-filter: grayscale(100%) contrast(150) brightness(150);
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
object-fit: cover;
|
|
||||||
filter: var(--area-bg-filter);
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
.chainbreaker {
|
|
||||||
--area-animation-keyframe: var(--kf-color-bleed);
|
|
||||||
--area-animation-duration: var(--img-colorbleed-duration);
|
|
||||||
--area-animation-timing: var(--img-colorbleed-timing);
|
|
||||||
|
|
||||||
& .bgImg {
|
|
||||||
z-index: -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.hasBGImg {
|
|
||||||
--divider-color: transparent;
|
|
||||||
--title-color: transparent;
|
|
||||||
--subtitle-color: transparent;
|
|
||||||
--subtitle-transition: all 0.3s ease-in-out;
|
|
||||||
--title-transition: color 0.3s ease-in-out;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "";
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
opacity: 0;
|
|
||||||
background: alpharize(var(--grid-bg), 0.66);
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
--divider-color: var(--color-tertiary);
|
|
||||||
--title-color: var(--color-tertiary);
|
|
||||||
--subtitle-color: var(--color-tertiary);
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
import MenuItem from '@/components/Page/Menu//MenuItem/';
|
|
||||||
import { useCurrentPath } from '@/hooks/useCurrentPath';
|
|
||||||
|
|
||||||
import styles from './MenuArea.module.css';
|
|
||||||
|
|
||||||
import { NavigationItem } from '@/lib/types/navigation';
|
|
||||||
|
|
||||||
interface MenuAreaProps {
|
|
||||||
item: NavigationItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MenuArea = React.memo(({ item }: MenuAreaProps) => {
|
|
||||||
const hasBGImg = !!item.background;
|
|
||||||
const { isCurrentPath } = useCurrentPath();
|
|
||||||
|
|
||||||
const areaClasses = React.useMemo(() => {
|
|
||||||
return [
|
|
||||||
styles.area,
|
|
||||||
styles[item.gridPosition],
|
|
||||||
styles[item.variant],
|
|
||||||
isCurrentPath(item.path) ? styles.current : '',
|
|
||||||
item.background ? styles.hasBGImg : null,
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ');
|
|
||||||
}, [item.background, isCurrentPath]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className={areaClasses}>
|
|
||||||
{hasBGImg && (
|
|
||||||
<img
|
|
||||||
className={styles.bgImg}
|
|
||||||
src={item.background}
|
|
||||||
alt={`Background Image for ${item.name}`}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<MenuItem item={item} />
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
MenuArea.displayName = 'MenuArea';
|
|
||||||
|
|
||||||
export default MenuArea;
|
|
||||||
@@ -1,115 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.menu {
|
|
||||||
--grid-bg: var(--color-palette-charcoal-gray);
|
|
||||||
--grid-fg: var(--color-palette-light-silver);
|
|
||||||
|
|
||||||
/* === MenuTitle Vars === */
|
|
||||||
--title-color: var(--grid-fg);
|
|
||||||
--title-font: var(--font-mono);
|
|
||||||
--title-font-size: var(--typo-size-2xl);
|
|
||||||
--title-font-weight: var(--typo-weight-black);
|
|
||||||
--title-line-height: 1;
|
|
||||||
--title-transform: uppercase;
|
|
||||||
--title-spacing: var(--typo-spacing-comfortable);
|
|
||||||
--title-hover-fg: var(--primary);
|
|
||||||
--title-hover-bg: transparent;
|
|
||||||
--title-current-bg: var(--color-tertiary);
|
|
||||||
--title-current-fg: var(--grid-bg);
|
|
||||||
--title-focus-fg: var(--color-secondary);
|
|
||||||
--title-focus-bg: var(--grid-bg);
|
|
||||||
--title-transition: none;
|
|
||||||
|
|
||||||
/* === MenuSublinks Vars === */
|
|
||||||
--sublink-color: var(--grid-fg);
|
|
||||||
--sublink-font: var(--font-mono);
|
|
||||||
--sublink-font-size: var(--typo-size-xl);
|
|
||||||
--sublink-font-weight: var(--typo-weight-light);
|
|
||||||
--sublink-transform: uppercase;
|
|
||||||
--sublink-line-height: var(--typo-leading-relaxed);
|
|
||||||
--sublink-spacing: var(--typo-spacing-loosest);
|
|
||||||
--sublink-hover-fg: var(--color-tertiary);
|
|
||||||
--sublink-hover-bg: transparent;
|
|
||||||
--sublink-current-fg: var(--grid-bg);
|
|
||||||
--sublink-current-bg: var(--color-primary);
|
|
||||||
--sublink-focus-fg: var(--color-secondary);
|
|
||||||
--sublink-focus-bg: var(--grid-bg);
|
|
||||||
--sublink-transition: none;
|
|
||||||
|
|
||||||
/* === MenuSubtitle Vars === */
|
|
||||||
--divider-color: var(--grid-fg);
|
|
||||||
--divider-width: var(--size-12);
|
|
||||||
--divider-height: var(--size-2);
|
|
||||||
--divider-font: var(--font-mono);
|
|
||||||
--divider-font-size: var(--typo-size-2xl);
|
|
||||||
--divider-padding: 0 var(--typo-spacing-cozy);
|
|
||||||
--subtitle-font: var(--font-mono);
|
|
||||||
--subtitle-color: var(--grid-fg);
|
|
||||||
--subtitle-font-size: var(--typo-size-xl);
|
|
||||||
--subtitle-text-transform: uppercase;
|
|
||||||
--subtitle-letter-spacing: var(--typo-spacing-cozy);
|
|
||||||
--subtitle-transition: none;
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
|
|
||||||
position: fixed;
|
|
||||||
z-index: 9;
|
|
||||||
top: var(--el-header-height);
|
|
||||||
left: 0;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-auto-columns: 1fr;
|
|
||||||
grid-template-areas:
|
|
||||||
"area_1"
|
|
||||||
"area_2"
|
|
||||||
"area_3"
|
|
||||||
"area_4"
|
|
||||||
"area_5";
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
grid-template-rows: repeat(5, auto);
|
|
||||||
|
|
||||||
width: 100vw;
|
|
||||||
height: calc(100vh - var(--el-header-height));
|
|
||||||
|
|
||||||
color: var(--grid-fg);
|
|
||||||
|
|
||||||
visibility: hidden;
|
|
||||||
opacity: 0;
|
|
||||||
background-color: var(--grid-bg);
|
|
||||||
clip-path: inset(0 0 100% 0);
|
|
||||||
|
|
||||||
transition: clip-path 0.35s steps(8, end);
|
|
||||||
|
|
||||||
|
|
||||||
&.isOpen {
|
|
||||||
pointer-events: auto;
|
|
||||||
|
|
||||||
transform: translateY(0);
|
|
||||||
|
|
||||||
visibility: visible;
|
|
||||||
opacity: 1;
|
|
||||||
clip-path: inset(0 0 0 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.isClosing {
|
|
||||||
clip-path: inset(0 0 100% 0);
|
|
||||||
transition: clip-path 0.25s steps(6, end);
|
|
||||||
|
|
||||||
&.isOpen {
|
|
||||||
clip-path: inset(0 0 100% 0);
|
|
||||||
transition: clip-path 0.25s steps(6, end);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (--bp-desktop) {
|
|
||||||
display: grid;
|
|
||||||
grid-template-areas:
|
|
||||||
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_4 area_4 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_2"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_1"
|
|
||||||
"area_5 area_5 area_3 area_3 area_3 area_3 area_1";
|
|
||||||
grid-template-columns: 2.5fr 1fr 3fr 1.5fr 1fr 1fr 4fr;
|
|
||||||
grid-template-rows: 3fr 1fr 2.5fr 1.5fr 2fr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { useMenu } from '@/contexts/MenuContext';
|
|
||||||
import MenuArea from '@/components/Page/Menu/MenuArea/';
|
|
||||||
|
|
||||||
import styles from './MenuGrid.module.css';
|
|
||||||
|
|
||||||
interface MenuGridProps {
|
|
||||||
navigationData: Awaited<
|
|
||||||
ReturnType<
|
|
||||||
typeof import('@/lib/readers/system/navigation').getNavigationData
|
|
||||||
>
|
|
||||||
>;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MenuGrid({ navigationData }: MenuGridProps) {
|
|
||||||
const { isMenuOpen, closeMenu, isClosing, startClosing, resetClosing } =
|
|
||||||
useMenu();
|
|
||||||
const menuRef = React.useRef<HTMLElement>(null);
|
|
||||||
const handleClose = React.useCallback(() => {
|
|
||||||
startClosing();
|
|
||||||
setTimeout(() => {
|
|
||||||
closeMenu();
|
|
||||||
resetClosing();
|
|
||||||
}, 800);
|
|
||||||
}, [closeMenu, startClosing, resetClosing]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
const handleEscape = (e: KeyboardEvent) => {
|
|
||||||
if (e.key === 'Escape' && isMenuOpen) {
|
|
||||||
handleClose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.addEventListener('keydown', handleEscape);
|
|
||||||
return () => document.removeEventListener('keydown', handleEscape);
|
|
||||||
}, [isMenuOpen, handleClose]);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
if (isMenuOpen && menuRef.current) {
|
|
||||||
const initialFocus = menuRef.current.querySelector(
|
|
||||||
'a, button'
|
|
||||||
) as HTMLElement;
|
|
||||||
initialFocus?.focus();
|
|
||||||
}
|
|
||||||
}, [isMenuOpen]);
|
|
||||||
|
|
||||||
if (!navigationData) return null;
|
|
||||||
|
|
||||||
const { items } = navigationData;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<nav
|
|
||||||
ref={menuRef}
|
|
||||||
className={`${styles.menu} ${isMenuOpen ? styles.isOpen : ''} ${isClosing ? styles.isClosing : ''}`}
|
|
||||||
aria-hidden={!isMenuOpen}
|
|
||||||
aria-label="Main navigation"
|
|
||||||
>
|
|
||||||
{items.map((item, index) => (
|
|
||||||
<MenuArea key={item.gridPosition} item={item} />
|
|
||||||
))}
|
|
||||||
</nav>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
import { hasSublinks, hasSubtitle } from '@/lib/types/navigation';
|
|
||||||
import MenuTitle from '@/components/Page/Menu/MenuTitle/';
|
|
||||||
import MenuSublinks from '@/components/Page/Menu/MenuSublinks/';
|
|
||||||
import MenuSubtitle from '@/components/Page/Menu/MenuSubtitle/';
|
|
||||||
|
|
||||||
import { NavigationItem } from '@/lib/types/navigation';
|
|
||||||
|
|
||||||
interface MenuItem {
|
|
||||||
item: NavigationItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MenuItem({ item }: MenuItem) {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<MenuTitle path={item.path} name={item.name} variant={item.variant} />
|
|
||||||
{hasSublinks(item) && (
|
|
||||||
<MenuSublinks sublinks={item.sublinks.value} variant={item.variant} />
|
|
||||||
)}
|
|
||||||
{hasSubtitle(item) && (
|
|
||||||
<MenuSubtitle subtitle={item.subtitle.value} variant={item.variant} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.list {
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
@util hide-visually;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.item {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sublink {
|
|
||||||
font-family: var(--sublink-font);
|
|
||||||
font-size: var(--sublink-font-size);
|
|
||||||
font-weight: var(--sublink-font-weight);
|
|
||||||
line-height: var(--sublink-line-height);
|
|
||||||
color: var(--sublink-color);
|
|
||||||
text-transform: var(--sublink-transform);
|
|
||||||
letter-spacing: var(--sublink-spacing);
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
padding: var(--spacing-snug) var(--spacing-tight);
|
|
||||||
color: var(--title-current-fg);
|
|
||||||
animation: var(--kf-text-glitch) 5s infinite;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "⟩";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.current) {
|
|
||||||
--pointer-left-symbol: "▶";
|
|
||||||
--pointer-right-symbol: "◀";
|
|
||||||
--pointer-distance: 1em;
|
|
||||||
|
|
||||||
@mixin anim-txt-pointer_focus;
|
|
||||||
@mixin px var(--spacing-tight);
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
color: var(--sublink-focus-fg);
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:focus) {
|
|
||||||
--pointer-left-symbol: "{";
|
|
||||||
--pointer-right-symbol: "}";
|
|
||||||
--pointer-distance: 0.5em;
|
|
||||||
|
|
||||||
@mixin anim-txt-pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
--sublink-color: var(--color-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import styles from './MenuSublinks.module.css';
|
|
||||||
|
|
||||||
import { SubNavigationItem } from '@/lib/types/navigation';
|
|
||||||
import { useCurrentPath } from '@/hooks/useCurrentPath';
|
|
||||||
|
|
||||||
interface MenuSublinks {
|
|
||||||
sublinks: readonly SubNavigationItem[];
|
|
||||||
variant: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MenuSublinks({ sublinks, variant }: MenuSublinks) {
|
|
||||||
const { isCurrentPath } = useCurrentPath();
|
|
||||||
return (
|
|
||||||
<ul className={`${styles.list} ${styles[`${variant}`]}`}>
|
|
||||||
{sublinks.map((sublink: SubNavigationItem) => (
|
|
||||||
<li className={styles.item} key={sublink.path}>
|
|
||||||
<Link
|
|
||||||
href={sublink.path}
|
|
||||||
className={`${styles.sublink} ${isCurrentPath(sublink.path) ? styles.current : ''}`}
|
|
||||||
>
|
|
||||||
{sublink.name}
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.claim {
|
|
||||||
|
|
||||||
@media screen and (--bp-tablet-down) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.divider {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dividersymbol {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
font-family: var(--divider-font);
|
|
||||||
font-size: var(--divider-font-size);
|
|
||||||
line-height: var(--divider-line-height);
|
|
||||||
color: var(--divider-color);
|
|
||||||
|
|
||||||
transition: var(--subtitle-transition);
|
|
||||||
|
|
||||||
&::before,
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
|
|
||||||
width: var(--divider-width);
|
|
||||||
height: var(--divider-height);
|
|
||||||
|
|
||||||
background-color: var(--divider-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
left: calc(var(--divider-width) *-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
right: calc(var(--divider-width) *-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.subtitle {
|
|
||||||
font-family: var(--subtitle-font);
|
|
||||||
font-size: var(--subtitle-font-size);
|
|
||||||
color: var(--subtitle-color);
|
|
||||||
text-transform: var(--subtitle-text-transform);
|
|
||||||
letter-spacing: var(--subtitle-letter-spacing);
|
|
||||||
|
|
||||||
transition: var(--subtitle-transition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
import { Subtitle, hasDivider } from '@/lib/types/navigation';
|
|
||||||
import styles from './MenuSubtitle.module.css';
|
|
||||||
|
|
||||||
interface MenuSubtitleProps {
|
|
||||||
subtitle: Subtitle;
|
|
||||||
variant: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MenuSubtitle({ subtitle, variant }: MenuSubtitleProps) {
|
|
||||||
const divider = hasDivider(subtitle) ? (
|
|
||||||
<div className={styles.divider}>
|
|
||||||
<span className={`${styles.dividersymbol}`}>
|
|
||||||
{subtitle.divider.value}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={`${styles.claim} ${styles[`${variant}`]}`}>
|
|
||||||
{divider}
|
|
||||||
<p className={`${styles.subtitle}`}>{subtitle.content}</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
@layer components {
|
|
||||||
.heading {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&:has(+ ul) {
|
|
||||||
@mixin my var(--spacing-comfortable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mainlink {
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
font-family: var(--title-font);
|
|
||||||
font-size: var(--title-font-size);
|
|
||||||
font-weight: var(--title-font-weight);
|
|
||||||
line-height: var(--title-line-height);
|
|
||||||
color: var(--title-color);
|
|
||||||
text-transform: var(--title-transform);
|
|
||||||
letter-spacing: var(--title-spacing);
|
|
||||||
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
transition: var(--title-transition);
|
|
||||||
|
|
||||||
&.current {
|
|
||||||
padding: var(--spacing-snug) var(--spacing-tight);
|
|
||||||
color: var(--title-current-fg);
|
|
||||||
animation: var(--kf-text-glitch) 5s infinite;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: "⟩";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(.current) {
|
|
||||||
--pointer-left-symbol: "▶";
|
|
||||||
--pointer-right-symbol: "◀";
|
|
||||||
--pointer-distance: 1em;
|
|
||||||
|
|
||||||
@mixin anim-txt-pointer_focus;
|
|
||||||
@mixin px var(--spacing-tight);
|
|
||||||
|
|
||||||
&:focus {
|
|
||||||
color: var(--title-focus-fg);
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:not(:focus) {
|
|
||||||
--pointer-left-symbol: "{";
|
|
||||||
--pointer-right-symbol: "}";
|
|
||||||
--pointer-distance: 0.5em;
|
|
||||||
|
|
||||||
@mixin anim-txt-pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
--title-color: var(--color-primary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import Link from 'next/link';
|
|
||||||
|
|
||||||
import styles from './MenuTitle.module.css';
|
|
||||||
|
|
||||||
import { useCurrentPath } from '@/hooks/useCurrentPath';
|
|
||||||
|
|
||||||
interface MenuTitleProps {
|
|
||||||
name: string;
|
|
||||||
path: string;
|
|
||||||
variant: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MenuTitle({ name, path, variant }: MenuTitleProps) {
|
|
||||||
const { isCurrentPath } = useCurrentPath();
|
|
||||||
return (
|
|
||||||
<h2 className={`${styles.heading} ${styles[`${variant}`]}`}>
|
|
||||||
<Link
|
|
||||||
className={`${styles.mainlink} ${isCurrentPath(path) ? styles.current : ''}`}
|
|
||||||
href={path}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</Link>
|
|
||||||
</h2>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { getNavigationData } from '@/lib/readers/system/navigation';
|
|
||||||
import MenuGrid from '@/components/Page/Menu/MenuGrid';
|
|
||||||
|
|
||||||
export default async function Menu() {
|
|
||||||
const navigation = await getNavigationData();
|
|
||||||
return <MenuGrid navigationData={navigation} />;
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
'use client';
|
|
||||||
|
|
||||||
import React, { useContext, useEffect } from 'react';
|
|
||||||
|
|
||||||
interface MenuContextType {
|
|
||||||
isMenuOpen: boolean;
|
|
||||||
isClosing: boolean;
|
|
||||||
closeMenu: () => void;
|
|
||||||
openMenu: () => void;
|
|
||||||
startClosing: () => void;
|
|
||||||
resetClosing: () => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MenuContext = React.createContext<MenuContextType | undefined>(undefined);
|
|
||||||
|
|
||||||
interface MenuProviderProps {
|
|
||||||
children: React.ReactNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MenuProvider = ({ children }: MenuProviderProps) => {
|
|
||||||
const [isMenuOpen, setIsMenuOpen] = React.useState(false);
|
|
||||||
const [isClosing, setIsClosing] = React.useState(false);
|
|
||||||
|
|
||||||
const closeMenu = () => setIsMenuOpen(false);
|
|
||||||
const openMenu = () => setIsMenuOpen(true);
|
|
||||||
const startClosing = () => setIsClosing(true);
|
|
||||||
const resetClosing = () => setIsClosing(false);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (isMenuOpen) {
|
|
||||||
document.body.style.overflow = 'hidden';
|
|
||||||
} else {
|
|
||||||
document.body.style.overflow = 'unset';
|
|
||||||
}
|
|
||||||
return () => {
|
|
||||||
document.body.style.overflow = 'unset';
|
|
||||||
};
|
|
||||||
}, [isMenuOpen]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<MenuContext.Provider
|
|
||||||
value={{
|
|
||||||
isMenuOpen,
|
|
||||||
openMenu,
|
|
||||||
closeMenu,
|
|
||||||
isClosing,
|
|
||||||
startClosing,
|
|
||||||
resetClosing,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</MenuContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useMenu = () => {
|
|
||||||
const context = useContext(MenuContext);
|
|
||||||
if (context === undefined) {
|
|
||||||
throw new Error('useMenu must be used within a MenuProvider');
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
};
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user