Compare commits

..

1 commit

Author SHA1 Message Date
bf11292a85
Switch to Symfony UX Twig Components, Icons and Stimulus
All checks were successful
Quality Check / QS Backend (push) Successful in 17s
Quality Check / QS Frontend (push) Successful in 34s
2024-07-21 20:39:34 +02:00
51 changed files with 6538 additions and 2234 deletions

View file

@ -1,6 +0,0 @@
{
"name": "Euph Website",
"image": "git.euph.dev/development_tools/symfony:latest",
"forwardPorts": [8080],
workspaceMount: ""
}

View file

@ -48,21 +48,3 @@ jobs:
- name: "PHP Stan" - name: "PHP Stan"
working-directory: app working-directory: app
run: "vendor/bin/phpstan analyze" run: "vendor/bin/phpstan analyze"
qs_mixed:
name: "QS Mixed"
runs-on: "ubuntu-latest"
container:
image: "git.euph.dev/actions/runner-php-8.3:latest"
steps:
- name: "Checkout"
uses: "https://git.euph.dev/actions/checkout@v3"
- name: "Install Dependencies"
working-directory: app
run: |
parallel --halt soon,fail=1 ::: \
"composer check-platform-reqs && composer install --no-scripts --audit" \
"npm install --no-fund"
- name: "Lint"
working-directory: app
run: "node node_modules/eslint/bin/eslint.js frontend"

View file

@ -1,8 +1,8 @@
_default: _default:
@bin/just/choose.sh {{ source_file() }} choose @bin/just/choose.sh {{ source_file() }} choose
mod backend mod backend 'app/backend/mod.just'
mod frontend mod frontend 'app/frontend/mod.just'
alias i := install alias i := install
alias start := up alias start := up
@ -69,7 +69,7 @@ lint linter="":
just frontend::lint all && just backend::lint;; just frontend::lint all && just backend::lint;;
*PHP*) just backend::lint ;; *PHP*) just backend::lint ;;
*TS*) just frontend::lint TS ;; *TS*) just frontend::lint TS ;;
*SCSS*) just frontend::lint all SCSS ;; *SCSS*) just frontend::lint SCSS ;;
*Twig*) just frontend::lint TWIG ;; *Twig*) just frontend::lint TWIG ;;
esac esac

View file

@ -0,0 +1,13 @@
<svg
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
xml:space="preserve"
width="32mm"
height="32mm"
viewBox="0 0 32 32"
>
<path
d="M16 0A16 16 0 0 0 0 16a16 16 0 0 0 16 16 16 16 0 0 0 16-16A16 16 0 0 0 16 0zm-.555 1.034 3.304 3.302a7.95 7.95 0 0 1 0 11.243l-2.97 2.971a4.364 4.364 0 0 0 0 6.174l7.852-7.852a8.532 8.532 0 0 0 1.868-4.747l.079-1.093c2.55 2.82 1.891 7.774.267 9.398l-10.47 10.537L6.5 22.09a8.566 8.566 0 0 1 0-12.114l8.945-8.943zm.03 5.936-6.23 6.226a3.512 3.512 0 0 0 0 4.966l.508.507 6.07-6.07a3.732 3.732 0 0 0 0-5.28l-.348-.35z"
fill="currentColor"
/>
</svg>

After

Width:  |  Height:  |  Size: 664 B

View file

@ -27,7 +27,7 @@ final readonly class TestController
{ {
return new Response( return new Response(
$this->twig->render( $this->twig->render(
'index.html.twig' 'sites/index.html.twig'
) )
); );
} }

View file

