24 Commits

Author SHA1 Message Date
9d4fad0889 fix: change back to current and make first release manual
All checks were successful
Build / build (push) Successful in 4m23s
Build / deploy-production (push) Successful in 4m50s
Build / deploy-stage (push) Successful in 5m0s
Build / switch-stage (push) Successful in 2m21s
Release / switch-production (push) Successful in 2m56s
2025-06-26 12:16:30 +02:00
9720b9328e fix: change to apt-get and change cache:flush to release from current, to work on first release
Some checks failed
Build / build (push) Successful in 4m16s
Build / deploy-stage (push) Successful in 3m42s
Build / switch-stage (push) Failing after 2m17s
Build / deploy-production (push) Successful in 3m56s
2025-06-26 11:55:16 +02:00
177d79ceb1 fix: change php version for deployment
Some checks failed
Build / build (push) Successful in 4m11s
Build / deploy-stage (push) Successful in 3m6s
Build / switch-stage (push) Successful in 2m4s
Build / deploy-production (push) Failing after 3m13s
2025-06-26 10:04:43 +02:00
b6ba7f24fe feat: deploy to production
Some checks failed
Build / build (push) Successful in 5m16s
Build / deploy-production (push) Failing after 2m24s
Build / deploy-stage (push) Failing after 2m3s
Build / switch-stage (push) Has been skipped
2025-06-26 09:47:50 +02:00
080bf9e186 fix: flush cache at deployment
All checks were successful
Build / build (push) Successful in 4m17s
Build / deploy-stage (push) Successful in 2m42s
Build / switch-stage (push) Successful in 2m8s
2025-06-23 17:19:24 +02:00
71d06aabd6 fix: flush cache before extension:setup
Some checks failed
Build / build (push) Successful in 4m22s
Build / deploy-stage (push) Failing after 2m29s
Build / switch-stage (push) Has been skipped
2025-06-23 17:10:43 +02:00
b65377dee4 fix: update card image styling for improved visibility and layout
Some checks failed
Build / build (push) Successful in 4m26s
Build / deploy-stage (push) Failing after 2m30s
Build / switch-stage (push) Has been skipped
2025-06-23 16:54:04 +02:00
c552021c35 fix: change back to columns
All checks were successful
Build / build (push) Successful in 4m20s
Build / deploy-stage (push) Successful in 2m38s
Build / switch-stage (push) Successful in 2m9s
2025-06-18 17:48:34 +02:00
1cd8e30a16 fix: change to imagecols
All checks were successful
Build / build (push) Successful in 4m19s
Build / deploy-stage (push) Successful in 2m43s
Build / switch-stage (push) Successful in 2m5s
2025-06-18 17:37:42 +02:00
6c602a4838 fix: remove not available view helper 2025-06-18 17:34:34 +02:00
37300492dc feat: add image gallery content element with configurable columns and backend preview
All checks were successful
Build / build (push) Successful in 4m21s
Build / deploy-stage (push) Successful in 2m41s
Build / switch-stage (push) Successful in 2m4s
2025-06-16 13:50:41 +02:00
c4d01f2a47 feat: update image size handling in textimage component for better layout control
All checks were successful
Build / build (push) Successful in 4m18s
Build / deploy-stage (push) Successful in 4m47s
Build / switch-stage (push) Successful in 2m3s
2025-06-16 12:44:31 +02:00
f36e0d7f72 fix: simplify DDEV command usage in setup instructions 2025-06-16 12:31:33 +02:00
e3c7a18505 feat: add TYPO3 project rules for LLM assistance 2025-06-05 00:13:52 +02:00
5effa2d89c feat: update ToDo list with new tasks for social media icons and footer links 2025-06-04 23:38:25 +02:00
c2da399a32 feat: update post-start hooks for npm commands and add mailpit service 2025-06-04 22:48:35 +02:00
f5dd861ef1 fix: deploy command order
All checks were successful
Build / build (push) Successful in 4m37s
Build / deploy-stage (push) Successful in 2m46s
Build / switch-stage (push) Successful in 2m10s
2025-05-23 19:13:09 +02:00
4a0628e25d feat: change navigation link size on desktop
Some checks failed
Build / build (push) Successful in 4m20s
Build / deploy-stage (push) Failing after 2m46s
Build / switch-stage (push) Has been skipped
2025-05-23 16:34:23 +02:00
f1e73d57f6 feat: change default mail settings to env
All checks were successful
Build / build (push) Successful in 4m13s
Build / deploy-stage (push) Successful in 2m46s
Build / switch-stage (push) Successful in 2m1s
2025-05-09 15:59:45 +02:00
af9b157622 feat: add option for sendmail command
All checks were successful
Build / build (push) Successful in 4m39s
Build / deploy-stage (push) Successful in 2m45s
Build / switch-stage (push) Successful in 2m6s
2025-05-09 15:46:13 +02:00
2e0980ca7e feat: change email and phone number
All checks were successful
Build / build (push) Successful in 4m9s
Build / deploy-stage (push) Successful in 2m43s
Build / switch-stage (push) Successful in 1m59s
2025-05-09 14:33:14 +02:00
592a76737b feat: comment out social media links, set links to datenschutz and impressum
All checks were successful
Build / build (push) Successful in 4m23s
Build / deploy-stage (push) Successful in 2m58s
Build / switch-stage (push) Successful in 2m7s
2025-04-25 15:13:47 +02:00
3fddfdff67 feat: accessibility and performance improvement
All checks were successful
Build / build (push) Successful in 4m17s
Build / deploy-stage (push) Successful in 3m23s
Build / switch-stage (push) Successful in 2m31s
2025-04-24 12:52:20 +02:00
edc2cf7634 fix: remove safelist entry which is not longer needed
All checks were successful
Build / build (push) Successful in 4m24s
Build / deploy-stage (push) Successful in 2m56s
Build / switch-stage (push) Successful in 2m8s
2025-04-23 23:21:36 +02:00
22 changed files with 443 additions and 81 deletions

