Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
65 changes: 18 additions & 47 deletions ux.symfony.com/assets/styles/components/_Cookbook.scss
Original file line number Diff line number Diff line change
@@ -1,51 +1,15 @@
.Cookbook {
h1 {
margin-top: 3rem;
margin-bottom: 1rem;
text-align: center;
font-size: 52px;
font-weight: 700;
line-height: 60px;
}

.description {
text-align: center;
font-size: 24px;
font-weight: 600;
margin-top: 1.5rem;
}

.tags {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
gap: 1rem;
text-decoration: none;
list-style: none;
margin-bottom: 3rem;

li {
background-color: rgb(74 29 150);
color: rgb(202 191 253);
font-weight: 500;
font-size: 0.75rem;
line-height: 1rem;
padding: .125rem .625rem;
border-radius: 0.25rem;
}
}

.image-title {
width: 100%;
max-height: 40vh;
overflow: hidden;
border-radius: 4px;
margin-bottom: 3rem;
width: auto;
border-radius: .75rem;
aspect-ratio: 16 / 9;
max-width: 1280px;

img {
display: block;
object-fit: contain;
object-fit: cover;
width: 100%;
}
}
Expand All @@ -65,15 +29,22 @@
font-size: 24px;
font-weight: 700;
line-height: 32px;
color: #FFFFFF;
color: var(--color-text);
}

h4 {
margin-top: 3rem;
margin-bottom: 1rem;
}
}

pre {
margin-top: 4rem;
margin-bottom: 2rem;
border-radius: 4px;
margin-block: 2rem;
border-radius: .75rem;
background-color: #0A0A0A;
padding: 2rem;
padding: 1rem 1.5rem;
color: #d7e2e3;
font-size: 1rem;
line-height: 1.5;
}
}
}
9 changes: 6 additions & 3 deletions ux.symfony.com/assets/styles/components/_DemoCard.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
box-shadow: 0 0 0 transparent;
background: var(--bs-body-bg);
}

.DemoCard:hover {
transition: color 250ms ease-in-out, transform 250ms ease-in-out, box-shadow 250ms ease-in-out;
transform: translateY(-.25rem);
Expand All @@ -36,11 +37,12 @@
}

.DemoCard__image {
max-height: 100%;
width: 100%;
max-width: 100%;
display: block;
object-fit: cover;
opacity: .90;
}

.DemoCard:hover .DemoCard__image {
opacity: .93;
}
Expand Down Expand Up @@ -71,6 +73,7 @@
line-height: 1.4;
margin: 0;
}

.DemoCard:hover .DemoCard__description {
opacity: .85;
}
Expand All @@ -80,5 +83,5 @@
margin-bottom: 0;
display: flex;
flex-wrap: wrap;
gap: .5rem;
gap: .5rem;
}
1 change: 1 addition & 0 deletions ux.symfony.com/config/packages/twig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ twig:

paths:
'%kernel.project_dir%/templates/demos/live_memory': ~
'%kernel.project_dir%/cookbook/': 'Cookbook'

when@test:
twig:
Expand Down
2 changes: 0 additions & 2 deletions ux.symfony.com/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ services:
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
bind:
string $cookbookPath: '%kernel.project_dir%/cookbook'

# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Architecture component
title: Component architecture
description: Rules and pattern to work with components
image: images/cookbook/component_architecture.png
image: images/cookbook/component-architecture.png
tags:
- javascript
- symfony
Expand Down Expand Up @@ -174,5 +174,5 @@ class Button
## Conclusion

Even in Symfony, you can use the component architecture.
Follow those rules help your front developpers working on codebase
their are familiar with since those rules are already used in the js world.
Follow those rules help your front developers working on codebase
they are familiar with since those rules are already used in the JS world.
15 changes: 8 additions & 7 deletions ux.symfony.com/src/Controller/CookbookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,20 @@

namespace App\Controller;

use App\Service\CookbookFactory;
use App\Service\CookbookRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Requirement\Requirement;