@ -1,17 +1,19 @@
__default: __default:
@../bin/just/choose.sh {{ source_file() }} choose @../../bin/just/choose.sh {{ source_file() }} choose
# Checks whether the requriements are met # Checks whether the requriements are met
[group('main')] [group('main')]
check: check:
#!/bin/bash #!/bin/bash
source ../bin/just/colors.sh source ../../bin/just/colors.sh
source ../bin/just/check.sh source ../../bin/just/check.sh
printf "${BLUE_BG}${BLACK_FG} Checking Backend Requirements ${CLEAR}\n" printf "${BLUE_BG}${BLACK_FG} Checking Backend Requirements ${CLEAR}\n"
cd .. cd ..
check_cmd "php" "Php" check_cmd "php" "Php"
check_cmd "composer" "Composer" check_cmd "composer" "Composer"
check_cmd "symfony" "Symfony cli"
current_composer_version=$(composer --version 2>/dev/null | awk '{print $3}' | cut -d '.' -f 1) current_composer_version=$(composer --version 2>/dev/null | awk '{print $3}' | cut -d '.' -f 1)
if [ "${current_composer_version}" = "2" ]; then if [ "${current_composer_version}" = "2" ]; then
printf >&2 "${GREEN_FG}✔ Composer${BLUE_FG} Version ${GREEN_FG}${current_composer_version}${BLUE_FG} is ${GREEN_FG}installed${BLUE_FG}.\n" printf >&2 "${GREEN_FG}✔ Composer${BLUE_FG} Version ${GREEN_FG}${current_composer_version}${BLUE_FG} is ${GREEN_FG}installed${BLUE_FG}.\n"
@ -19,8 +21,6 @@ check:
printf >&2 "${RED_FG}✘ Wrong Composer Version${YELLOW_FG} is installed!\n Version ${RED_FG}2${YELLOW_FG} is ${RED_FG}required${YELLOW_FG}.\n" printf >&2 "${RED_FG}✘ Wrong Composer Version${YELLOW_FG} is installed!\n Version ${RED_FG}2${YELLOW_FG} is ${RED_FG}required${YELLOW_FG}.\n"
error = 1 error = 1
fi fi
check_cmd "symfony" "Symfony cli"
required_php_version=$(cat .php-version) required_php_version=$(cat .php-version)
current_php_version=$(symfony php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;") current_php_version=$(symfony php -r "echo PHP_MAJOR_VERSION.'.'.PHP_MINOR_VERSION;")
if [ "${current_php_version}" = "${required_php_version}" ]; then if [ "${current_php_version}" = "${required_php_version}" ]; then
@ -34,7 +34,12 @@ check:
check "[ $(php -m | grep -c pdo_mysql) -eq 1 ]" "Php Mysql PDO" check "[ $(php -m | grep -c pdo_mysql) -eq 1 ]" "Php Mysql PDO"
check_cmd "docker" "Docker" check_cmd "docker" "Docker"
check "$(docker compose version >/dev/null 2>&1)" "Docker Compose" if [[ "$(docker compose version 2>&1)" == "Docker Compose version v"* ]]; then
printf >&2 "${GREEN_FG}✔ Docker Compose${BLUE_FG} is ${GREEN_FG}installed${BLUE_FG}.\n"
else
printf >&2 "${RED_FG}✘ Docker Compose${YELLOW_FG} is ${RED_FG}not installed${YELLOW_FG}! \n"
error=1
fi
if ((error > 0 )); then if ((error > 0 )); then
exit 1 exit 1

View file

@ -1,5 +1,3 @@
version: '3'
services: services:
mysql: mysql:
container_name: 'euph-website_mysql' container_name: 'euph-website_mysql'

View file

@ -30,7 +30,8 @@
"symfony/twig-bundle": "7.1.*", "symfony/twig-bundle": "7.1.*",
"symfony/uid": "7.1.*", "symfony/uid": "7.1.*",
"symfony/ux-icons": "^2.18", "symfony/ux-icons": "^2.18",
"symfony/ux-twig-component": "^2.18", "symfony/ux-swup": "^2.18",
"symfony/ux-twig-component": "*",
"symfony/validator": "7.1.*", "symfony/validator": "7.1.*",
"symfony/webpack-encore-bundle": "^2.1", "symfony/webpack-encore-bundle": "^2.1",
"symfony/yaml": "7.1.*", "symfony/yaml": "7.1.*",

69
app/composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "fde2d40a3f2774eaaf160d4814649934", "content-hash": "9af65731bd60f6cd005a51b1747d6d92",
"packages": [ "packages": [
{ {
"name": "dflydev/dot-access-data", "name": "dflydev/dot-access-data",
@ -6045,6 +6045,73 @@
], ],
"time": "2024-06-07T23:22:02+00:00" "time": "2024-06-07T23:22:02+00:00"
}, },
{
"name": "symfony/ux-swup",
"version": "v2.18.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/ux-swup.git",
"reference": "208f26399b594613a0eb18dcf6117f67a691a2c4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/ux-swup/zipball/208f26399b594613a0eb18dcf6117f67a691a2c4",
"reference": "208f26399b594613a0eb18dcf6117f67a691a2c4",
"shasum": ""
},
"conflict": {
"symfony/flex": "<1.13"
},
"type": "symfony-bundle",
"extra": {
"thanks": {
"name": "symfony/ux",
"url": "https://github.com/symfony/ux"
}
},
"autoload": {
"psr-4": {
"Symfony\\UX\\Swup\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Titouan Galopin",
"email": "galopintitouan@gmail.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Swup integration for Symfony",
"homepage": "https://symfony.com",
"keywords": [
"symfony-ux"
],
"support": {
"source": "https://github.com/symfony/ux-swup/tree/v2.18.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-06-01T17:50:16+00:00"
},
{ {
"name": "symfony/ux-twig-component", "name": "symfony/ux-twig-component",
"version": "v2.18.1", "version": "v2.18.1",

View file

@ -16,6 +16,7 @@ return [
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Presta\SitemapBundle\PrestaSitemapBundle::class => ['all' => true], Presta\SitemapBundle\PrestaSitemapBundle::class => ['all' => true],
Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true], Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
Symfony\UX\Icons\UXIconsBundle::class => ['all' => true],
Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true], Symfony\UX\TwigComponent\TwigComponentBundle::class => ['all' => true],
Symfony\UX\Icons\UXIconsBundle::class => ['all' => true],
Symfony\UX\Swup\SwupBundle::class => ['all' => true],
]; ];

View file

@ -1,5 +1,5 @@
twig: twig:
default_path: '%kernel.project_dir%/frontend/templates/' default_path: '%kernel.project_dir%/frontend/templates'
when@test: when@test:
twig: twig:

View file

@ -2,4 +2,4 @@ twig_component:
anonymous_template_directory: 'components/' anonymous_template_directory: 'components/'
defaults: defaults:
# Namespace & directory for components # Namespace & directory for components
App\Twig\Components\: 'components/' App\Components\: 'components/'

View file

@ -5,13 +5,19 @@
}, },
"extends": [ "extends": [
"eslint:recommended", "eslint:recommended",
"plugin:@typescript-eslint/strict", "plugin:@typescript-eslint/strict"
], ],
"parser": "@typescript-eslint/parser", "parser": "@typescript-eslint/parser",
"parserOptions": { "parserOptions": {
"ecmaVersion": "latest", "ecmaVersion": "latest",
"sourceType": "module" "sourceType": "module"
}, },
"overrides": [
{
"files": ["*.svelte"],
"parser": "svelte-eslint-parser"
}
],
"plugins": [ "plugins": [
"@typescript-eslint" "@typescript-eslint"
], ],