View File

@@ -16,7 +16,10 @@ web_environment:
corepack_enable: false corepack_enable: false
nodejs_version: "18" nodejs_version: "18"
additional_services:
- mailpit
hooks: hooks:
post-start: post-start:
- exec: "npm install" - exec-host: |
- exec: "npm run dev:css" ddev npm install
ddev npm run dev:css -- --watch &

View File

@@ -1,9 +0,0 @@
version: '3.6'
services:
web:
# Install needed dependencies and run webpack in watch mode
command: /bin/sh -c "npm install && npm run build:css -- --watch"
volumes:
- ../packages/base:/var/www/html/packages/base
environment:
- NODE_ENV=development

View File

@@ -68,8 +68,8 @@ jobs:
rm typo3.tar.gz rm typo3.tar.gz
- name: Install ssh agent and rsync - name: Install ssh agent and rsync
run: | run: |
apt update apt-get update
apt install -y openssh-client rsync apt-get install -y openssh-client rsync
- name: Upload release - name: Upload release
uses: deployphp/action@v1 uses: deployphp/action@v1
with: with:
@@ -93,8 +93,8 @@ jobs:
rm typo3.tar.gz rm typo3.tar.gz
- name: Install ssh agent and rsync - name: Install ssh agent and rsync
run: | run: |
apt update apt-get update
apt install -y openssh-client rsync apt-get install -y openssh-client rsync
- name: Switch to release - name: Switch to release
uses: deployphp/action@v1 uses: deployphp/action@v1
with: with:
@@ -102,28 +102,28 @@ jobs:
dep: --file=./build/deploy.php release:switch stage dep: --file=./build/deploy.php release:switch stage
private-key: ${{secrets.STAGE_KEY}} private-key: ${{secrets.STAGE_KEY}}
# deploy-production: deploy-production:
# needs: build needs: build
# runs-on: ubuntu-latest runs-on: ubuntu-latest
# steps: steps:
# - name: Setup PHP - name: Setup PHP
# uses: shivammathur/setup-php@7c0b4c8c8ebed23eca9ec2802474895d105b11bc uses: shivammathur/setup-php@7c0b4c8c8ebed23eca9ec2802474895d105b11bc
# with: with:
# php-version: ${{ env.PHP_VERSION }} php-version: ${{ env.PHP_VERSION }}
# - uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
# with: with:
# name: typo3 name: typo3
# - name: Extract artifact - name: Extract artifact
# run: | run: |
# tar xf typo3.tar.gz tar xf typo3.tar.gz
# rm typo3.tar.gz rm typo3.tar.gz
# - name: Install ssh agent and rsync - name: Install ssh agent and rsync
# run: | run: |
# apt update apt-get update
# apt install -y openssh-client rsync apt-get install -y openssh-client rsync
# - name: Deploy - name: Deploy
# uses: deployphp/action@v1 uses: deployphp/action@v1
# with: with:
# deployer-binary: "./bin/dep" deployer-binary: "./bin/dep"
# dep: --file=./build/deploy.php release:create production dep: --file=./build/deploy.php release:create production
# private-key: ${{secrets.PROD_KEY}} private-key: ${{secrets.PROD_KEY}}

View File

@@ -26,8 +26,8 @@ jobs:
composer validate --no-check-publish && composer install --prefer-dist --no-progress --ignore-platform-reqs composer validate --no-check-publish && composer install --prefer-dist --no-progress --ignore-platform-reqs
- name: Install ssh agent, rsync - name: Install ssh agent, rsync
run: | run: |
apt update apt-get update
apt install -y openssh-client rsync apt-get install -y openssh-client rsync
- name: Switch to release - name: Switch to release
uses: deployphp/action@v1 uses: deployphp/action@v1
with: with:

163
.roo/rules/rules.md Normal file
View File

