Skip to content

Add Symfony UX Image component (Slim v1)#3549

Open
KindImagination wants to merge 1 commit into
symfony:3.xfrom
KindImagination:ux-image
Open

Add Symfony UX Image component (Slim v1)#3549
KindImagination wants to merge 1 commit into
symfony:3.xfrom
KindImagination:ux-image

Conversation

@KindImagination

Copy link
Copy Markdown
Q A
Bug fix? no
New feature? yes
Deprecations? no
Issues
License MIT

Summary

Slim v1 of symfony/ux-image — responsive image components addressing all feedback from the original PR #3188.

What's Included

<twig:ux:img> — Simple responsive images

  • Viewport-based width syntax (100vw md:80vw)
  • Automatic srcset/sizes generation
  • Density support (densities="x1 x2")
  • Fallback format for older browsers

<twig:ux:picture> — Art direction

  • Breakpoint-specific aspect ratios (sm:1:1 md:16:9)
  • Ratio cascading (CSS-like inheritance)
  • Exclusive media queries for correct aspect ratio

Key Changes from Original PR

Original Issue Resolution
liip/imagine-bundle in require Removed — no hard dependencies
No local file support PassThroughProvider works out of the box
PreloadManager controversy Removed entirely
Arrays instead of objects ImageConfig value object
Component name conflicts ux:img / ux:picture
Only TwigComponent syntax Also supports {{ ux_image() }}
Too many features Slim scope — iterate on v1

Provider Architecture

  • PassThroughProvider (default) — works with local files, no CDN required
  • UrlPatternProvider — generic CDN via URL template (Cloudflare, imgix, etc.)
  • Custom providers — implement ProviderInterface and tag with ux_image.provider

Usage

{# Simple responsive image #}
<twig:ux:img src="/images/hero.jpg" alt="Hero" width="100vw md:80vw" />

{# Art direction #}
<twig:ux:picture src="/images/banner.jpg" alt="Banner" width="100vw md:80vw" ratio="sm:1:1 md:16:9" />

{# Without Twig components #}
{{ ux_image('/images/hero.jpg', 'Hero', { width: '100vw md:80vw' }) }}

Configuration

# config/packages/ux_image.yaml
ux_image:
    default_provider: passthrough
    providers:
        cloudflare:
            pattern: '/cdn-cgi/image/w={width},f={format},q={quality}/{src}'

This addresses feedback from @WebMamba, @smnandre, and @Kocal on the original PR. Happy to iterate further!

Addresses maintainer feedback from PR symfony#3188:
- No hard dependencies (liip/imagine-bundle removed from require)
- PassThroughProvider as default — works with local files out of the box
- UrlPatternProvider for generic CDN integration via URL templates
- Objects (ImageConfig) instead of arrays for internal data
- No PreloadManager (Google advises against preload for SSR)
- Component names: ux:img and ux:picture (avoid conflicts)
- Three usage modes: TwigComponent, {{ component() }}, {{ ux_image() }}
- Target Symfony UX 3.x (PHP 8.4+, Symfony 7.4|8.0)
@carsonbot carsonbot added Feature New Feature Status: Needs Review Needs to be reviewed labels May 18, 2026
@carsonbot carsonbot changed the title Add Symfony UX Image component (Slim v1) Add Symfony UX Image component (Slim v1) May 18, 2026
Comment thread src/Image/LICENSE

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file is empty; you need the associated content.

You can find it on other components.

Comment thread src/Image/CHANGELOG.md
@@ -0,0 +1,5 @@
# CHANGELOG

## 2.32.0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## 2.32.0
## 3.1


foreach ($taggedServices as $id => $tags) {
foreach ($tags as $attributes) {
$name = $attributes['name'] ?? $id;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$name is unused.

Comment thread src/Image/composer.json
"twig/twig": "^3.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.65",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be deleted here.

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review the file to make it look something like this: https://github.com/symfony/ux/blob/3.x/src/Native/phpunit.xml.dist.

@seb-jean

Copy link
Copy Markdown
Contributor

The documentation should be added.

return [];
}

$breakpointOrder = ['sm', 'md', 'lg', 'xl', '2xl'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A user who configures ux_image.breakpoints with different names (e.g. mobile, tablet) will get empty cascades. Same issue for Transformer::BREAKPOINT_ORDER.

*/
class Transformer
{
private const BREAKPOINT_ORDER = ['default', 'sm', 'md', 'lg', 'xl', '2xl'];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A user who configures ux_image.breakpoints with different names (e.g. mobile, tablet) will get empty cascades.

@@ -0,0 +1,89 @@
<?php

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class is never used.

public function getFunctions(): array
{
return [
new TwigFunction('ux_image', [$this, 'renderImage']),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
new TwigFunction('ux_image', [$this, 'renderImage']),
new TwigFunction('ux_image', [$this, 'renderImage'], ['is_safe' => ['html']]),

@@ -0,0 +1,111 @@
<?php

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You would need to have Lazy-Loaded Twig Extensions and therefore have the ImageExtension and ImageRuntime classes

Comment thread src/Image/.gitattributes
Comment on lines +1 to +6
* export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.php-cs-fixer.dist.php export-ignore
phpunit.dist.xml export-ignore
tests/ export-ignore

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* export-ignore
.gitattributes export-ignore
.gitignore export-ignore
.php-cs-fixer.dist.php export-ignore
phpunit.dist.xml export-ignore
tests/ export-ignore
/.git* export-ignore
/.symfony.bundle.yaml export-ignore
/doc export-ignore
/phpunit.xml.dist export-ignore
/tests export-ignore

@seb-jean

Copy link
Copy Markdown
Contributor

@KindImagination, I’ve given you some initial feedback that you can already start correcting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature New Feature Status: Needs Review Needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants