Compare commits
3 Commits
5d039e2b63
...
983436da32
| Author | SHA1 | Date | |
|---|---|---|---|
| 983436da32 | |||
| 6c9d8966b0 | |||
| 700066b2b2 |
@@ -1,4 +1,4 @@
|
||||
name: lena-schilling
|
||||
name: dialog-relations
|
||||
type: typo3
|
||||
docroot: public
|
||||
php_version: "8.3"
|
||||
@@ -14,6 +14,7 @@ composer_version: "2"
|
||||
web_environment:
|
||||
- TYPO3_CONTEXT=Development/Ddev
|
||||
corepack_enable: false
|
||||
nodejs_version: "18"
|
||||
|
||||
# Key features of DDEV's config.yaml:
|
||||
|
||||
@@ -278,6 +279,7 @@ corepack_enable: false
|
||||
# See https://ddev.readthedocs.io/en/stable/users/extend/custom-commands/ for more
|
||||
# information on the commands that can be extended and the tasks you can define
|
||||
# for them. Example:
|
||||
#hooks:
|
||||
# post-start:
|
||||
# - exec: composer install -d /var/www/html
|
||||
hooks:
|
||||
post-start:
|
||||
- exec: "npm install"
|
||||
- exec: "npm run build:css"
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
base: https://lena-schilling.at
|
||||
base: https://dialog-relations.at
|
||||
baseVariants:
|
||||
- base: https://lena-schilling.ddev.site
|
||||
- base: https://dialog-relations.ddev.site
|
||||
condition: 'applicationContext == "Development/Ddev"'
|
||||
- base: https://lena-schilling.cloonar.dev
|
||||
- base: https://dialog-relations.cloonar.dev
|
||||
condition: 'applicationContext == "Production/Staging"'
|
||||
dependencies:
|
||||
- georgringer/news
|
||||
@@ -25,8 +25,8 @@ languages:
|
||||
rootPageId: 1
|
||||
websiteTitle: ''
|
||||
favicons:
|
||||
full_name: 'Lena Schilling'
|
||||
short_name: 'Lena Schilling'
|
||||
full_name: 'Dialog Relations'
|
||||
short_name: 'Dialog Relations'
|
||||
theme_color: '#233600'
|
||||
favicon_path: 'EXT:base/Resources/Public/Images/Favicons/'
|
||||
favicon_svg: favicon.svg
|
||||
|
||||
83
flake.nix
Normal file
83
flake.nix
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
description = "Dialog Relations VSCode workspace";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||
mcp-servers-nix = {
|
||||
url = "github:natsukium/mcp-servers-nix";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
outputs =
|
||||
{
|
||||
nixpkgs,
|
||||
mcp-servers-nix,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
forAllSystems = lib.genAttrs [
|
||||
"aarch64-darwin"
|
||||
"aarch64-linux"
|
||||
"x86_64-darwin"
|
||||
"x86_64-linux"
|
||||
];
|
||||
in
|
||||
{
|
||||
devShells = forAllSystems (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config.allowUnfree = true;
|
||||
};
|
||||
in
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
packages = with pkgs; [ vscode ];
|
||||
shellHook =
|
||||
let
|
||||
config = mcp-servers-nix.lib.mkConfig pkgs {
|
||||
fileName = "mcp.json";
|
||||
flavor = "vscode-workspace";
|
||||
programs = {
|
||||
filesystem = {
|
||||
enable = true;
|
||||
args = [
|
||||
# NOTE: Using builtins.getEnv requires running `nix develop` with --impure flag
|
||||
"${toString (builtins.getEnv "PWD")}"
|
||||
];
|
||||
};
|
||||
fetch = {
|
||||
enable = true;
|
||||
};
|
||||
# github = {
|
||||
# enable = true;
|
||||
# env = {
|
||||
# GITHUB_PERSONAL_ACCESS_TOKEN = ''''${input:github_token}'';
|
||||
# };
|
||||
# };
|
||||
};
|
||||
settings.inputs = [
|
||||
# {
|
||||
# type = "promptString";
|
||||
# id = "github_token";
|
||||
# description = "GitHub Personal Access Token";
|
||||
# password = true;
|
||||
# }
|
||||
];
|
||||
};
|
||||
in
|
||||
''
|
||||
if [ -L ".vscode/mcp.json" ]; then
|
||||
unlink .vscode/mcp.json
|
||||
fi
|
||||
mkdir -p .vscode
|
||||
ln -sf ${config} .vscode/mcp.json
|
||||
'';
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
1734
package-lock.json
generated
1734
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -5,10 +5,14 @@
|
||||
"build:css": "webpack --config webpack.config.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^10.4.21",
|
||||
"css-loader": "^6.7.3",
|
||||
"mini-css-extract-plugin": "^2.7.5",
|
||||
"postcss": "^8.5.3",
|
||||
"postcss-loader": "^8.1.1",
|
||||
"sass": "^1.63.4",
|
||||
"sass-loader": "^13.3.2",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"webpack": "^5.88.0",
|
||||
"webpack-cli": "^5.1.4"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<f:layout name="Default" />
|
||||
<f:section name="Main">
|
||||
<h1><span class="tapered">{data.header}</span></h1>
|
||||
<h1 class="font-hajime text-primary font-normal leading-none text-center text-5xl md:text-7xl">
|
||||
<span>{data.header}</span>
|
||||
</h1>
|
||||
</f:section>
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
.frame-type-cloonar_hero {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
/* Use a relative path to correctly load the image */
|
||||
background: #cecece;
|
||||
background-repeat: repeat;
|
||||
background: url('../../../Images/background.jpg') repeat;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero + .frame {
|
||||
margin-top: -10.4rem;
|
||||
}
|
||||
.frame-type-cloonar_hero .container {
|
||||
padding-bottom: 3rem;
|
||||
}
|
||||
|
||||
/* Inner container with white background and padding */
|
||||
.frame-type-cloonar_hero .hero-inner {
|
||||
padding: 3rem 1rem;
|
||||
max-width: 1140px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-subheader {
|
||||
font-size: 2rem;
|
||||
color: var(--bs-primary);
|
||||
margin-bottom: 0rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-title {
|
||||
text-transform: uppercase;
|
||||
font-size: 4rem;
|
||||
color: var(--bs-primary);
|
||||
line-height: 1;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero h4 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-text {
|
||||
font-size: 1rem;
|
||||
color: #333;
|
||||
line-height: 1.4;
|
||||
margin-bottom: 1rem;
|
||||
max-width: 45ch;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-social-icons {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Smaller icons on mobile */
|
||||
.frame-type-cloonar_hero .social-icon {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
padding: 1rem;
|
||||
text-decoration: none;
|
||||
border-radius: 50%;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-image-wrapper {
|
||||
margin-top: 1rem;
|
||||
align-self: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.frame-type-cloonar_hero .container {
|
||||
padding-bottom: 4rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-subheader {
|
||||
font-size: 3rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-title {
|
||||
font-size: 5rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-text {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .social-icon {
|
||||
width: 2.5rem;
|
||||
height: 2rem;
|
||||
font-size: 2rem;
|
||||
padding: 2.375rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-image {
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.frame-type-cloonar_hero .hero {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 40% 7.125rem;
|
||||
grid-template-rows: auto auto 1fr;
|
||||
grid-template-areas:
|
||||
"subheader image social"
|
||||
"title image social"
|
||||
"text image social";
|
||||
align-items: start;
|
||||
justify-items: start;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-subheader {
|
||||
grid-area: subheader;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-title {
|
||||
grid-area: title;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-text {
|
||||
grid-area: text;
|
||||
font-size: 1rem;
|
||||
max-width: 40ch;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-social-icons {
|
||||
grid-area: social;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-bottom: 0;
|
||||
align-items: flex-start;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-image-wrapper {
|
||||
grid-area: image;
|
||||
margin-top: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.frame-type-cloonar_hero .hero-image {
|
||||
}
|
||||
}
|
||||
@@ -1,62 +1,115 @@
|
||||
<f:layout name="Default" />
|
||||
<f:layout name="FullWidth" />
|
||||
|
||||
<!-- No extra heading from the parent layout -->
|
||||
<f:section name="Header" />
|
||||
|
||||
<f:section name="Main">
|
||||
<f:asset.css identifier="CBHero" href="{cb:assetPath()}/frontend.css" />
|
||||
<div class="md:flex">
|
||||
|
||||
<div class="hero-inner">
|
||||
<div class="hero">
|
||||
<h2 class="hero-subheader">{data.subheader}</h2>
|
||||
<h1 class="hero-title">{data.header}</h1>
|
||||
<div class="hero-text">
|
||||
<f:format.html>{data.bodytext}</f:format.html>
|
||||
</div>
|
||||
<div class="hero-social-icons">
|
||||
<a href="https://www.instagram.com/lena.ats/" target="_blank" aria-label="Lena Schillings Instagram" class="btn social-icon"><i class="ci ci-instagram"></i></a>
|
||||
<a href="https://www.tiktok.com/@dieschilling" target="_blank" aria-label="Lena Schillings TikTok" class="btn social-icon"><i class="ci ci-tiktok"></i></a>
|
||||
</div>
|
||||
<div class="hero-image-wrapper">
|
||||
<f:if condition="{data.image}">
|
||||
<f:then>
|
||||
<figure>
|
||||
<!-- WEBP source -->
|
||||
<!-- LEFT: blue background + image -->
|
||||
<div class="relative bg-primary md:w-3/5 py-16 flex justify-end">
|
||||
<!-- picture wrapper for relative positioning -->
|
||||
<div class="relative w-3/4">
|
||||
<f:if condition="{data.image}">
|
||||
<f:then>
|
||||
<picture class="block w-full object-cover">
|
||||
<!-- webp / fallback sources as before… -->
|
||||
<source
|
||||
type="image/webp"
|
||||
srcset="
|
||||
{f:uri.image(image:data.image.0, width:'320c', cropVariant:'default', fileExtension:'webp')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'768c', cropVariant:'default', fileExtension:'webp')} 768w,
|
||||
{f:uri.image(image:data.image.0, width:'430c', cropVariant:'default', fileExtension:'webp')} 1024w"
|
||||
sizes="(max-width: 320px) 80vw,
|
||||
(max-width: 768px) 80px,
|
||||
430px" />
|
||||
{f:uri.image(image:data.image.0, width:'320c', fileExtension:'webp')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'768c', fileExtension:'webp')} 768w,
|
||||
{f:uri.image(image:data.image.0, width:'1024c', fileExtension:'webp')} 1024w"
|
||||
sizes="(max-width: 768px) 80vw, 430px" />
|
||||
<source
|
||||
srcset="
|
||||
{f:uri.image(image:data.image.0, width:'320c')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'768c')} 768w,
|
||||
{f:uri.image(image:data.image.0, width:'1024c')} 1024w"
|
||||
sizes="(max-width: 768px) 80vw, 430px" />
|
||||
<f:image
|
||||
image="{data.image.0}"
|
||||
treatIdAsReference="1"
|
||||
fetchpriority="high"
|
||||
cropVariant="default"
|
||||
width="1024c"
|
||||
alt="Hero Image"
|
||||
loading="lazy"
|
||||
class="w-full h-auto"
|
||||
/>
|
||||
</picture>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<p class="w-full text-center text-white">No image available</p>
|
||||
</f:else>
|
||||
</f:if>
|
||||
|
||||
<!-- Fallback source -->
|
||||
<source
|
||||
srcset="
|
||||
{f:uri.image(image:data.image.0, width:'320c', cropVariant:'default')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'600c', cropVariant:'default')} 600w,
|
||||
{f:uri.image(image:data.image.0, width:'430c', cropVariant:'default')} 1024w"
|
||||
sizes="(max-width: 320px) 80vw,
|
||||
(max-width: 768px) 80vw,
|
||||
430px" />
|
||||
<f:image
|
||||
image="{data.image.0}"
|
||||
treatIdAsReference="1"
|
||||
fetchpriority="high"
|
||||
cropVariant="default"
|
||||
width="430c"
|
||||
alt="Hero Image"
|
||||
loading="lazy"
|
||||
class="hero-image" />
|
||||
</figure>
|
||||
</f:then>
|
||||
<f:else>
|
||||
<p>No image available</p>
|
||||
</f:else>
|
||||
</f:if>
|
||||
<!-- arrow: half‑out on right edge -->
|
||||
<div class="absolute top-1/2 -translate-y-1/2 right-[-2rem] z-20">
|
||||
<a href="#next-section"
|
||||
class="bg-primary border-4 border-white rounded-full p-5 inline-flex items-center justify-center hover:bg-opacity-90">
|
||||
<span class="sr-only">Scroll down</span>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
class="w-6 h-6"
|
||||
fill="none" viewBox="0 0 24 24"
|
||||
stroke="currentColor" stroke-width="2">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M19 9l-7 7-7-7" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- RIGHT: text & socials -->
|
||||
<div class="md:w-2/5 px-6 py-12 md:py-0 md:px-16 flex flex-col justify-center">
|
||||
|
||||
<!-- Mobile: simple centered intro -->
|
||||
<div class="block md:hidden text-center space-y-2 mb-8">
|
||||
<div class="text-sm uppercase tracking-wide text-gray-600">
|
||||
Hallo, wir sind
|
||||
</div>
|
||||
<h1 class="text-3xl font-extrabold">
|
||||
Dialog Relations
|
||||
</h1>
|
||||
<p class="text-base text-gray-800">
|
||||
Sorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Desktop: line + intro -->
|
||||
<div class="hidden md:block space-y-4">
|
||||
<!-- horizontal line + text -->
|
||||
<div class="flex items-center space-x-3 mb-2">
|
||||
<span class="block h-px w-10 bg-gray-600"></span>
|
||||
<div class="text-sm uppercase tracking-wide text-gray-600">
|
||||
Hallo, wir sind
|
||||
</div>
|
||||
</div>
|
||||
<h1 class="text-5xl font-extrabold">
|
||||
Dialog Relations
|
||||
</h1>
|
||||
<p class="text-lg text-gray-800 max-w-md">
|
||||
Sorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Nunc vulputate libero et velit interdum, ac aliquet odio mattis.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Social icons -->
|
||||
<div class="mt-8 flex justify-center md:justify-start space-x-4">
|
||||
<a href="#" class="bg-primary text-white p-3 rounded-full">
|
||||
<span class="sr-only">LinkedIn</span>
|
||||
<svg class="w-5 h-5" fill="currentColor"><!-- … --></svg>
|
||||
</a>
|
||||
<a href="#" class="bg-primary text-white p-3 rounded-full">
|
||||
<span class="sr-only">Instagram</span>
|
||||
<svg class="w-5 h-5" fill="currentColor"><!-- … --></svg>
|
||||
</a>
|
||||
<a href="#" class="bg-primary text-white p-3 rounded-full">
|
||||
<span class="sr-only">Facebook</span>
|
||||
<svg class="w-5 h-5" fill="currentColor"><!-- … --></svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</f:section>
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
.frame-type-cloonar_stats .stats-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
background: #fff;
|
||||
padding: 1rem;
|
||||
max-width: 1140px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
gap: 1rem; /* maintain gap on mobile */
|
||||
}
|
||||
|
||||
/* Two columns on mobile */
|
||||
.frame-type-cloonar_stats .stats-wrapper p {
|
||||
box-sizing: border-box;
|
||||
flex: 0 0 calc((100% - 1rem) / 2);
|
||||
max-width: calc((100% - 1rem) / 2);
|
||||
text-align: center;
|
||||
margin-bottom: 1rem;
|
||||
text-transform: uppercase;
|
||||
color: var(--bs-primary);
|
||||
}
|
||||
|
||||
.frame-type-cloonar_stats .stats-wrapper span.big-number {
|
||||
font-size: 4rem;
|
||||
font-family: 'Hajime Sans', sans-serif;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.frame-type-cloonar_stats .stats-wrapper {
|
||||
padding: 3rem 1rem;
|
||||
gap: 2rem; /* increase gap on desktop */
|
||||
}
|
||||
|
||||
/* Four columns on desktop */
|
||||
.frame-type-cloonar_stats .stats-wrapper p {
|
||||
flex: 0 0 calc((100% - 6rem) / 4); /* 3 gaps * 2rem = 6rem total gap */
|
||||
max-width: calc((100% - 6rem) / 4);
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,12 @@
|
||||
<f:section name="Header" />
|
||||
|
||||
<f:section name="Main">
|
||||
<f:asset.css identifier="CBStats" href="{cb:assetPath()}/frontend.css" />
|
||||
|
||||
<div class="stats-wrapper">
|
||||
<div class="relative z-10 bg-white p-4 md:py-12 md:px-4 max-w-6xl mx-auto grid grid-cols-2 md:grid-cols-4 gap-4 md:gap-8">
|
||||
<f:format.html>
|
||||
{data.bodytext}
|
||||
{data.bodytext -> f:format.raw() -> cb:processRichText(styles: [
|
||||
'p=text-center uppercase text-primary',
|
||||
'span.big-number=block text-6xl font-hajime normal-case'
|
||||
])}
|
||||
</f:format.html>
|
||||
</div>
|
||||
</f:section>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
/* CSS for text content element */
|
||||
.frame-type-cloonar_text .text-bodytext {
|
||||
max-width: 750px;
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
<f:layout name="Default" />
|
||||
<f:section name="Main">
|
||||
<f:asset.css identifier="CBText" href="{cb:assetPath()}/frontend.css" />
|
||||
<div class="fade-in-on-scroll">
|
||||
<f:if condition="{data.header}">
|
||||
<f:then><h2>{data.header}</h2></f:then>
|
||||
<f:then><h2 class="font-hajime text-primary font-normal leading-none text-3xl md:text-5xl mb-4">{data.header}</h2></f:then>
|
||||
</f:if>
|
||||
<f:if condition="{data.bodytext}">
|
||||
<f:then>
|
||||
<div class="text-bodytext"><f:format.html>{data.bodytext}</f:format.html></div>
|
||||
<div class="max-w-3xl prose lg:prose-lg">
|
||||
<f:format.html>{data.bodytext}</f:format.html>
|
||||
</div>
|
||||
</f:then>
|
||||
</f:if>
|
||||
</div>
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
.textimage-container {
|
||||
--gap: 2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--gap);
|
||||
}
|
||||
|
||||
.textimage-wrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.textimage-text {
|
||||
font-size: 1rem;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.textimage-image-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.textimage-picture {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.textimage-image {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Image positions: 25 = left, 26 = right */
|
||||
.textimage-container.image-pos-25 {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.textimage-container.image-pos-26 {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* On larger screens, arrange horizontally for image position settings */
|
||||
@media (min-width: 768px) {
|
||||
.textimage-container.size-25 {
|
||||
--gap: 8rem;
|
||||
}
|
||||
|
||||
.textimage-container.image-pos-25 {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.textimage-container.image-pos-26 {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.textimage-image-wrapper.size-25 {
|
||||
flex: 0 0 calc(40% - (var(--gap) / 2));
|
||||
max-width: calc(40% - (var(--gap) / 2));
|
||||
}
|
||||
.textimage-wrapper.size-25 {
|
||||
flex: 0 0 calc(40% - (var(--gap) / 2));
|
||||
max-width: calc(40% - (var(--gap) / 2));
|
||||
}
|
||||
|
||||
.textimage-image-wrapper.size-50 {
|
||||
flex: 0 0 calc(50% - (var(--gap) / 2));
|
||||
max-width: calc(50% - (var(--gap) / 2));
|
||||
}
|
||||
|
||||
.textimage-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
<f:layout name="Default" />
|
||||
|
||||
<f:section name="Header"></f:section>
|
||||
<f:section name="Main">
|
||||
<f:asset.css identifier="CBTextImage" href="{cb:assetPath()}/frontend.css" />
|
||||
<f:variable name="imageSizeClass" value="md:w-1/2" />
|
||||
<f:variable name="textSizeClass" value="md:w-1/2" />
|
||||
<f:variable name="gapClass" value="gap-8" />
|
||||
|
||||
<!-- Determine size class based on imagesize field -->
|
||||
<f:variable name="sizeClass" value="" />
|
||||
<f:if condition="{data.imagesize} == 1">
|
||||
<f:then><f:variable name="sizeClass" value="size-25" /></f:then>
|
||||
</f:if>
|
||||
<f:if condition="{data.imagesize} == 2">
|
||||
<f:then><f:variable name="sizeClass" value="size-50" /></f:then>
|
||||
<f:if condition="{data.imagesize} == 1"> <!-- Size 25% -> map to 40% for layout -->
|
||||
<f:variable name="imageSizeClass" value="md:w-2/5" />
|
||||
<f:variable name="textSizeClass" value="md:w-3/5" />
|
||||
<f:variable name="gapClass" value="gap-8 md:gap-16 lg:gap-32" />
|
||||
</f:if>
|
||||
|
||||
<div class="textimage-container image-pos-{data.imageorient} {sizeClass} fade-in-on-scroll">
|
||||
<div class="textimage-image-wrapper {sizeClass}">
|
||||
<div class="flex flex-col {gapClass} fade-in-on-scroll {f:if(condition: '{data.imageorient} == 26', then: 'md:flex-row-reverse', else: 'md:flex-row')}">
|
||||
<div class="flex items-center justify-center {imageSizeClass}">
|
||||
<f:if condition="{data.image}">
|
||||
<f:then>
|
||||
<figure class="textimage-picture">
|
||||
<figure class="block w-full">
|
||||
<!-- WEBP source -->
|
||||
<source
|
||||
type="image/webp"
|
||||
@@ -25,27 +23,23 @@
|
||||
{f:uri.image(image:data.image.0, width:'320c', cropVariant:'default', fileExtension:'webp')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'768c', cropVariant:'default', fileExtension:'webp')} 768w,
|
||||
{f:uri.image(image:data.image.0, width:'1024c', cropVariant:'default', fileExtension:'webp')} 1024w"
|
||||
sizes="(max-width: 320px) 90vw,
|
||||
(max-width: 768px) 600px,
|
||||
600px" />
|
||||
|
||||
sizes="(max-width: 767px) 90vw,
|
||||
{f:if(condition: '{data.imagesize} == 1', then: '(min-width: 768px) 40vw', else: '(min-width: 768px) 50vw')}" />
|
||||
<!-- Fallback source -->
|
||||
<source
|
||||
srcset="
|
||||
{f:uri.image(image:data.image.0, width:'320c', cropVariant:'default')} 320w,
|
||||
{f:uri.image(image:data.image.0, width:'400c', cropVariant:'default')} 768w,
|
||||
{f:uri.image(image:data.image.0, width:'538c', cropVariant:'default')} 1024w"
|
||||
sizes="(max-width: 320px) 90vw,
|
||||
(max-width: 768px) 600px,
|
||||
600px" />
|
||||
|
||||
sizes="(max-width: 767px) 90vw,
|
||||
{f:if(condition: '{data.imagesize} == 1', then: '(min-width: 768px) 40vw', else: '(min-width: 768px) 50vw')}" />
|
||||
<f:image
|
||||
image="{data.image.0}"
|
||||
treatIdAsReference="1"
|
||||
cropVariant="default"
|
||||
width="538c"
|
||||
alt="{data.image.0.alternative}"
|
||||
class="textimage-image"
|
||||
class="max-w-full h-auto rounded-lg block"
|
||||
/>
|
||||
</figure>
|
||||
</f:then>
|
||||
@@ -54,13 +48,13 @@
|
||||
</f:else>
|
||||
</f:if>
|
||||
</div>
|
||||
<div class="textimage-wrapper {sizeClass}">
|
||||
<div class="{textSizeClass}">
|
||||
<f:if condition="{data.header}">
|
||||
<h2 class="textimage-header">{data.header}</h2>
|
||||
<h3 class="textimage-subheader">{data.subheader}</h3>
|
||||
<h2 class="font-hajime text-primary font-normal leading-none text-3xl md:text-5xl mb-2">{data.header}</h2>
|
||||
<h3 class="text-xl md:text-2xl font-semibold mb-4">{data.subheader}</h3>
|
||||
</f:if>
|
||||
<f:if condition="{data.bodytext}">
|
||||
<div class="textimage-text">
|
||||
<div class="prose lg:prose-lg">
|
||||
<f:format.html>{data.bodytext}</f:format.html>
|
||||
</div>
|
||||
</f:if>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
<div class="frame frame-type-{data.CType}">
|
||||
<f:render section="Header" optional="true" />
|
||||
<f:render section="Main" optional="true" />
|
||||
</div>
|
||||
<f:section name="Header">
|
||||
<div class="header">
|
||||
<h2>{data.header}</h2>
|
||||
</div>
|
||||
</f:section>
|
||||
@@ -1,23 +1,29 @@
|
||||
<nav class="main-nav" id="mainNav">
|
||||
<div class="container">
|
||||
<nav class="main-nav group sticky top-0 z-50 bg-repeat" id="mainNav">
|
||||
<div class="container flex items-center h-full mx-auto px-4">
|
||||
<a href="/" class="nav-logo">
|
||||
<f:image src="EXT:base/Resources/Public/Images/logo.png" alt="Logo" />
|
||||
<f:image src="EXT:base/Resources/Public/Images/logo.png" alt="Logo" class="block max-h-[50px] h-auto w-auto" />
|
||||
</a>
|
||||
<button class="nav-toggle" id="navToggle" aria-label="Toggle Menu">
|
||||
<span class="nav-toggle-icon"></span>
|
||||
<button class="nav-toggle group lg:hidden relative w-[30px] h-[30px] cursor-pointer ml-auto bg-none border-none" id="navToggle" aria-label="Toggle Menu">
|
||||
<span class="nav-toggle-icon block relative w-full h-[2px] bg-primary transition-all duration-300
|
||||
before:content-[''] before:block before:absolute before:w-full before:h-[2px] before:bg-primary before:left-0 before:-top-[8px] before:transition-all before:duration-300
|
||||
after:content-[''] after:block after:absolute after:w-full after:h-[2px] after:bg-primary after:left-0 after:top-[8px] after:transition-all after:duration-300
|
||||
group-[.active]:bg-transparent group-[.active]:before:rotate-45 group-[.active]:before:translate-x-[5px] group-[.active]:before:translate-y-[5px]
|
||||
group-[.active]:after:-rotate-45 group-[.active]:after:translate-x-[5px] group-[.active]:after:-translate-y-[5px]"></span>
|
||||
</button>
|
||||
|
||||
<ul class="nav-links" id="navLinks">
|
||||
<ul class="nav-links flex items-center list-none mx-auto font-hajime text-primary
|
||||
lg:flex lg:relative lg:top-auto lg:left-auto lg:right-auto lg:flex-row lg:max-h-full lg:overflow-visible lg:bg-transparent
|
||||
absolute top-full left-0 right-0 flex-col max-h-0 overflow-hidden bg-white transition-max-height duration-400 ease-in-out group-[.open]:max-h-[500px]" id="navLinks">
|
||||
<f:for each="{mainnavigation}" as="mainnavigationItem">
|
||||
<li class="nav-item{f:if(condition: mainnavigationItem.active, then:' active')}{f:if(condition: mainnavigationItem.children, then:' has-submenu')}">
|
||||
<a href="{mainnavigationItem.link}" target="{mainnavigationItem.target}" title="{mainnavigationItem.title}">
|
||||
<li class="nav-item lg:mx-4 lg:my-0 lg:p-0 lg:border-0 mx-0 my-0 p-4 border-t border-black/10 first:border-t-0 {f:if(condition: mainnavigationItem.active, then:' active')}{f:if(condition: mainnavigationItem.children, then:' has-submenu')}">
|
||||
<a href="{mainnavigationItem.link}" target="{mainnavigationItem.target}" title="{mainnavigationItem.title}" class="nav-link block lg:inline-block no-underline text-primary font-bold uppercase tracking-[0.05em] text-sm transition-colors duration-300 hover:text-brand">
|
||||
{mainnavigationItem.title}
|
||||
</a>
|
||||
<f:if condition="{mainnavigationItem.children}">
|
||||
<ul class="sub-menu">
|
||||
<ul class="sub-menu hidden lg:absolute lg:block lg:opacity-0 lg:invisible lg:group-hover:opacity-100 lg:group-hover:visible lg:bg-white lg:shadow-md lg:mt-2 lg:py-2 lg:rounded lg:border lg:border-gray-200">
|
||||
<f:for each="{mainnavigationItem.children}" as="child">
|
||||
<li class="{f:if(condition: child.active, then:'active')}">
|
||||
<a class="nav-link" href="{child.link}" target="{child.target}" title="{child.title}">
|
||||
<li class="{f:if(condition: child.active, then:'active')} lg:px-4 lg:py-2 hover:bg-gray-100">
|
||||
<a class="nav-link block text-sm text-primary hover:text-brand" href="{child.link}" target="{child.target}" title="{child.title}">
|
||||
{child.title}
|
||||
</a>
|
||||
</li>
|
||||
|
||||
@@ -35,12 +35,6 @@ h1 {
|
||||
font-size: 4.5rem;
|
||||
}
|
||||
}
|
||||
h1 span.tapered {
|
||||
background-size: 100% 15%;
|
||||
background-repeat: repeat-x;
|
||||
background-position: left 0% bottom 15%;
|
||||
background-image: linear-gradient(179deg,var(--bs-yellow) 0%, var(--bs-yellow) 50%,transparent 54%, transparent 100%);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
|
||||
@@ -15,8 +15,6 @@ body > header {
|
||||
}
|
||||
|
||||
.main-nav {
|
||||
background: url('../Images/background.jpg') repeat;
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
/* Keep existing imports for now, comment out or remove as needed during conversion */
|
||||
@import 'abstracts/variables';
|
||||
@import 'abstracts/mixins';
|
||||
@import 'abstracts/fonts';
|
||||
|
||||
6
postcss.config.js
Normal file
6
postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
39
tailwind.config.js
Normal file
39
tailwind.config.js
Normal file
@@ -0,0 +1,39 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
const defaultTheme = require('tailwindcss/defaultTheme')
|
||||
|
||||
module.exports = {
|
||||
content: [
|
||||
"./packages/base/Resources/Private/**/*.html",
|
||||
"./packages/base/Resources/Private/**/*.js",
|
||||
"./packages/base/ContentBlocks/ContentElements/**/*.html",
|
||||
"./public/typo3conf/ext/*/Resources/Private/**/*.html",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
transitionProperty: {
|
||||
'max-height': 'max-height' // Add max-height to transition properties
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', ...defaultTheme.fontFamily.sans],
|
||||
hajime: ['"Hajime Sans"', ...defaultTheme.fontFamily.sans],
|
||||
},
|
||||
colors: {
|
||||
primary: {
|
||||
DEFAULT: '#0B197D', // Use SCSS primary color for text
|
||||
dark: '#1C2B00',
|
||||
light: '#4E5E32',
|
||||
'brand-blue': '#0B197D',
|
||||
},
|
||||
yellow: '#F5AE07',
|
||||
'light-green': '#F4F6EC',
|
||||
brand: '#6B8E23', // Added brand color for hover states from SCSS
|
||||
},
|
||||
maxHeight: {
|
||||
'0': '0',
|
||||
'[500px]': '500px', // Add specific max-height for mobile menu transition
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
}
|
||||
|
||||
@@ -15,6 +15,17 @@ module.exports = {
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
'css-loader',
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
options: {
|
||||
postcssOptions: {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
'sass-loader'
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user