Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
30c5cb5
Add code quality tools, lint configs, node deps, and PHP requirement
mike-sheppard May 1, 2026
e867003
Add support for icon sets/groupings + multiple theme path locations
mike-sheppard May 1, 2026
18790cc
Update README + move changelog to dedicated file and update it with l…
mike-sheppard May 1, 2026
ad686be
Add tests for all new methods
mike-sheppard May 1, 2026
2b8c42d
Use Mago + oxfmt for linting/formatting, much neater than WP rules
mike-sheppard May 1, 2026
0c5af06
Update Mago format, keep function/class braces same line
mike-sheppard May 1, 2026
302b96d
Update screenshot preview with groupings/sets
mike-sheppard May 1, 2026
47716f8
Bump phpstan to lvl 9 + fix issues
mike-sheppard May 1, 2026
d251416
Use PHPStan level 9 + fixes + update docs
mike-sheppard May 1, 2026
77416ed
Create css-customisation.md
mike-sheppard May 1, 2026
10aaaa5
Remove CSS customisation docs, not keen on support it across versions…
mike-sheppard May 1, 2026
6e83378
Drop dev-only version override; release version comes from git tag
mike-sheppard May 1, 2026
b845f43
Add ACF field option to limit to allowed icon sets
mike-sheppard May 1, 2026
bb0fbe0
Add tests + update changelog
mike-sheppard May 1, 2026
6e93953
Format tests as well
mike-sheppard May 1, 2026
b1f309c
Regenerate composer.lock + reformat mago.toml so CI checks pass
mike-sheppard May 1, 2026
292650c
Fixes for Copilot review: init guard, escape urls, sanitise keys, con…
mike-sheppard May 1, 2026
6509e3a
Pin platform PHP to 8.1 in composer config so the lock resolves to PH…
mike-sheppard May 1, 2026
b44cb1c
Add tearDown filter cleanup to keep tests isolated; drop the no-op re…
mike-sheppard May 1, 2026
64c2bff
Address Copilot review: fall back to aria-label when group has no hea…
mike-sheppard May 1, 2026
67a99ed
Title-case Allowed Groups field label
mike-sheppard May 1, 2026
4441494
Restyle picker grid with subtle border + shadow, label hidden until h…
mike-sheppard May 1, 2026
4190548
Fix sets slug collision, tidy js by moving templates out + bump to v5
mike-sheppard May 2, 2026
5462eb1
Fix code smells and remove v4 deprecations
mike-sheppard May 2, 2026
fd5b79b
Upgrade phpstan to v2 + level 10 + fix remaining issues
mike-sheppard May 2, 2026
27a10c5
Bump min PHP to 8.2, use Rector to tidy up, add 8.5 to tests
mike-sheppard May 2, 2026
6d32aac
Fix keyboard nav to respect cols
mike-sheppard May 2, 2026
a65c5b3
Add explicit missing state + show icon names in the UI
mike-sheppard May 5, 2026
d476bad
Tidy up docs
mike-sheppard May 5, 2026
cd0efe6
v5 code refactor + break-up + tidy
mike-sheppard May 5, 2026
25d3746
More performant filters/search + a11y keyboard fix
mike-sheppard May 5, 2026
51af268
Update project docs
mike-sheppard May 5, 2026
5488253
Tidy up our tooling configs
mike-sheppard May 5, 2026
0ed583e
Simplify CSS + nicer error state
mike-sheppard May 5, 2026
cc21225
Tidy spacing
mike-sheppard May 5, 2026
5fb3e87
Reset the missing-asset state
mike-sheppard May 5, 2026
17c1caf
Add array icon data return format
mike-sheppard May 5, 2026
d9793b6
Update docs
mike-sheppard May 5, 2026
e8a6bdc
Simplify/tidy codebase
mike-sheppard May 5, 2026
ba66d52
Update input.js
mike-sheppard May 5, 2026
b4c87c7
Update input.js
mike-sheppard May 5, 2026
51e5d51
Update README.md
mike-sheppard May 5, 2026
fda0210
Resolve PR comments
mike-sheppard May 5, 2026
10b8ceb
Enforce allowed_groups on render
mike-sheppard May 5, 2026
f44b2b4
Address PR comments
mike-sheppard May 5, 2026
9d38a69
Test cleanup
mike-sheppard May 5, 2026
17409e1
chore: Add mago.toml and package files to export-ignore in .gitattrib…
Levdbas May 6, 2026
06f44e6
fix: fix acf field class not available
Levdbas Jun 9, 2026
84b2ae5
feat: add POT file and added Dutch translation
Levdbas Jun 9, 2026
97e5dc5
chore: format package.json for consistency
Levdbas Jun 9, 2026
519d28f
chore: lint files
Levdbas Jun 9, 2026
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
33 changes: 21 additions & 12 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
/README.md export-ignore
/CONTRIBUTING.md export-ignore
/.gitattributes export-ignore
/.editorconfig export-ignore
/composer.lock export-ignore
/.gitignore export-ignore
/tests export-ignore
/screenshots export-ignore
/.github export-ignore
/.gitattributes export-ignore
/.github export-ignore
/.phpcs.xml.dist export-ignore
/phpunit.xml.dist export-ignore
/phpstan.neon export-ignore
/.gitignore export-ignore
/.oxfmtrc.json export-ignore
/.phpunit.result.cache export-ignore
/CONTRIBUTING.md export-ignore
/LICENSE.txt export-ignore
/bin export-ignore
/README.md export-ignore
/UPGRADING.md export-ignore
/bin export-ignore
/composer.lock export-ignore
/mago.toml export-ignore
/node_modules export-ignore
/package-lock.json export-ignore
/package.json export-ignore
/phpstan.neon export-ignore
/phpunit.xml.dist export-ignore
/screenshots export-ignore
/tests export-ignore
/wp-content export-ignore
/mago.toml export-ignore
/package-lock.json export-ignore
/package.json export-ignore
73 changes: 73 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Code quality