@@ -0,0 +1,163 @@
# TYPO3 Project Rules for LLM Assistance
## Project Overview
This project is a TYPO3 installation with a custom site-package extension located in [`packages/base`](packages/base), providing layout, templates, and modular ContentBlocks for pages. The LLM should dynamically determine the TYPO3 version and related dependencies by examining project files.
## Technology Stack
- PHP (version defined in [`composer.json`](composer.json))
- TYPO3 (version defined in [`composer.json`](composer.json))
- Composer ([`composer.json`](composer.json))
- Deployer ([`build/deploy.php`](build/deploy.php), [`build/servers.yaml`](build/servers.yaml))
- Webpack ([`webpack.config.js`](webpack.config.js))
- PostCSS ([`postcss.config.js`](postcss.config.js)) with Tailwind CSS (version defined in [`package.json`](package.json)) and Autoprefixer
- SCSS (`packages/base/Resources/Public/Scss/`)
- JavaScript bundling (`packages/base/Resources/Public/JavaScript/`)
- PHPStan, Rector (`phpstan.neon`, `rector.php`)
- YAML and TypoScript for configuration
## Project Structure
- [`config/`](config/): Global TYPO3 config and environment overrides
- [`data/`](data/): Database dumps and test fixtures
- [`packages/base/`](packages/base/): Site-package extension with design assets, Fluid templates, TypoScript, ContentBlocks
- [`public/`](public/): Document root
- Build files: [`webpack.config.js`](webpack.config.js), [`postcss.config.js`](postcss.config.js)
- Dependency manifests: [`package.json`](package.json), [`composer.json`](composer.json)
## Development Guidelines
- Use DDEV for local environment management: `ddev start`, `ddev restart`, `ddev stop`, etc.
- Check versions in [`composer.json`](composer.json) and [`package.json`](package.json) before referencing dependencies; the LLM should examine these files to determine actual versions
- Manage PHP dependencies via Composer within DDEV: `ddev exec composer install`, `ddev exec composer update`
- Manage JS/CSS via npm within DDEV: `ddev exec npm install`, `ddev exec npm run dev` / `ddev exec npm run build`
- Follow TYPO3 extension conventions in [`packages/base`](packages/base): `ext_localconf.php`, `ext_tables.php`, `ext_emconf.php`
- Organize TypoScript under [`packages/base/Configuration/Sets/SitePackage/TypoScript/`](packages/base/Configuration/Sets/SitePackage/TypoScript/)
- Enforce static analysis and automated refactoring with PHPStan and Rector
## Default Workflow
When handling any task, LLMs should follow this structured approach:
1. **Information Gathering**
- Read the necessary code from the project using available tools
- Examine [`composer.json`](composer.json) and [`package.json`](package.json) to understand current dependencies and versions
- Use MCP servers to read documentation about libraries that are used and should be used
- Review relevant project files to understand the current implementation
- Gather context about the specific area of the codebase that will be affected
2. **Planning**
- Analyze the gathered information to understand the task requirements
- Plan how the task should be implemented within the existing project structure
- Consider potential impacts on other parts of the codebase
- Identify which files need to be created, modified, or reviewed
- Determine the best approach that follows project conventions and best practices
3. **Implementation**
- Execute the planned task using appropriate tools
- Follow the project's coding standards and conventions
- Test the implementation where possible
- Ensure all changes work within the existing project structure
4. **Documentation Updates**
- Update project documentation (README files) if the task affects user-facing functionality
- Update these rules ([`.roo/rules/rules.md`](.roo/rules/rules.md)) if the task introduces new patterns, conventions, or important information that future LLMs should know
- Ensure any new features or changes are properly documented for future reference
This workflow ensures thorough understanding, proper planning, clean implementation, and maintained documentation for all project changes.
## ContentBlocks Usage
- Defined under [`packages/base/ContentBlocks/ContentElements/`](packages/base/ContentBlocks/ContentElements/)
- Element folder contains:
- `config.yaml` (block definition)
- `templates/frontend.html` (frontend rendering)
- `templates/backend-preview.html` (backend preview)
- `language/labels.xlf` (translations)
- To add a new block:
1. Create a folder under `ContentElements/`
2. Define `config.yaml` and labels
3. Add Fluid templates in `templates/`
4. Clear caches and verify in TYPO3 backend (`ddev exec vendor/bin/typo3cms cache:flush`)
- Content element restrictions:
- ContentBlocks are automatically registered via their YAML config files
- Availability is controlled through PageTSconfig using `TCEFORM.tt_content.CType.keepItems`
- The `keepItems` list in [`packages/base/Configuration/Sets/SitePackage/page.tsconfig`](packages/base/Configuration/Sets/SitePackage/page.tsconfig) determines which content elements editors can use
- To enable a new ContentBlock, add its CType to the `keepItems` list
- Clear caches after changes
## Styling Guidelines
- All design work lives in the [`packages/base`](packages/base) extension
- SCSS structure in `Resources/Public/Scss/`:
- `abstracts/` (variables, mixins, functions)
- `base/` (resets, global styles)
- `components/` (UI modules: buttons, cards, nav, etc.)
- `layouts/` (page-specific styles)
- Include Tailwind directives in `main.scss`:
```scss
@tailwind base;
@tailwind components;
@tailwind utilities;
```
- Customize Tailwind in [`tailwind.config.js`](tailwind.config.js)
## Build Process
1. Compile SCSS → PostCSS (Tailwind + Autoprefixer) → CSS in `Resources/Public/Css/` (within DDEV: `ddev exec npm run build:css`)
2. Bundle JS via Webpack → `Resources/Public/JavaScript/` (within DDEV: `ddev exec npm run build:js`)
3. Run dev mode: `ddev exec npm run dev`
4. Run production build: `ddev exec npm run build`
5. Deploy via Deployer: `ddev exec vendor/bin/dep deploy`
## File Editing Guidelines
- TypoScript: `packages/base/Configuration/Sets/SitePackage/TypoScript/`
- YAML: `packages/base/Configuration/**/*.yaml`
- Fluid templates: `packages/base/Resources/Private/**/*.html`
- SCSS: `packages/base/Resources/Public/Scss/**/*.scss`
- JavaScript: `packages/base/Resources/Public/JavaScript/**/*.js`
- Never read or commit the environment file: [`.env`](.env)
## MCP Server Usage
- Use `brave_web_search` for general web searches via `use_mcp_tool`
- Use `resolve-library-id` + `get-library-docs` for official API docs:
- `/typo3/docs` for TYPO3 reference
- `/tailwindcss` for Tailwind CSS docs
- For NixOS/Home Manager queries: use `nixos_search`, `home_manager_search`
## Version Management
- Always inspect [`composer.json`](composer.json) for PHP dependencies and TYPO3 version
- Always inspect [`package.json`](package.json) for frontend dependencies
- Use MCP servers (e.g., `resolve-library-id`, `get-library-docs`) to fetch documentation matching the exact versions found
- Never assume specific dependency versions in code examples; dynamically reference versions as discovered
## Common Tasks
1. **Initial Setup**
```bash
ddev start
ddev composer install
ddev npm install
```
2. **Development Build**
```bash
ddev npm run dev
```
3. **Production Build**
```bash
ddev npm run build
```
4. **Clear TYPO3 Cache**
```bash
ddev typo3cms cache:flush
```
5. **Add a ContentBlock**
- Create folder, config, templates, translations
- Add the new ContentBlock's CType to the `keepItems` list in [`packages/base/Configuration/Sets/SitePackage/page.tsconfig`](packages/base/Configuration/Sets/SitePackage/page.tsconfig)
- Clear caches and verify in backend
6. **DDEV Environment Management**
- Restart environment: `ddev restart`
- Stop environment: `ddev stop`
7. **Deploy**
```bash
ddev exec vendor/bin/dep deploy production
```
## Troubleshooting
- **Blank CSS/JS**: confirm build pipeline ran; check [`webpack.config.js`](webpack.config.js)
- **YAML Syntax Errors**: validate `config.yaml` with a linter
- **Fluid Rendering Issues**: clear caches; verify template paths
- **TypoScript Not Loading**: ensure correct path under `Configuration/Sets`
- **Cache Problems**: always flush caches after changes

