Rework handling of icons and tinting of external icons

This commit is contained in:
2026-02-25 13:34:34 +01:00
parent f0b768e5bb
commit 582ed5fd60
31 changed files with 70 additions and 134 deletions

View File

@@ -5,4 +5,21 @@ This is a fork of the original default dokuwiki template.
## Changes from the original template ## Changes from the original template
- Default font changed to "Perfect DOS VGA 437 Win" - Default font changed to "Perfect DOS VGA 437 Win"
- Enhanced header search with DokuWiki quicksearch suggestions, keyboard navigation, and disabled browser autofill - Enhanced header search with DokuWiki quicksearch suggestions, keyboard navigation, and disabled browser autofill
## Icon theming (light/dark)
- Header tool icons (user tools and site tools) are rendered as inline SVG.
- The pagetools footer is intentionally text-only (no icons).
- Icon color is controlled through `@ini_icons` (placeholder `__icons__`) in [replacements] inside `style.ini`.
- Hover/active icon color follows `@ini_link` to match link interaction color.
## Edit toolbar icons
- The edit page toolbar (`?do=edit`) is generated by DokuWiki core and uses PNG toolbar images.
- This template converts those toolbar `<img>` icons to CSS mask icons at runtime, then applies `@ini_icons`.
- Hover/active/focus color follows `@ini_link`.
- This keeps DokuWiki core files untouched while still allowing light/dark icon theming.
### About coloring SVG icons from the outside
- Recommended: inline SVG + CSS (`fill`, `stroke`, or `currentColor`).
- Limited: external SVG via `<img>` or `background-image` cannot reliably be recolored with plain CSS.
- Workarounds for external SVG exist (`mask-image`, CSS `filter`), but they are less maintainable and less precise.

View File

@@ -30,6 +30,27 @@
float: right; float: right;
} }
.dokuwiki div.toolbar #tool__bar button.toolbutton .toolicon {
display: inline-block;
width: 16px;
height: 16px;
background-color: @ini_icons;
-webkit-mask-image: var(--icon-url);
mask-image: var(--icon-url);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-position: center;
mask-position: center;
-webkit-mask-size: contain;
mask-size: contain;
}
.dokuwiki div.toolbar #tool__bar button.toolbutton:hover .toolicon,
.dokuwiki div.toolbar #tool__bar button.toolbutton:active .toolicon,
.dokuwiki div.toolbar #tool__bar button.toolbutton:focus .toolicon {
background-color: @ini_link;
}
/* picker popups (outside of .dokuwiki) */ /* picker popups (outside of .dokuwiki) */
div.picker { div.picker {
width: 300px; width: 300px;

View File

@@ -79,7 +79,6 @@
text-transform: uppercase; text-transform: uppercase;
} }
/* Hide SVG icons - we use text-only status bar style */
svg { svg {
display: none; display: none;
} }

View File

@@ -19,7 +19,7 @@
height: 1.4em; height: 1.4em;
width: 1.4em; width: 1.4em;
vertical-align: middle; vertical-align: middle;
fill: @ini_border; fill: @ini_icons;
margin-right: 0.2em; margin-right: 0.2em;
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 207 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 178 B

View File