on:
push:
branches:
- main
pull_request:
branches:
- main
types:
- opened
- synchronize
- ready_for_review

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
phpstan:
name: PHPStan (level 10)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
tools: composer:v2

- uses: ramsey/composer-install@v4

- name: Run PHPStan
run: composer phpstan

mago-format:
name: Mago format check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
tools: composer:v2

- uses: ramsey/composer-install@v4

- name: Run Mago format check
run: composer format:check

oxc:
name: Oxfmt + Oxlint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: "22"
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Run Oxfmt format check
run: npm run format -- --check

- name: Run Oxlint
run: npm run lint
10 changes: 2 additions & 8 deletions .github/workflows/php-unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,15 @@ jobs:
strategy:
fail-fast: false
matrix:
php: ["8.1", "8.2", "8.3"]
php: ["8.2", "8.3", "8.4", "8.5"]
wp: ["latest", "6.3"]
multisite: ["0"]
dependency-version: ["highest"]
webp: [false]
coverage: [false]
experimental: [false]
include:
# PHP 8.4 / experimental
- php: "8.4"
wp: "trunk"
dependency-version: "highest"
multisite: "0"
experimental: true
# PHP 8.3 / experimental
# WP trunk smoke test on the newest stable PHP.
- php: "8.5"
wp: "trunk"
dependency-version: "highest"
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
vendor
wp-content
node_modules
.phpunit.result.cache
.DS_Store
17 changes: 17 additions & 0 deletions .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"singleQuote": true,
"sortPackageJson": false,
"ignorePatterns": [
"vendor/**",
"node_modules/**",
"wp-content/**",
"tests/assets/**",
".github/**",
"**/*.php",
"**/*.svg",
"**/*.md",
"composer.lock",
"package-lock.json"
]
}
24 changes: 0 additions & 24 deletions .phpcs.xml.dist

This file was deleted.

153 changes: 153 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Changelog

All notable changes to this project are documented here.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [5.0.0]

A major release focused on icon-set organisation, accessibility, and sane handling of stale data. See [UPGRADING.md](UPGRADING.md) for the v4 → v5 walkthrough.

### Added