class CookbookController extends AbstractController
{
public function __construct(
private CookbookRepository $cookbookRepository,
private CookbookFactory $cookbookFactory,
private readonly CookbookRepository $cookbookRepository,
) {
}

#[Route('/cookbook', name: 'app_cookbook_index')]
#[Route('/cookbook', name: 'app_cookbook')]
public function index(): Response
{
$cookbooks = $this->cookbookRepository->findAll();
Expand All @@ -35,13 +34,15 @@ public function index(): Response
]);
}

#[Route('/cookbook/{slug}', name: 'app_cookbook_show')]
#[Route('/cookbook/{slug}', name: 'app_cookbook_show', requirements: ['slug' => Requirement::ASCII_SLUG])]
public function show(string $slug): Response
{
$cookbook = $this->cookbookRepository->findOneByName($slug);
$cookbook = $this->cookbookRepository->findOneBySlug($slug);
if (!$cookbook) {
throw $this->createNotFoundException(\sprintf('Cookbook "%s" not found', $slug));
}

return $this->render('cookbook/show.html.twig', [
'slug' => $slug,
'cookbook' => $cookbook,
]);
}
Expand Down
14 changes: 7 additions & 7 deletions ux.symfony.com/src/Model/Cookbook.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@

namespace App\Model;

class Cookbook
final readonly class Cookbook
{
/**
* @param list<string> $tags
*/
public function __construct(
public string $title,
public string $description,
public string $route,
public string $slug,
public string $image,
public string $description,
public string $content,
/**
* @var string[]
*/
public array $tags = [],
public array $tags,
) {
}
}
50 changes: 37 additions & 13 deletions ux.symfony.com/src/Service/CookbookFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,51 @@
namespace App\Service;

use App\Model\Cookbook;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use League\CommonMark\Extension\FrontMatter\Data\SymfonyYamlFrontMatterParser;
use League\CommonMark\Extension\FrontMatter\FrontMatterParser;
use League\CommonMark\Extension\FrontMatter\FrontMatterParserInterface;

class CookbookFactory
final class CookbookFactory
{
public function __construct(
private readonly CookbookParser $cookbookParser,
private readonly UrlGeneratorInterface $urlGenerator,
) {
private FrontMatterParserInterface $frontMatterParser;

public function __construct()
{
$this->frontMatterParser = new FrontMatterParser(new SymfonyYamlFrontMatterParser());
}

public function buildFromFile(\SplFileInfo $file): Cookbook
public function createFromFile(string $file): Cookbook
{
$content = $file->getContents();
if (!file_exists($file)) {
throw new \InvalidArgumentException(\sprintf('File "%s" not found.', $file));
}

$content = file_get_contents($file);

if (!\is_array($frontMatter = $this->frontMatterParser->parse($content)->getFrontMatter())) {
throw new \RuntimeException(\sprintf('Cookbook file "%s" does not contains Front Matter data.', $file));
}

if (!isset($frontMatter['title']) || !\is_string($frontMatter['title'])) {
throw new \RuntimeException('Missing title in Front Matter.');
}
if (!isset($frontMatter['description']) || !\is_string($frontMatter['description'])) {
throw new \RuntimeException('Missing description in Front Matter.');
}
if (!isset($frontMatter['image']) || !\is_string($frontMatter['image'])) {
throw new \RuntimeException('Missing image in Front Matter.');
}
if (!isset($frontMatter['tags']) || !\is_array($frontMatter['tags'])) {
throw new \RuntimeException('Missing tags in Front Matter.');
}

return new Cookbook(
title: $this->cookbookParser->getTitle($content),
description: $this->cookbookParser->getDescriptions($content),
route: $this->urlGenerator->generate('app_cookbook_show', ['slug' => $file->getBasename('.md')]),
image: $this->cookbookParser->getImage($content),
title: $frontMatter['title'],
slug: str_replace('_', '-', basename($file, '.md')),
image: $frontMatter['image'],
description: $frontMatter['description'],
content: $content,
tags: $this->cookbookParser->getTags($content),
tags: $frontMatter['tags'],
);
}
}
75 changes: 0 additions & 75 deletions ux.symfony.com/src/Service/CookbookParser.php

This file was deleted.

Loading