@@ -1,5 +0,0 @@
Icons for: sitetools.png
Icon set: Dusseldorf
Designer: pc.de
License: Creative Commons Attribution License [http://creativecommons.org/licenses/by/3.0/]
URL: http://pc.de/icons/#Dusseldorf

View File

@@ -1,121 +0,0 @@
<?php
// phpcs:ignoreFile -- deprecated and will be removed
/**
* This script generates a sprite from the unprocessed pagetool icons by combining them
* and overlaying a color layer for the active state.
*
* This script requires a current libGD to be available.
*
* The color for the active state is read from the style.ini's __link__ replacement
*
* The final sprite is optimized with optipng if available.
*
* @author Andreas Gohr <andi@splitbrain.org>
* @deprecated 2018-06-15 we no longer use PNG based icons
* @todo Maybe add some more error checking
*/
$GAMMA = 0.8;
$OPTIPNG = '/usr/bin/optipng';
if('cli' != PHP_SAPI) die('please run from commandline');
// load input images
$input = glob('pagetools/*.png');
sort($input);
$cnt = count($input);
if(!$cnt){
die("No input images found. This script needs to be called from within the image directory!\n");
}
// create destination image
$DST = imagecreatetruecolor(30,$cnt*45*2);
imagesavealpha($DST, true);
$C_trans = imagecolorallocatealpha($DST, 0, 0, 0, 127);
imagefill($DST, 0, 0, $C_trans);
// load highlight color from style.ini
$ini = parse_ini_file('../style.ini',true);
$COLOR = hex2rgb($ini['replacements']['__link__']);
$C_active = imagecolorallocate($DST, $COLOR['r'],$COLOR['g'],$COLOR['b']);
// add all the icons to the sprite image
for($i=0; $i<$cnt; $i++){
$base = $i*90;
$IN = imagecreatefrompng($input[$i]);
imagesavealpha($IN, true);
imagecolorscale($IN,$GAMMA);
imagecopy($DST,$IN, 0,$base, 0,0, 30,30);
imagedestroy($IN);
$IN = imagecreatefrompng($input[$i]);
imagesavealpha($IN, true);
imagecolorscale($IN,$GAMMA);
imagecopy($DST,$IN, 0,$base+45, 0,0, 30,30);
imagedestroy($IN);
imagelayereffect($DST, IMG_EFFECT_OVERLAY);
imagefilledrectangle($DST, 0,$base+45, 30,$base+45+30, $C_active);
imagelayereffect($DST, IMG_EFFECT_NORMAL);
}
// output sprite
imagepng($DST,'pagetools-sprite.png');
imagedestroy($DST);
// optimize if possible
if(is_executable($OPTIPNG)){
system("$OPTIPNG -o5 'pagetools-sprite.png'");
}
/**
* Convert a hex color code to an rgb array
*/
function hex2rgb($hex) {
// strip hash
$hex = str_replace('#', '', $hex);
// normalize short codes
if(strlen($hex) == 3){
$hex = substr($hex,0,1).
substr($hex,0,1).
substr($hex,1,1).
substr($hex,1,1).
substr($hex,2,1).
substr($hex,2,1);
}
// calc rgb
return ['r' => hexdec(substr($hex, 0, 2)), 'g' => hexdec(substr($hex, 2, 2)), 'b' => hexdec(substr($hex, 4, 2))];
}
/**
* Scale (darken/lighten) a given image
*
* @param resource $img The truetype GD image to work on
* @param float $scale Scale the colors by this value ( <1 darkens, >1 lightens)
*/
function imagecolorscale(&$img, $scale){
$w = imagesx($img);
$h = imagesy($img);
imagealphablending($img, false);
for($x = 0; $x < $w; $x++){
for($y = 0; $y < $h; $y++){
$rgba = imagecolorat($img, $x, $y);
$a = ($rgba >> 24) & 0xFF;
$r = ($rgba >> 16) & 0xFF;
$g = ($rgba >> 8) & 0xFF;
$b = $rgba & 0xFF;
$r = max(min(round($r*$scale),255),0);
$g = max(min(round($g*$scale),255),0);
$b = max(min(round($b*$scale),255),0);
$color = imagecolorallocatealpha($img, $r, $g, $b, $a);
imagesetpixel($img, $x, $y, $color);
}
}
imagealphablending($img, true);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 519 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 288 B

View File

@@ -1,4 +0,0 @@
Icon set: iPhone toolbar icons
Designer: TheWorkingGroup.ca
License: Creative Commons Attribution-Share Alike License [http://creativecommons.org/licenses/by-sa/3.0/]
URL: http://blog.twg.ca/2009/09/free-iphone-toolbar-icons/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -87,6 +87,34 @@ jQuery(function(){
this.blur(); this.blur();
}); });
// make edit toolbar icons themeable by converting img icons to CSS masks
(function enhanceEditToolbarIcons() {
function toMaskIcons() {
jQuery('.dokuwiki #tool__bar button.toolbutton img').each(function () {
var $img = jQuery(this);
var src = $img.attr('src');
if (!src) {
return;
}
var $icon = jQuery('<span/>', {
'class': 'toolicon',
'aria-hidden': 'true'
});
$icon[0].style.setProperty('--icon-url', 'url("' + src.replace(/"/g, '\\"') + '")');
$img.replaceWith($icon);
});
}
toMaskIcons();
var toolbar = document.getElementById('tool__bar');
if (toolbar && window.MutationObserver) {
new MutationObserver(toMaskIcons).observe(toolbar, {childList: true, subtree: true});
}
}());
// enhance header search with suggestions and keyboard navigation // enhance header search with suggestions and keyboard navigation
(function enhanceSearch(){ (function enhanceSearch(){
var $input = jQuery('#qsearch__in'); var $input = jQuery('#qsearch__in');

View File

@@ -70,6 +70,7 @@ __highlight__ = "#ff9" ; @ini_highlight
; links ; links
__link__ = "#2b73b7" ; @ini_link __link__ = "#2b73b7" ; @ini_link
__icons__ = "#666" ; @ini_icons
__luxtools_locationlink__ = "#b57d35" ; @ini_luxtools_locationlink __luxtools_locationlink__ = "#b57d35" ; @ini_luxtools_locationlink
;-------------------------------------------------------------------------- ;--------------------------------------------------------------------------

View File

@@ -66,7 +66,7 @@ if (!defined('DOKU_INC')) die();
<?php echo (new \dokuwiki\Menu\MobileMenu())->getDropdown($lang['tools']); ?> <?php echo (new \dokuwiki\Menu\MobileMenu())->getDropdown($lang['tools']); ?>
</div> </div>
<ul> <ul>
<?php echo (new \dokuwiki\Menu\SiteMenu())->getListItems('action ', false); ?> <?php echo (new \dokuwiki\Menu\SiteMenu())->getListItems('action '); ?>
</ul> </ul>
</div> </div>