View File

@@ -2,3 +2,5 @@
[x] unordered list design [x] unordered list design
[x] check if marker design of ul and ol use em instead of rem for sizing [x] check if marker design of ul and ol use em instead of rem for sizing
[x] navbar should be sticky on mobile [x] navbar should be sticky on mobile
[ ] disable social media icons
[ ] footer links zu datenschutz und impressum

View File

@@ -55,16 +55,16 @@ set('rsync', [
'timeout' => 300 'timeout' => 300
]); ]);
task('typo3:extension:setup', function () {
cd('{{release_path}}');
run('{{bin/php}} bin/typo3 extension:setup');
});
task('typo3:cache:flush', function() { task('typo3:cache:flush', function() {
cd('current'); cd('current');
run('{{bin/php}} bin/typo3 cache:flush'); run('{{bin/php}} bin/typo3 cache:flush');
}); });
task('typo3:extension:setup', function () {
cd('{{release_path}}');
run('{{bin/php}} bin/typo3 extension:setup');
});
task('typo3:cache:warmup', function() { task('typo3:cache:warmup', function() {
cd('current'); cd('current');
run('{{bin/php}} bin/typo3 cache:warmup'); run('{{bin/php}} bin/typo3 cache:warmup');
@@ -94,6 +94,7 @@ task('release:create', [
'deploy:vendors', 'deploy:vendors',
'deploy:shared', 'deploy:shared',
'deploy:writable', 'deploy:writable',
'typo3:cache:flush',
'typo3:extension:setup', 'typo3:extension:setup',
'deploy:unlock', 'deploy:unlock',
'deploy:success' 'deploy:success'
@@ -117,6 +118,7 @@ task('deploy', [
'deploy:vendors', 'deploy:vendors',
'deploy:shared', 'deploy:shared',
'deploy:writable', 'deploy:writable',
'typo3:cache:flush',
'typo3:extension:setup', 'typo3:extension:setup',
'deploy:symlink', 'deploy:symlink',
'php:reload', 'php:reload',

View File

@@ -23,6 +23,7 @@ $customChanges = [
'transport_smtp_encrypt' => $_ENV['TYPO3_MAIL_SMTP_ENCRYPT'], 'transport_smtp_encrypt' => $_ENV['TYPO3_MAIL_SMTP_ENCRYPT'],
'transport_smtp_username' => $_ENV['TYPO3_MAIL_SMTP_USER'], 'transport_smtp_username' => $_ENV['TYPO3_MAIL_SMTP_USER'],
'transport_smtp_password' => $_ENV['TYPO3_MAIL_SMTP_PASSWORD'], 'transport_smtp_password' => $_ENV['TYPO3_MAIL_SMTP_PASSWORD'],
'transport_sendmail_command' => $_ENV['TYPO3_MAIL_SENDMAIL_COMMAND'],
], ],
'SYS' => [ 'SYS' => [
'caching' => [ 'caching' => [

View File

@@ -112,11 +112,14 @@ return [
'processor_path' => '/run/current-system/sw/bin/', 'processor_path' => '/run/current-system/sw/bin/',
], ],
'MAIL' => [ 'MAIL' => [
'defaultMailFromAddress' => 'no-reply@example.com', 'defaultMailFromAddress' => $_ENV['TYPO3_MAIL_FROM'],
'transport_smtp_encrypt' => false, 'transport' => $_ENV['TYPO3_MAIL_TRANSPORT'],
'transport_smtp_password' => '', 'transport_smtp_server' => $_ENV['TYPO3_MAIL_SMTP_SERVER'],
'transport_smtp_server' => '', 'transport_smtp_encrypt' => $_ENV['TYPO3_MAIL_SMTP_ENCRYPT'],
'transport_smtp_username' => '', 'transport_smtp_username' => $_ENV['TYPO3_MAIL_SMTP_USER'],
'transport_smtp_password' => $_ENV['TYPO3_MAIL_SMTP_PASSWORD'],
'transport_sendmail_command' => $_ENV['TYPO3_MAIL_SENDMAIL_COMMAND'],
'transport_sendmail_command' => $_ENV['TYPO3_MAIL_SENDMAIL_COMMAND'],
], ],
'SYS' => [ 'SYS' => [
'caching' => [ 'caching' => [

View File

@@ -3,7 +3,7 @@
"version": "1.0.0", "version": "1.0.0",
"scripts": { "scripts": {
"build:css": "NODE_ENV=production webpack --config webpack.config.js --mode production", "build:css": "NODE_ENV=production webpack --config webpack.config.js --mode production",
"dev:css": "webpack --config webpack.config.js --mode development" "dev:css": "webpack --config webpack.config.js --mode development --watch"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^10.4.21", "autoprefixer": "^10.4.21",

View File

@@ -9,7 +9,7 @@ RTE {
TCEFORM { TCEFORM {
tt_content { tt_content {
CType { CType {
keepItems = cloonar_text,cloonar_textimage,cloonar_hero,cloonar_cards,form_formframework keepItems = cloonar_text,cloonar_textimage,cloonar_hero,cloonar_cards,cloonar_imagegallery,form_formframework
} }
} }
} }

View File

@@ -25,7 +25,33 @@
<div class="card-front absolute w-full h-full backface-hidden overflow-hidden shadow-lg"> <div class="card-front absolute w-full h-full backface-hidden overflow-hidden shadow-lg">
<f:if condition="{card.images}"> <f:if condition="{card.images}">
<f:then> <f:then>
<f:image image="{card.images.0}" alt="{card.images.0.alternative}" class="w-full h-full object-cover grayscale group-hover:grayscale-0 transition-all duration-500" /> <picture class="w-full h-full object-cover transition-all duration-500">
<!-- WEBP source -->
<source
type="image/webp"
srcset="
{f:uri.image(image:card.images.0, width:'320c', cropVariant:'default', fileExtension:'webp')} 320w,
{f:uri.image(image:card.images.0, width:'768c', cropVariant:'default', fileExtension:'webp')} 768w,
{f:uri.image(image:card.images.0, width:'1024c', cropVariant:'default', fileExtension:'webp')} 1024w"
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:card.images.0, width:'320c', cropVariant:'default')} 320w,
{f:uri.image(image:card.images.0, width:'400c', cropVariant:'default')} 768w,
{f:uri.image(image:card.images.0, width:'538c', cropVariant:'default')} 1024w"
sizes="(max-width: 767px) 90vw,
{f:if(condition: '{data.imagesize} == 1', then: '(min-width: 768px) 40vw', else: '(min-width: 768px) 50vw')}" />
<f:image
image="{card.images.0}"
treatIdAsReference="1"
cropVariant="default"
width="538c"
alt="{card.images.0.alternative}"
class="w-full h-full object-cover"
/>
</picture>
</f:then> </f:then>
<f:else> <f:else>
<div class="w-full h-full bg-gray-300 flex items-center justify-center"> <div class="w-full h-full bg-gray-300 flex items-center justify-center">
@@ -33,9 +59,9 @@
</div> </div>
</f:else> </f:else>
</f:if> </f:if>
<div class="absolute inset-0 bg-black bg-opacity-40 flex flex-col items-center justify-center"> <div class="absolute inset-0 bg-white bg-opacity-80 flex flex-col items-center justify-center">
<div class="w-full"> <div class="w-full">
<h3 class="text-white text-xl font-bold text-center px-4">{card.header}</h3> <h3 class="text-black text-xl font-bold text-center px-4">{card.header}</h3>
</div> </div>
<div class="w-full text-center"> <div class="w-full text-center">
<div class="w-6 h-6 bg-primary text-white rounded-full inline-flex items-center justify-center"> <div class="w-6 h-6 bg-primary text-white rounded-full inline-flex items-center justify-center">
@@ -46,7 +72,7 @@
</div> </div>
<div class="card-back absolute w-full h-full backface-hidden rotate-y-180 bg-light-grey border border-dark-grey p-6"> <div class="card-back absolute w-full h-full backface-hidden rotate-y-180 bg-light-grey border border-dark-grey p-6">
<h4>{card.header}</h4> <h4 class="text-center">{card.header}</h4>
<div class="text-sm"> <div class="text-sm">
<f:format.html>{card.bodytext}</f:format.html> <f:format.html>{card.bodytext}</f:format.html>
</div> </div>

View File

@@ -78,18 +78,20 @@
<f:format.html>{data.bodytext}</f:format.html> <f:format.html>{data.bodytext}</f:format.html>
</div> </div>
<f:comment>
<!-- Social icons --> <!-- Social icons -->
<div class="space-x-3"> <div class="space-x-3">
<a href="#" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white"> <a href="#" aria-label="LinkedIn" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white">
<i class="ci ci-linkedin"></i> <i class="ci ci-linkedin"></i>
</a> </a>
<a href="#" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white"> <a href="#" aria-label="Instagram" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white">
<i class="ci ci-instagram"></i> <i class="ci ci-instagram"></i>
</a> </a>
<a href="#" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white"> <a href="#" aria-label="Facebook" class="w-6 h-6 md:w-10 md:h-10 bg-primary text-white rounded-full inline-flex items-center justify-center hover:bg-primary-dark hover:text-white">
<i class="ci ci-facebook"></i> <i class="ci ci-facebook"></i>
</a> </a>
</div> </div>
</f:comment>
</div> </div>
</div> </div>

View File

@@ -0,0 +1,26 @@
name: cloonar/imagegallery
typeName: cloonar_imagegallery
group: default
prefixFields: false
fields:
- identifier: header
useExistingField: true
- identifier: image
type: File
properties:
allowed: [jpg, jpeg, png, gif, webp]
multiple: true
useExistingField: true
- identifier: columns
type: Select
renderType: selectSingle
default: 1
items:
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.1
value: 1
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.2
value: 2
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.3
value: 3
- label: LLL:EXT:base/ContentBlocks/ContentElements/imagegallery/language/labels.xlf:columns.5
value: 5

View File

@@ -0,0 +1,26 @@
<?xml version="1.0"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file datatype="plaintext" original="labels.xlf" source-language="en" product-name="cloonar/imagegallery">
<header/>
<body>
<trans-unit id="title">
<source>Image Gallery</source>
</trans-unit>
<trans-unit id="description">
<source>A gallery of images with configurable columns</source>
</trans-unit>
<trans-unit id="columns.1">
<source>1 Column</source>
</trans-unit>
<trans-unit id="columns.2">
<source>2 Columns</source>
</trans-unit>
<trans-unit id="columns.3">
<source>3 Columns</source>
</trans-unit>
<trans-unit id="columns.5">
<source>5 Columns</source>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -0,0 +1,36 @@
<html
xmlns:be="http://typo3.org/ns/TYPO3/CMS/Backend/ViewHelpers"
data-namespace-typo3-fluid="true"
>
<f:layout name="Preview"/>
<f:section name="Header">
<be:link.editRecord uid="{data.uid}" table="{data.mainType}">
<f:if condition="{data.header}">
<f:then><strong>{data.header}</strong></f:then>
</f:if>
</be:link.editRecord>
</f:section>
<f:section name="Content">
<f:if condition="{data.image}">
<div class="row">
<f:for each="{data.image}" as="image" iteration="iterator">
<f:if condition="{iterator.index} < 3">
<div class="col-4">
<f:image image="{image}" width="100" height="auto" treatIdAsReference="1" alt="Preview image" />
</div>
</f:if>
</f:for>
</div>
<p>
<f:switch expression="{data.columns}">
<f:case value="2">2 Columns</f:case>
<f:case value="3">3 Columns</f:case>
<f:case value="5">5 Columns</f:case>
<f:defaultCase>1 Column</f:defaultCase>
</f:switch>
</p>
</f:if>
</f:section>
</html>

View File

@@ -0,0 +1,63 @@
<f:layout name="Default" />
<f:section name="Header"></f:section>
<f:section name="Main">
<f:if condition="{data.header}">
<h2 class="text-center mb-8">{data.header}</h2>
</f:if>
<f:if condition="{data.image}">
<f:variable name="columnClass">
<f:switch expression="{data.columns}">
<f:case value="2">md:grid-cols-2</f:case>
<f:case value="3">md:grid-cols-3</f:case>
<f:case value="5">md:grid-cols-5</f:case>
<f:defaultCase>md:grid-cols-1</f:defaultCase>
</f:switch>
</f:variable>
<div class="grid grid-cols-1 {columnClass} gap-6 md:gap-8">
<f:for each="{data.image}" as="image">
<div class="relative">
<f:if condition="{image.link}">
<f:then>
<f:link.typolink parameter="{image.link}" class="block w-full h-full">
<picture class="block w-full h-full">
<source
type="image/webp"
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default', fileExtension:'webp')} 320w,
{f:uri.image(image:image, width:'768', cropVariant:'default', fileExtension:'webp')} 768w"
sizes="(max-width: 767px) 90vw, 33vw" />
<img
src="{f:uri.image(image:image, width:'768', cropVariant:'default')}"
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default')} 320w,
{f:uri.image(image:image, width:'768', cropVariant:'default')} 768w"
sizes="(max-width: 767px) 90vw, 33vw"
alt="{image.alternative}"
class="w-full h-full object-cover"
/>
</picture>
</f:link.typolink>
</f:then>
<f:else>
<picture class="block w-full h-full">
<source
type="image/webp"
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default', fileExtension:'webp')} 320w,
{f:uri.image(image:image, width:'768', cropVariant:'default', fileExtension:'webp')} 768w"
sizes="(max-width: 767px) 90vw, 33vw" />
<img
src="{f:uri.image(image:image, width:'768', cropVariant:'default')}"
srcset="{f:uri.image(image:image, width:'320', cropVariant:'default')} 320w,
{f:uri.image(image:image, width:'768', cropVariant:'default')} 768w"
sizes="(max-width: 767px) 90vw, 33vw"
alt="{image.alternative}"
class="w-full h-full object-cover"
/>
</picture>
</f:else>
</f:if>
</div>
</f:for>
</div>
</f:if>
</f:section>

View File

@@ -21,9 +21,11 @@ fields:
- identifier: imagesize - identifier: imagesize
type: Select type: Select
renderType: selectSingle renderType: selectSingle
default: 2 default: 3
items: items:
- label: 25% - label: 25%
value: 1 value: 1
- label: 33%
value: 2
- label: 50% - label: 50%
value: 2 value: 3

View File

@@ -5,10 +5,16 @@
<f:variable name="textSizeClass" value="md:w-1/2" /> <f:variable name="textSizeClass" value="md:w-1/2" />
<f:variable name="gapClass" value="gap-8 md:gap-16" /> <f:variable name="gapClass" value="gap-8 md:gap-16" />
<f:if condition="{data.imagesize} == 1"> <!-- Size 25% -> map to 40% for layout --> <f:if condition="{data.imagesize} == 1"> <!-- Size 25% -->
<f:variable name="imageSizeClass" value="md:w-2/5" /> <f:variable name="imageSizeClass" value="md:w-1/4" />
<f:variable name="textSizeClass" value="md:w-3/5" /> <f:variable name="textSizeClass" value="md:w-3/4" />
<f:variable name="gapClass" value="gap-8 md:gap-16 lg:gap-32" /> <f:variable name="gapClass" value="gap-6 md:gap-12" />
</f:if>
<f:if condition="{data.imagesize} == 2"> <!-- Size 33% -->
<f:variable name="imageSizeClass" value="md:w-1/3" />
<f:variable name="textSizeClass" value="md:w-2/3" />
<f:variable name="gapClass" value="gap-8 md:gap-16" />
</f:if> </f:if>
<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 flex-col {gapClass} fade-in-on-scroll {f:if(condition: '{data.imageorient} == 26', then: 'md:flex-row-reverse', else: 'md:flex-row')}">
@@ -24,7 +30,11 @@
{f:uri.image(image:data.image.0, width:'768c', cropVariant:'default', fileExtension:'webp')} 768w, {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" {f:uri.image(image:data.image.0, width:'1024c', cropVariant:'default', fileExtension:'webp')} 1024w"
sizes="(max-width: 767px) 90vw, sizes="(max-width: 767px) 90vw,
{f:if(condition: '{data.imagesize} == 1', then: '(min-width: 768px) 40vw', else: '(min-width: 768px) 50vw')}" /> {f:if(condition: '{data.imagesize} == 1',
then: '(min-width: 768px) 25vw',
else: f:if(condition: '{data.imagesize} == 2',
then: '(min-width: 768px) 33vw',
else: '(min-width: 768px) 50vw'))}" />
<!-- Fallback source --> <!-- Fallback source -->
<source <source
srcset=" srcset="
@@ -32,7 +42,11 @@
{f:uri.image(image:data.image.0, width:'400c', cropVariant:'default')} 768w, {f:uri.image(image:data.image.0, width:'400c', cropVariant:'default')} 768w,
{f:uri.image(image:data.image.0, width:'538c', cropVariant:'default')} 1024w" {f:uri.image(image:data.image.0, width:'538c', cropVariant:'default')} 1024w"
sizes="(max-width: 767px) 90vw, sizes="(max-width: 767px) 90vw,
{f:if(condition: '{data.imagesize} == 1', then: '(min-width: 768px) 40vw', else: '(min-width: 768px) 50vw')}" /> {f:if(condition: '{data.imagesize} == 1',
then: '(min-width: 768px) 25vw',
else: f:if(condition: '{data.imagesize} == 2',
then: '(min-width: 768px) 33vw',
else: '(min-width: 768px) 50vw'))}" />
<f:image <f:image
image="{data.image.0}" image="{data.image.0}"
treatIdAsReference="1" treatIdAsReference="1"

View File

@@ -22,26 +22,27 @@
<!-- Kontaktiere uns --> <!-- Kontaktiere uns -->
<div> <div>
<h5 class="text-white">Kontaktiere uns</h5> <h3 class="text-white text-sm">Kontaktiere uns</h3>
<ul class="space-y-4"> <ul class="space-y-4">
<li class="flex items-center"> <li class="flex items-center pl-0">
<!-- mail --> <!-- mail -->
<a href="mailto:inquiry@dialogrelations.com" class="hover:text-white text-white"> <a href="mailto:office@dialog-relations.at" class="hover:text-white text-white">
inquiry@dialogrelations.com office@dialog-relations.at
</a> </a>
</li> </li>
<li class="flex items-center"> <li class="flex items-center pl-0">
<!-- phone --> <!-- phone -->
<a href="tel:+4312313435" class="hover:text-white text-white"> <a href="tel:+436763533669" class="hover:text-white text-white">
+43 1231 3435 +43 676 3533669
</a> </a>
</li> </li>
</ul> </ul>
</div> </div>
<f:comment>
<!-- Folge uns --> <!-- Folge uns -->
<div class="flex flex-col items-start md:items-end"> <div class="flex flex-col items-start md:items-end">
<h5 class="text-white">Folge uns</h5> <h3 class="text-white text-sm">Folge uns</h3>
<div class="flex space-x-4"> <div class="flex space-x-4">
<!-- Social buttons --> <!-- Social buttons -->
@@ -56,6 +57,7 @@
</a> </a>
</div> </div>
</div> </div>
</f:comment>
</div><!-- /Row 1 --> </div><!-- /Row 1 -->
@@ -70,9 +72,9 @@
<!-- Privacy links --> <!-- Privacy links -->
<p> <p>
<a href="#" class="hover:text-white text-white">Privacy Policy</a> <a href="/datenschutz" class="hover:text-white text-white">Datenschutz</a>
<span class="mx-1">|</span> <span class="mx-1">|</span>
<a href="#" class="hover:text-white text-white">Terms and Conditions</a> <a href="/impressum" class="hover:text-white text-white">Impressum</a>
</p> </p>
</div><!-- /Row 2 --> </div><!-- /Row 2 -->

View File

@@ -16,7 +16,7 @@
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"> 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"> <f:for each="{mainnavigation}" as="mainnavigationItem">
<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')}"> <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')}">
<a href="{mainnavigationItem.link}" title="{mainnavigationItem.title}" class="nav-link block lg:inline-block no-underline text-primary lg:text-white font-bold uppercase tracking-[0.05em] text-sm transition-colors duration-300 hover:text-primary lg:hover:text-white"> <a href="{mainnavigationItem.link}" title="{mainnavigationItem.title}" class="nav-link block lg:inline-block no-underline text-primary lg:text-white font-bold uppercase tracking-[0.05em] text-sm md:text-base transition-colors duration-300 hover:text-primary lg:hover:text-white">
{mainnavigationItem.title} {mainnavigationItem.title}
</a> </a>
</li> </li>

View File

@@ -19,7 +19,7 @@ const config = {
...safelist, ...safelist,
] : [ ] : [
'md:col-span-6', 'md:col-span-6',
{ {
pattern: /col-span-\d+/, pattern: /col-span-\d+/,
variants: ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] // Include other variants (sm, lg) if needed variants: ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'] // Include other variants (sm, lg) if needed
}, },