- **Multiple icon locations** — `acf_svg_icon_picker_custom_location` now accepts a list of `{ path, url, name?, key? }` arrays. Each location renders as a named group in the picker UI; a single location with `'group_by_subdir' => true` exposes each top-level subfolder as its own group instead.
- **Per-field group filter** — new `allowed_groups` field setting restricts a specific field to a chosen subset of the configured groups (closes [#32](https://github.com/smithfield-studio/acf-svg-icon-picker/issues/32)).
- **Composite save format in grouped mode** (`groupkey.slug`, e.g. `nucleo.arrow-down`). Records the editor's explicit pick so the same slug can live in multiple groups without colliding. Strict resolution — see the missing-asset note below.
- **Missing-asset state in the editor.** When a saved value can't be resolved (file deleted, group renamed, etc.), the field renders a distinct red-tinted trigger with a `!` glyph and an inline status message ("Icon not found. Please replace or check original path: …"). Editors can spot stale data instead of mistaking it for a never-picked field. Frontend output unchanged.
- **Native `<dialog>` popup** — focus trap, Esc-to-close, focus restoration, inert background page all handled by the browser. Icon tiles are real `<button>` elements with `aria-label`. Arrow-key navigation across the grid (Left/Right step a tile, Up/Down jump a row, Home/End to extremes), with column preservation when crossing groups.
- **PHP 8.2 minimum**, declared via `composer.json` so install fails fast. PHP 8.1 reached EOL in Nov 2025.
- **`'array'` return format** + new `get_svg_icon_data()` helper. Returns `{ slug, url, path, title, group_key, group_name }`, or `null` when the saved value no longer resolves. SVG markup is intentionally omitted to keep the format cheap on long lists — call `get_svg_icon($slug)` when markup is needed.

### Breaking

- **Deprecated filters removed** — `acf_icon_path`, `acf_icon_url`, `acf_icon_path_suffix` (deprecated since 4.0.0). Use `acf_svg_icon_picker_folder` instead.
- **Global constants removed** — `ACF_SVG_ICON_PICKER_VERSION`, `_URL`, `_PATH`. Version is now `\SmithfieldStudio\AcfSvgIconPicker\ACF_Field_Svg_Icon_Picker::VERSION`; URL/path are derived inline at use sites.
- **DOM hooks renamed** for custom CSS that targets the picker UI:
- `.acf-svg-icon-picker__popup-overlay` → `.acf-svg-icon-picker__popup::backdrop`
- `.acf-svg-icon-picker__popup ul li[data-svg]` → `.acf-svg-icon-picker__option`
- **Browser baseline raised** by the native `<dialog>` move: Chrome 37+, Firefox 98+, Safari 15.4+. WP admin only — frontend unchanged.
- **Composite save values** in grouped mode. Code that reads via `get_field()` + `get_svg_icon*()` keeps working (helpers accept both forms). Custom code that does its own slug → file lookup needs to handle the `groupkey.slug` form (`str_replace('.', '/', $slug) . '.svg'` is a reasonable default).
- **Custom-location filter is now authoritative.** Previously, when `acf_svg_icon_picker_custom_location` resolved to no icons (wrong path, empty dir) the picker silently fell back to scanning the active theme dirs, hiding the broken config. The filter is now the source of truth when set — an empty result surfaces as "no icons" with the existing diagnostic message rather than substituting theme icons.
- **`allowed_groups` is enforced server-side, not just in the picker UI.** A saved value whose source group isn't in the field's allowlist now renders as missing-asset (instead of silently showing an icon from a disallowed group), and `update_value`'s bare-slug → composite canonicalisation only matches within the allowlist. Stale allowlists (no live-group matches) fall open the same way the picker JS does, so misconfigured fields stay recoverable.

### Fixed

- `get_svg_icon_uri()` returns the matching custom-location URL instead of always falling back to `get_theme_file_uri()` (which 404'd whenever icons lived outside the theme).
- Pressing Enter anywhere in the admin no longer opens the icon picker ([#34](https://github.com/smithfield-studio/acf-svg-icon-picker/issues/34)) — trigger and remove buttons were missing `type="button"` and defaulted to `type="submit"`.
- Numerous a11y gaps in the popup: missing dialog role, no focus trap, no Esc handler, no focus restoration, unlabelled search input and close button, list items not keyboard-focusable.
- `group_by_subdir` resolution for non-slug folder names — the helper now scans subdirs and matches via `sanitize_title($subdir)`, so `Brand Icons/` on disk resolves saved values like `brand-icons.foo`.
- Group-key collisions auto-disambiguate with `-2`, `-3`, … rather than letting later locations silently overwrite or merge into earlier ones.

## [4.3.1]

- fix: Increase z-index of SVG icon picker overlay so it sits above the block-editor extended view, co-authored by @adambichler in #38.
- chore: Update GitHub Actions workflows to use latest PHP versions.
- chore: Code formatting pass.

## [4.3.0]

- Change action hook for field type registration by @EarthmanWeb in #37.
- Update GitHub Actions workflows to use latest PHP versions.

## [4.2.0]

- `get_svg_icon_path()` helper function now returns the correct path when using the custom location filter.

## [4.1.0]

- Add ability to return the icon markup directly from the field via `'return_format' => 'icon'`.
- Enhance markup of the icon picker modal and field.
- Update hook docs in README, by @huubl in #29.
- Add tests for the new return format.
- Run PHPCS on PRs.

## [4.0.1]

- Fix version numbers in constant.
- Add files to export ignore.

## [4.0.0]

- Remove/deprecate legacy filters; refactor and simplify icon path filters, by [@Levdbas](https://github.com/Levdbas) in [#25](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/25).
- Add unit tests, PHPStan, and return types, by [@Levdbas](https://github.com/Levdbas) in [#25](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/25).
- Better support for hashed assets, by [@mike-sheppard](https://github.com/mike-sheppard) in [#26](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/26).

## [3.1.4]

- Fix filter on filenames with diacritical marks, by [@Rvervuurt](https://github.com/Rvervuurt) in [#21](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/21).

## [3.1.3]

- Added MutationObserver, by [@chrisbakr](https://github.com/chrisbakr) in [#20](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/20).

## [3.1.2]

- Add debounce to improve filter performance, by [@stefanmomm](https://github.com/stefanmomm) in [#17](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/17).

## [3.1.1]

- Optimize css, by [@stefanmomm](https://github.com/stefanmomm) in [#16](https://github.com/smithfield-studio/acf-svg-icon-picker/pull/16).

## [3.1.0]

- Changed name of field to `svg_icon_picker` to avoid conflicts with vanilla ACF Icon Picker field.

## [3.0.0]

- Revert to original ACF field name, quick tidy + README updates.

## [2.0.0]

- Fix for ACF 6.3 which now has an official icon-picker field, plus merged open PRs from [@Levdbas](https://github.com/Levdbas) in [#38](https://github.com/houke/acf-icon-picker/pull/38) and [@phschmanau](https://github.com/phschmanau) in [#37](https://github.com/houke/acf-icon-picker/pull/37).

---

**Forked from [houke/acf-icon-picker](https://github.com/houke/acf-icon-picker).** Pre-fork history below.

---

## [1.9.1]

- ACF 6 compatibility fix, by [@idflood](https://github.com/idflood) in [#30](https://github.com/houke/acf-icon-picker/pull/30).

## [1.9.0]

- Fix issue with Gutenberg preview not updating when removing, by [@cherbst](https://github.com/cherbst) in [#23](https://github.com/houke/acf-icon-picker/pull/23).

## [1.8.0]

- Fix issue with Gutenberg not saving icon, by [@tlewap](https://github.com/tlewap) in [#17](https://github.com/houke/acf-icon-picker/pull/17).

## [1.7.0]

- 2 new filters for more control over icon path, by [@benjibee](https://github.com/benjibee) in [#11](https://github.com/houke/acf-icon-picker/pull/11).

## [1.6.0]

- Performance fix with lots of icons, by [@idflood](https://github.com/idflood) in [#9](https://github.com/houke/acf-icon-picker/pull/9).

## [1.5.0]

- Fix issue where searching for icons would break preview if icon name has space.

## [1.4.0]

- Add filter to change folder where svg icons are stored.

## [1.3.0]

- Adding close option on modal.

## [1.2.0]

- Adding search filter input to filter through icons by name.

## [1.1.0]

- Add button to remove the selected icon when the field is not required.

## [1.0.0]

- First release.
Loading
Loading