View file

@ -0,0 +1,4 @@
*.ts
*.twig
*.json
mod.just

View file

@ -1,6 +1,7 @@
{ {
"extends": [ "extends": [
"stylelint-config-standard-scss" "stylelint-config-standard-scss",
"stylelint-config-tailwindcss/scss"
], ],
"plugins": [ "plugins": [
"stylelint-scss" "stylelint-scss"

View file

@ -1,2 +1,46 @@
import '#styles/app.scss'; import '@styles/app.scss';
import '#pkg/stimulus'; import '@pkg/stimulus';
import '@pkg/swup';
import {Theme, THEME_LOCAL_STORAGE_ID} from '#const/theme';
const DARK_MODE_QUERY: MediaQueryList = window.matchMedia('(prefers-color-scheme: dark)');
function initTheme(): void {
handleTheme(DARK_MODE_QUERY.matches);
DARK_MODE_QUERY.addEventListener('change', handleThemeChange);
}
function handleThemeChange(e: MediaQueryListEvent): void {
handleTheme(e.matches);
}
function handleTheme(prefersDark: boolean): void {
const theme = localStorage[THEME_LOCAL_STORAGE_ID];
if (theme === Theme.DARK) {
document.documentElement.classList.add(Theme.DARK);
console.log('explicit dark');
} else if (!(THEME_LOCAL_STORAGE_ID in localStorage) && prefersDark) {
document.documentElement.classList.add(Theme.DARK);
console.log('implicit dark');
} else {
document.documentElement.classList.remove(Theme.DARK);
console.log('light');
}
}
export {initTheme};
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
// Whenever the user explicitly chooses light mode
//localStorage.theme = 'light';
// Whenever the user explicitly chooses dark mode
//localStorage.theme = 'dark';
// Whenever the user explicitly chooses to respect the OS preference
//localStorage.removeItem('theme');
initTheme();

View file

@ -0,0 +1,20 @@
import {Controller} from '@hotwired/stimulus';
export default class extends Controller {
static targets: Array<string> = ['container'];
declare readonly containerTarget: HTMLElement;
connect(): void {
console.log('Init Burgers');
this.containerTarget.style.left = '';
this.containerTarget.style.right = `-${this.containerTarget.offsetWidth}px`;
}
open(): void {
this.containerTarget.style.right = '0';
}
close(): void {
this.containerTarget.style.right = `-${this.containerTarget.offsetWidth}px`;
}
}

View file

@ -1,4 +1,11 @@
{ {
"controllers": [], "controllers": {
"@symfony/ux-swup": {
"swup": {
"enabled": true,
"fetch": "eager"
}
}
},
"entrypoints": [] "entrypoints": []
} }

View file

@ -1,14 +1,15 @@
__default: __default:
@../bin/just/choose.sh {{ source_file() }} choose @../../bin/just/choose.sh {{ source_file() }} choose
# Checks whether the requriements are met # Checks whether the requriements are met
[group('main')] [group('main')]
check: check:
#!/bin/bash #!/bin/bash
source ../bin/just/colors.sh source ../../bin/just/colors.sh
source ../bin/just/check.sh source ../../bin/just/check.sh
printf "${BLUE_BG}${BLACK_FG} Checking Frontend Requirements ${CLEAR}\n" printf "${BLUE_BG}${BLACK_FG} Checking Frontend Requirements ${CLEAR}\n"
check_cmd "screen" "screen"
check_cmd "volta" "Volta" check_cmd "volta" "Volta"
check_cmd "node" "Node" check_cmd "node" "Node"
check_cmd "npm" "NPM" check_cmd "npm" "NPM"
@ -39,7 +40,7 @@ session_name := "euph-website_frontend"
[group('main')] [group('main')]
up: halt up: halt
#!/bin/bash #!/bin/bash
source ../bin/just/colors.sh source ../../bin/just/colors.sh
cd .. && screen -dmS {{ session_name }} npm run watch >> /dev/null cd .. && screen -dmS {{ session_name }} npm run watch >> /dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "${GREEN_FG}Frontend was started${CLEAR}\n" printf "${GREEN_FG}Frontend was started${CLEAR}\n"
@ -51,7 +52,7 @@ up: halt
[group('main')] [group('main')]
halt: halt:
#!/bin/bash #!/bin/bash
source ../bin/just/colors.sh source ../../bin/just/colors.sh
screen -XS {{ session_name }} quit >> /dev/null screen -XS {{ session_name }} quit >> /dev/null
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
printf "${GREEN_FG}Frontend was stopped${CLEAR}\n" printf "${GREEN_FG}Frontend was stopped${CLEAR}\n"
@ -60,7 +61,7 @@ halt:
[group('main')] [group('main')]
attach: attach:
#!/bin/bash #!/bin/bash
source ../bin/just/colors.sh source ../../bin/just/colors.sh
if screen -ls | grep -q {{ session_name }}; then if screen -ls | grep -q {{ session_name }}; then
screen -r {{ session_name }} screen -r {{ session_name }}
else else

View file

@ -0,0 +1,2 @@
//import Swup from 'swup';
//new Swup();

View file

@ -1,9 +1,24 @@
@import "sizes"; @import "components/Header";
@import "components/BurgerMenu/Index";
@tailwind base;
@tailwind components;
@tailwind utilities;
@import "components/Header/_"; hr {
@import "components/BurgerMenu/_"; @apply h-px my-2 border-0;
@apply bg-gray-300 dark:bg-gray-500;
:root, body { }
margin: 0;
min-height: 100%; .app {
&__text {
@apply text-gray-900 dark:text-gray-100
}
&__text-bold {
@apply app__text font-bold
}
&__text-light {
@apply text-gray-500 dark:text-gray-300 font-light
}
} }

View file

@ -0,0 +1,33 @@
@import "Nav";
@import "Login";
@import "User";
.burger-menu {
@apply ml-auto h-full aspect-square;
&__container {
@apply fixed top-0 right-0 h-screen overflow-y-auto z-40;
@apply flex flex-col p-2 gap-2 w-64;
@apply bg-gray-200 dark:bg-gray-600;
transition: ease-in-out 200ms;
}
&__button-open {
@apply h-full aspect-square;
}
&__button-close {
@apply h-8 w-8 absolute right-2 aspect-square;
}
&__icon {
@apply text-gray-900 dark:text-gray-100;
@apply h-6 w-6;
}
&__icon-full {
@apply text-gray-900 dark:text-gray-100;
@apply h-full w-full;
}
}

View file

@ -0,0 +1,8 @@
.burger-menu-login {
@apply flex p-2 gap-2 items-center justify-center;
@apply rounded-lg bg-blue-500 app__text;
&__icon {
@apply burger-menu__icon;
}
}

View file

@ -0,0 +1,20 @@
.burger-menu-nav {
@apply text-lg app__text;
&__list {
@apply flex flex-col gap-2;
}
&__item {
@apply h-8;
}
&__link {
@apply flex p-1 gap-2 items-center;
@apply rounded-md hover:bg-gray-200 dark:hover:bg-gray-600;
}
&__icon {
@apply burger-menu__icon;
}
}

View file

@ -0,0 +1,47 @@
.burger-menu-user {
@apply flex flex-col items-center;
@apply text-gray-900 dark:text-gray-100;
&__picture-wrapper {
@apply w-1/3 aspect-square mx-auto;
}
&__name {
@apply app__text-bold text-xl;
@apply h-6;
}
&__icon-full {
@apply burger-menu__icon-full;
}
&__email {
@apply app__text-light text-base;
@apply h-6;
}
&__info {
@apply app__text-light text-base;
@apply h-6;
}
&__actions {
@apply inline-flex mt-2;
button {
@apply inline-flex p-1;
@apply bg-transparent;
@apply app__text text-sm;
@apply border border-r-0 border-gray-900 dark:border-gray-100;
&:first-of-type {
@apply rounded-s-lg;
}
&:last-of-type {
@apply rounded-e-lg border-r;
}
}
}
}

View file

@ -1,5 +0,0 @@
#burger-menu {
&__container {
display: none;
}
}

View file

@ -0,0 +1,17 @@
.header {
@apply flex h-12 p-2 gap-2 items-center;
@apply bg-gray-300 dark:bg-gray-700;
&__logo {
@apply h-full dark:hidden;
}
&__logo-dark {
@apply h-full hidden dark:block;
}
&__logo-text {
@apply text-lg text-center text-black dark:text-white;
}
}

View file

@ -1,7 +0,0 @@
#header {
display: flex;
height: $size-xxl;
padding: $size-xs;
gap: $size-xs;
justify-items: center;
}

View file

@ -1,7 +0,0 @@
$size-xxs: 0.25rem; // 4px
$size-xs: 0.5rem; // 8px
$size-s: 0.75rem; // 12px
$size-m: 1rem; // 16px
$size-l: 1.5rem; // 24px
$size-xl: 2rem; // 32px
$size-xxl: 3rem; // 48px

View file

@ -1,4 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
{% set logged_in = true %}
<html lang="de"> <html lang="de">
<head> <head>
<meta charset="UTF-8"/> <meta charset="UTF-8"/>
@ -19,9 +21,8 @@
<title>{% block title %}Euph{% endblock %}</title> <title>{% block title %}Euph{% endblock %}</title>
</head> </head>
<body> <body>
<twig:Header:_/> <twig:Header/>
{% block body %}{% endblock %} {% block body %}{% endblock %}
</body> </body>
</html> </html>

View file

@ -0,0 +1,24 @@
{% set logged_in = true %}
<div
class="burger-menu"
{{ stimulus_controller('Components/BurgerMenu') }}
>
<button class="burger-menu__button-open" {{ stimulus_action('Components/BurgerMenu', 'open') }}>
<twig:ux:icon name="ph:list" class="burger-menu__icon-full"/>
</button>
<div
class="burger-menu__container"
tabindex="-1"
{{ stimulus_target('Components/BurgerMenu', 'container') }}
style="left: 100%"
>
<button class="burger-menu__button-close" {{ stimulus_action('Components/BurgerMenu', 'close') }}>
<twig:ux:icon name="ph:x" class="burger-menu__icon-full"/>
</button>
<twig:BurgerMenu:User logged_in="{{ logged_in }}"/>
<twig:BurgerMenu:Login logged_in="{{ logged_in }}"/>
<hr/>
<twig:BurgerMenu:Nav/>
</div>
</div>

View file

@ -1,6 +1,9 @@
{% set logged_in = false %} {% props logged_in = false %}
{% if not logged_in %} {% if not logged_in %}
<a> <hr/>
<a class="burger-menu-login">
<twig:ux:icon name="branding:euphcloud" class="burger-menu-login__icon"/>
<span>Login with Euphcloud</span> <span>Login with Euphcloud</span>
</a> </a>
{% endif %} {% endif %}

View file

@ -0,0 +1,16 @@
<nav class="burger-menu-nav">
<ul class="burger-menu-nav__list">
{{ _self.nav_item('Test1', '#test1', 'list') }}
{{ _self.nav_item('Test2', '#test2', 'list') }}
{{ _self.nav_item('Test3', '#test3', 'list') }}
</ul>
</nav>
{% macro nav_item(name, href, icon) %}
<li class="burger-menu-nav__item">
<a class="burger-menu-nav__link" href="{{ href }}">
<twig:ux:icon name="ph:{{ icon }}" class="burger-menu-nav__icon"/>
<span class="flex-1">{{ name }}</span>
</a>
</li>
{% endmacro %}

View file

@ -1,16 +0,0 @@
<nav id="burger-menu-navigation">
<ul>
{{ _self.nav_item('Test1', '#test1', 'bars') }}
{{ _self.nav_item('Test2', '#test2', 'bars') }}
{{ _self.nav_item('Test3', '#test3', 'bars') }}
</ul>
</nav>
{% macro nav_item(name, href, icon) %}
<li>
<a href="{{ href }}">
<twig:ux:icon name="fa6-solid:{{ icon }}" />
<span>{{ name }}</span>
</a>
</li>
{% endmacro %}

View file

@ -1,26 +1,25 @@
{% set logged_in = false %} {% props logged_in = false %}
<div id="burger-menu-user">
<div > <div class="burger-menu-user">
<twig:ux:icon name="fa6-solid:circle-user" /> <div class="burger-menu-user__picture-wrapper">
<twig:ux:icon name="ph:user-circle-fill" class="burger-menu-user__icon-full"/>
</div> </div>
{% if logged_in %} {% if logged_in %}
<span>Username</span> <span class="burger-menu-user__name">Username</span>
<span>username@email.com</span> <span class="burger-menu-user__email">username@email.com</span>
<div> <div class="burger-menu-user__actions">
{{ _self.user_action('Profile', 'user') }} {{ _self.user_action('Profile', 'user') }}
{{ _self.user_action('Settings', 'gear') }} {{ _self.user_action('Settings', 'gear') }}
{{ _self.user_action('Logout', 'right-from-bracket') }} {{ _self.user_action('Logout', 'sign-out') }}
</div> </div>
{% else %} {% else %}
<span>not logged in</span> <span class="burger-menu-user__info">not logged in</span>
{% endif %} {% endif %}
</div> </div>
{% macro user_action(name, icon) %} {% macro user_action(name, icon) %}
<button> <button>
<twig:ux:icon name="fa6-solid:{{ icon }}" /> <twig:ux:icon name="ph:{{ icon }}" class="burger-menu__icon"/>
<span>{{ name }}</span> <span>{{ name }}</span>
</button> </button>
{% endmacro %} {% endmacro %}

View file

@ -1,14 +0,0 @@
<button id="burger-menu">
<twig:ux:icon name="fa6-solid:bars" />
</button>
<div id="burger-menu__container" tabindex="-1">
<button>
<twig:ux:icon name="fa6-solid:x" />
</button>
<twig:BurgerMenu:User/>
<hr/>
<twig:BurgerMenu:Login/>
<hr/>
<twig:BurgerMenu:Navigation/>
</div>

View file

@ -1,12 +1,14 @@
<header id="header"> <header class="header">
<img <img
class="header__logo"
src="{{ asset("icons/logo/logo.svg") }}" src="{{ asset("icons/logo/logo.svg") }}"
alt="Euph Logo" alt="Euph Logo"
> >
<img <img
class="header__logo-dark"
src="{{ asset("icons/logo/dark-logo.svg") }}" src="{{ asset("icons/logo/dark-logo.svg") }}"
alt="Euph Logo" alt="Euph Logo"
> >
<h1>Euph</h1> <span class="header__logo-text">Euph</span>
<twig:BurgerMenu:_/> <twig:BurgerMenu:Index/>
</header> </header>

View file

@ -1,3 +1,4 @@
{% extends 'base.html.twig' %} {% extends 'base.html.twig' %}
{% block body %} {% block body %}
<p>A Phrase</p>
{% endblock %} {% endblock %}

View file

@ -13,25 +13,27 @@
"~*": [ "~*": [
".*" ".*"
], ],
"#components/*": [ "@components/*": [
"./templates/components/*"
],
"@controllers/*": [
"./controllers/*" "./controllers/*"
], ],
"#controllers/*": [ "@styles/*": [
"./controllers/*"
],
"#pkg/*": [
"./packages/*"
],
"#styles/*": [
"./styles/*" "./styles/*"
], ],
"@pkg/*": [
"./packages/*"
],
"#types/*": [ "#types/*": [
"./types/*" "./types/*"
],
"#const/*": [
"./types/constants/*"
] ]
} }
}, },
"include": [ "include": [
"./**/*.ts", "./**/*.ts"
"./**/*.svelte"
] ]
} }

