- content_type === 'application/pdf'): ?>
-
+ makeFileIcon($singleFile)): ?>
+ = $fileIcon ?>

diff --git a/modules/backend/partials/_file_icon.php b/modules/backend/partials/_file_icon.php
new file mode 100644
index 0000000000..7fe53e61dd
--- /dev/null
+++ b/modules/backend/partials/_file_icon.php
@@ -0,0 +1,13 @@
+
+
diff --git a/modules/backend/widgets/mediamanager/assets/css/mediamanager.css b/modules/backend/widgets/mediamanager/assets/css/mediamanager.css
index 9d943e4beb..ae63b8c1cc 100644
--- a/modules/backend/widgets/mediamanager/assets/css/mediamanager.css
+++ b/modules/backend/widgets/mediamanager/assets/css/mediamanager.css
@@ -1,40 +1,40 @@
+.file-icon{fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;display:inline-block}
+.file-icon-extension{font-family:'ArialMT','Arial',sans-serif;font-size:4em;font-weight:900;fill:#fff}
+.file-icon-label{fill:#576D7E;fill-rule:nonzero}
+.file-icon-css,
+.file-icon-less,
+.file-icon-scss{fill:#B73FD9}
+.file-icon-html,
+.file-icon-xml{fill:#EA9B47}
+.file-icon-js,
+.file-icon-json{fill:#A9A9A9}
+.file-icon-pdf{fill:#E30713}
+.file-icon-txt{fill:#248BD0}
+.file-icon-ai{fill:#F29200}
+.file-icon-eps{fill:#F9B234}
+.file-icon-psd{fill:#2DAAE2}
+.file-icon-ttf,
+.file-icon-otf,
+.file-icon-woff,
+.file-icon-woff2{fill:#C4CA10}
+.file-icon-doc,
+.file-icon-docx,
+.file-icon-rtf,
+.file-icon-odt{fill:#0F70B7}
+.file-icon-csv,
+.file-icon-ods,
+.file-icon-xls,
+.file-icon-xlsx{fill:#3BAA34}
+.file-icon-odp,
+.file-icon-ppt,
+.file-icon-pptx{fill:#D04526}
+.file-icon-rar,
+.file-icon-tar,
+.file-icon-zip{fill:#363A56}
div[data-control="media-manager"]:focus{outline:none}
div[data-control="media-manager"] audio,
div[data-control="media-manager"] video{width:100%}
div[data-control="media-manager"] video{background:#ecf0f1;max-height:225px}
-div[data-control="media-manager"] .file-icon{fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;display:inline-block}
-div[data-control="media-manager"] .file-icon-extension{font-family:'ArialMT','Arial',sans-serif;font-size:4em;font-weight:900;fill:#fff}
-div[data-control="media-manager"] .file-icon-label{fill:#576D7E;fill-rule:nonzero}
-div[data-control="media-manager"] .file-icon-css,
-div[data-control="media-manager"] .file-icon-less,
-div[data-control="media-manager"] .file-icon-scss{fill:#B73FD9}
-div[data-control="media-manager"] .file-icon-html,
-div[data-control="media-manager"] .file-icon-xml{fill:#EA9B47}
-div[data-control="media-manager"] .file-icon-js,
-div[data-control="media-manager"] .file-icon-json{fill:#A9A9A9}
-div[data-control="media-manager"] .file-icon-pdf{fill:#E30713}
-div[data-control="media-manager"] .file-icon-txt{fill:#248BD0}
-div[data-control="media-manager"] .file-icon-ai{fill:#F29200}
-div[data-control="media-manager"] .file-icon-eps{fill:#F9B234}
-div[data-control="media-manager"] .file-icon-psd{fill:#2DAAE2}
-div[data-control="media-manager"] .file-icon-ttf,
-div[data-control="media-manager"] .file-icon-otf,
-div[data-control="media-manager"] .file-icon-woff,
-div[data-control="media-manager"] .file-icon-woff2{fill:#C4CA10}
-div[data-control="media-manager"] .file-icon-doc,
-div[data-control="media-manager"] .file-icon-docx,
-div[data-control="media-manager"] .file-icon-rtf,
-div[data-control="media-manager"] .file-icon-odt{fill:#0F70B7}
-div[data-control="media-manager"] .file-icon-csv,
-div[data-control="media-manager"] .file-icon-ods,
-div[data-control="media-manager"] .file-icon-xls,
-div[data-control="media-manager"] .file-icon-xlsx{fill:#3BAA34}
-div[data-control="media-manager"] .file-icon-odp,
-div[data-control="media-manager"] .file-icon-ppt,
-div[data-control="media-manager"] .file-icon-pptx{fill:#D04526}
-div[data-control="media-manager"] .file-icon-rar,
-div[data-control="media-manager"] .file-icon-tar,
-div[data-control="media-manager"] .file-icon-zip{fill:#363A56}
div[data-control="media-manager"] .media-player-fallback{font-size:13px;color:#95a5a6;background:#ecf0f1;line-height:180%}
div[data-control="media-manager"] .media-player-fallback.panel-embedded{padding:20px;margin:-20px -20px 0 -20px}
div[data-control="media-manager"] .empty-library{padding:20px;text-align:center}
diff --git a/modules/backend/widgets/mediamanager/assets/less/mediamanager.less b/modules/backend/widgets/mediamanager/assets/less/mediamanager.less
index 3aa47365bd..2ab52f9e3b 100644
--- a/modules/backend/widgets/mediamanager/assets/less/mediamanager.less
+++ b/modules/backend/widgets/mediamanager/assets/less/mediamanager.less
@@ -1,4 +1,5 @@
@import "../../../../../backend/assets/less/core/boot.less";
+@import "../../../../../backend/assets/less/controls/file-icon.less";
@color-media-list-hover-bg: mix(white, @brand-secondary, 13%);
@@ -63,83 +64,6 @@ div[data-control="media-manager"] {
max-height: 225px;
}
- .file-icon {
- fill-rule: evenodd;
- clip-rule: evenodd;
- stroke-linejoin: round;
- stroke-miterlimit: 2;
- display: inline-block;
-
- &-extension {
- font-family: 'ArialMT','Arial',sans-serif;
- font-size: 4em;
- font-weight: 900;
- fill: #fff;
- }
-
- &-label {
- fill: #576D7E; /* Default color */
- fill-rule: nonzero;
- }
-
- &-css,
- &-less,
- &-scss {
- fill: #B73FD9;
- }
- &-html,
- &-xml {
- fill: #EA9B47;
- }
- &-js,
- &-json {
- fill: #A9A9A9;
- }
- &-pdf {
- fill: #E30713;
- }
- &-txt {
- fill: #248BD0;
- }
- &-ai {
- fill: #F29200;
- }
- &-eps {
- fill: #F9B234;
- }
- &-psd {
- fill: #2DAAE2;
- }
- &-ttf,
- &-otf,
- &-woff,
- &-woff2 {
- fill: #C4CA10;
- }
- &-doc,
- &-docx,
- &-rtf,
- &-odt {
- fill: #0F70B7;
- }
- &-csv,
- &-ods,
- &-xls,
- &-xlsx {
- fill: #3BAA34;
- }
- &-odp,
- &-ppt,
- &-pptx {
- fill: #D04526;
- }
- &-rar,
- &-tar,
- &-zip {
- fill: #363A56;
- }
- }
-
.media-player-fallback {
font-size: 13px;
color: #95a5a6;
diff --git a/modules/backend/widgets/mediamanager/partials/_item-icon.php b/modules/backend/widgets/mediamanager/partials/_item-icon.php
index 9b789b8158..b53502b099 100644
--- a/modules/backend/widgets/mediamanager/partials/_item-icon.php
+++ b/modules/backend/widgets/mediamanager/partials/_item-icon.php
@@ -1,20 +1,10 @@
- itemTypeToIconClass($item, $itemType);
- $extension = substr(strtolower(pathinfo($item->path, PATHINFO_EXTENSION)), 0, 4) ?? '???';
-
- if ($itemIconClass == 'icon-file'): ?>
-
+ itemTypeToIconClass($item, $itemType) ?>
+
+ = $this->makePartial('~/modules/backend/partials/_file_icon.php', [
+ 'extension' => pathinfo($item->path, PATHINFO_EXTENSION),
+ ]) ?>
From f6a26757952271a8d71104779b17f1a7708b0afb Mon Sep 17 00:00:00 2001
From: Meindert
Date: Thu, 8 Oct 2026 12:12:34 +0200
Subject: [PATCH 3/3] Add Backend::fileIcon() helper for file extension icons
The FileUpload widget and the MediaManager both render the icon through the helper instead of including the partial by path.
Co-Authored-By: Claude Opus 5.5
---
modules/backend/facades/Backend.php | 1 +
modules/backend/formwidgets/FileUpload.php | 5 ++---
modules/backend/helpers/Backend.php | 11 +++++++++++
.../{partials/_file_icon.php => views/file_icon.php} | 7 ++-----
.../widgets/mediamanager/partials/_item-icon.php | 4 +---
5 files changed, 17 insertions(+), 11 deletions(-)
rename modules/backend/{partials/_file_icon.php => views/file_icon.php} (66%)
diff --git a/modules/backend/facades/Backend.php b/modules/backend/facades/Backend.php
index 1d679a073b..ac40a7a1a1 100644
--- a/modules/backend/facades/Backend.php
+++ b/modules/backend/facades/Backend.php
@@ -12,6 +12,7 @@
* @method static \Illuminate\Http\RedirectResponse redirectIntended(string $path, int $status = 302, array $headers = [], ?bool $secure = null)
* @method static string date($dateTime, array $options = [])
* @method static string dateTime($dateTime, array $options = [])
+ * @method static string fileIcon(string $extension)
*
* @see \Backend\Helpers\Backend
*/
diff --git a/modules/backend/formwidgets/FileUpload.php b/modules/backend/formwidgets/FileUpload.php
index ec0a3ac1e7..df2df69b7c 100644
--- a/modules/backend/formwidgets/FileUpload.php
+++ b/modules/backend/formwidgets/FileUpload.php
@@ -4,6 +4,7 @@
use Backend\Classes\FormField;
use Backend\Classes\FormWidgetBase;
+use Backend\Facades\Backend;
use Backend\Widgets\Form;
use Exception;
use Illuminate\Support\Facades\Response;
@@ -561,9 +562,7 @@ protected function makeFileIcon($file): ?string
return null;
}
- return $this->makePartial('~/modules/backend/partials/_file_icon.php', [
- 'extension' => $extension,
- ]);
+ return Backend::fileIcon($extension);
}
/**
diff --git a/modules/backend/helpers/Backend.php b/modules/backend/helpers/Backend.php
index b38fd58c06..b12f18e68e 100644
--- a/modules/backend/helpers/Backend.php
+++ b/modules/backend/helpers/Backend.php
@@ -7,6 +7,7 @@
use Exception;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Request;
+use Illuminate\Support\Facades\View;
use System\Helpers\DateTime as DateTimeHelper;
use Winter\Storm\Router\Helper as RouterHelper;
use Winter\Storm\Support\Facades\Config;
@@ -182,6 +183,16 @@ public function dateTime($dateTime, $options = [])
return ''.PHP_EOL;
}
+ /**
+ * Returns the SVG markup for a generic file icon labelled with the given file extension.
+ */
+ public function fileIcon(string $extension): string
+ {
+ return View::make('backend::file_icon', [
+ 'extension' => substr(strtolower(ltrim($extension, '.')), 0, 4),
+ ])->render();
+ }
+
/**
* Decompiles the compilation asset files
*
diff --git a/modules/backend/partials/_file_icon.php b/modules/backend/views/file_icon.php
similarity index 66%
rename from modules/backend/partials/_file_icon.php
rename to modules/backend/views/file_icon.php
index 7fe53e61dd..4352e295ac 100644
--- a/modules/backend/partials/_file_icon.php
+++ b/modules/backend/views/file_icon.php
@@ -1,13 +1,10 @@
-
diff --git a/modules/backend/widgets/mediamanager/partials/_item-icon.php b/modules/backend/widgets/mediamanager/partials/_item-icon.php
index b53502b099..2177d27077 100644
--- a/modules/backend/widgets/mediamanager/partials/_item-icon.php
+++ b/modules/backend/widgets/mediamanager/partials/_item-icon.php
@@ -2,9 +2,7 @@
itemTypeToIconClass($item, $itemType) ?>
- = $this->makePartial('~/modules/backend/partials/_file_icon.php', [
- 'extension' => pathinfo($item->path, PATHINFO_EXTENSION),
- ]) ?>
+ = Backend::fileIcon(pathinfo($item->path, PATHINFO_EXTENSION)) ?>