View file

@ -0,0 +1,8 @@
const THEME_LOCAL_STORAGE_ID = 'theme';
enum Theme {
LIGHT = 'light',
DARK = 'dark'
}
export {THEME_LOCAL_STORAGE_ID, Theme};

8129
app/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,12 @@
"@babel/preset-env": "^7.16.0", "@babel/preset-env": "^7.16.0",
"@hotwired/stimulus": "^3.0.0", "@hotwired/stimulus": "^3.0.0",
"@popperjs/core": "^2.11.8", "@popperjs/core": "^2.11.8",
"@swup/debug-plugin": "^3.0",
"@swup/fade-theme": "^1.0",
"@swup/forms-plugin": "^2.0",
"@swup/slide-theme": "^1.0",
"@symfony/stimulus-bridge": "^3.2.0", "@symfony/stimulus-bridge": "^3.2.0",
"@symfony/ux-swup": "file:vendor/symfony/ux-swup/assets",
"@symfony/webpack-encore": "^4.0.0", "@symfony/webpack-encore": "^4.0.0",
"@typescript-eslint/eslint-plugin": "^6.10.0", "@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0", "@typescript-eslint/parser": "^6.10.0",
@ -29,13 +34,18 @@
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.0", "fork-ts-checker-webpack-plugin": "^9.0.0",
"ignore-loader": "^0.1.2", "ignore-loader": "^0.1.2",
"postcss": "^8.4.39",
"postcss-loader": "^7.3.4",
"prettier": "^2.8.8", "prettier": "^2.8.8",
"regenerator-runtime": "^0.13.9", "regenerator-runtime": "^0.13.9",
"sass": "^1.69.4", "sass": "^1.69.4",
"sass-loader": "^13.3.2", "sass-loader": "^13.3.2",
"stylelint": "^16.2.1", "stylelint": "^16.2.1",
"stylelint-config-standard-scss": "^13.0.0", "stylelint-config-standard-scss": "^13.0.0",
"stylelint-config-tailwindcss": "^0.0.7",
"stylelint-scss": "^6.3.1", "stylelint-scss": "^6.3.1",
"swup": "^3.0",
"tailwindcss": "^3.4.4",
"ts-loader": "^9.5.0", "ts-loader": "^9.5.0",
"tsconfig-paths-webpack-plugin": "^4.1.0", "tsconfig-paths-webpack-plugin": "^4.1.0",
"typescript": "^5.2.2", "typescript": "^5.2.2",

6
app/postcss.config.js Normal file
View file

@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View file

@ -261,6 +261,21 @@
"assets/icons/symfony.svg" "assets/icons/symfony.svg"
] ]
}, },
"symfony/ux-svelte": {
"version": "2.18",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.9",
"ref": "4a6ee82d817d4e9be8d4a861476a112011d701e1"
},
"files": [
"assets/svelte/controllers/Hello.svelte"
]
},
"symfony/ux-swup": {
"version": "v2.18.0"
},
"symfony/ux-twig-component": { "symfony/ux-twig-component": {
"version": "2.18", "version": "2.18",
"recipe": { "recipe": {

View file

@ -1,18 +1,13 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: [ content: [
"./frontend/**/*.ts", "./frontend/**/*.ts",
"./frontend/templates/**/*.html.twig", "./frontend/templates/**/*.html.twig",
"./node_modules/flowbite/**/*.js" ],
], theme: {
theme: { extend: {
extend: {
},
}, },
}, darkMode: 'selector'
plugins: [
require('flowbite/plugin')
],
darkMode: 'selector'
} }

View file

@ -33,6 +33,7 @@ Encore
}) })
.enableStimulusBridge('./frontend/controllers/controllers.json') .enableStimulusBridge('./frontend/controllers/controllers.json')
.enableSassLoader() .enableSassLoader()
.enablePostCssLoader()
.enableTypeScriptLoader(function tsconfigCallback(tsConfig) { .enableTypeScriptLoader(function tsconfigCallback(tsConfig) {
tsConfig.configFile = TS_CONFIG_PATH; tsConfig.configFile = TS_CONFIG_PATH;
}) })
@ -45,7 +46,7 @@ Encore
proxy: 'http://localhost:8000', proxy: 'http://localhost:8000',
files: [ files: [
'frontend/**/*.twig', 'frontend/**/*.twig',
'frontend/**/*.svelte', 'frontend/**/*.scss',
'frontend/**/*.ts', 'frontend/**/*.ts',
], ],
reload: true, reload: true,

1
bin/just/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.cache/

View file

@ -9,5 +9,5 @@ check() {
} }
check_cmd() { check_cmd() {
check "$(command -v $1 >/dev/null 2>&1)" $2 check "$(command -v $1 >/dev/null 2>&1)" "$2"
} }

View file

@ -9,9 +9,9 @@ function preview() {
if [[ -z "$recipe" ]] || echo $recipe | grep -q "^\["; then if [[ -z "$recipe" ]] || echo $recipe | grep -q "^\["; then
printf "${RED_FG}Select this to Exit${CLEAR}" printf "${RED_FG}Select this to Exit${CLEAR}"
elif [[ "$content" == *" ..." ]]; then elif [[ "$content" == *" ..." ]]; then
just_wrapper --list $recipe | highlight --out-format xterm256 --syntax conf hash_highlight "$(just_wrapper --list $recipe)" "conf"
else else
just_wrapper --show $recipe | highlight --out-format xterm256 --syntax sh hash_highlight "$(just_wrapper --show $recipe)" "sh"
fi fi
} }
@ -33,7 +33,19 @@ function choose_truncate() {
function choose_list() { function choose_list() {
just_wrapper -l --no-aliases --list-heading="" | awk '{$1=$1};1' just_wrapper -l --no-aliases --list-heading="" | awk '{$1=$1};1'
} }
function hash_highlight() {
cache_dir="$(dirname ${BASH_SOURCE[0]})/.cache"
hash=$(echo $1 | md5sum | cut -d ' ' -f1)
file="$cache_dir/$hash"
if [[ -e $file ]]; then
cat $file
else
mkdir -p $cache_dir
data=$(printf "$1" | highlight --out-format xterm256 --syntax "$2")
printf "$data"
printf "$data" > $file
fi
}
case "$action" in case "$action" in
*choose) choose;; *choose) choose;;
*preview) preview;; *preview) preview;;