diff --git a/classes/feeds.php b/classes/feeds.php
index 62fd6a5b3901667d775d4e80a31667469bba2c3a..503108e41065b79719042cdb8de1159285d25688 100755
--- a/classes/feeds.php
+++ b/classes/feeds.php
@@ -133,7 +133,7 @@ class Feeds extends Handler_Protected {
 		$reply['vfeed_group_enabled'] = $vfeed_group_enabled;
 
 		$plugin_menu_items = "";
-		PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM,
+		PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2,
 			function ($result) use (&$plugin_menu_items) {
 				$plugin_menu_items .= $result;
 			},
diff --git a/classes/plugin.php b/classes/plugin.php
index be837692589564ee7f481770108d0a6960558a62..3bced3b04640df514669b07534096bcac7b3c31f 100644
--- a/classes/plugin.php
+++ b/classes/plugin.php
@@ -647,6 +647,7 @@ abstract class Plugin {
 	}
 
 	/** Allows adding custom elements to headlines Select... dropdown
+	 * @deprecated removed, see Plugin::hook_headline_toolbar_select_menu_item2()
 	 * @param int $feed_id
 	 * @param int $is_cat
 	 * @return string
@@ -658,6 +659,18 @@ abstract class Plugin {
 		return "";
 	}
 
+	/** Allows adding custom elements to headlines Select... select dropdown (<option> format)
+	 * @param int $feed_id
+	 * @param int $is_cat
+	 * @return string
+	 * @see PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2
+	 */
+	function hook_headline_toolbar_select_menu_item2($feed_id, $is_cat) {
+		user_error("Dummy method invoked.", E_USER_ERROR);
+
+		return "";
+	}
+
 	/** Invoked when user tries to subscribe to feed, may override information (i.e. feed URL) used afterwards
 	 * @param string $url
 	 * @param string $auth_login
diff --git a/classes/pluginhost.php b/classes/pluginhost.php
index a3a389def29047d53ad48ccc161f323e70bbc965..952d4df77cb9a0f4416e04c6a36a6f58e90d1c9f 100755
--- a/classes/pluginhost.php
+++ b/classes/pluginhost.php
@@ -189,9 +189,14 @@ class PluginHost {
 	/** @see Plugin::hook_headlines_custom_sort_override() */
 	const HOOK_HEADLINES_CUSTOM_SORT_OVERRIDE = "hook_headlines_custom_sort_override";
 
-	/** @see Plugin::hook_headline_toolbar_select_menu_item() */
+	/** @see Plugin::hook_headline_toolbar_select_menu_item()
+	 * @deprecated removed, see PluginHost::HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2
+	*/
 	const HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM = "hook_headline_toolbar_select_menu_item";
 
+	/** @see Plugin::hook_headline_toolbar_select_menu_item() */
+	const HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2 = "hook_headline_toolbar_select_menu_item2";
+
 	/** @see Plugin::hook_pre_subscribe() */
 	const HOOK_PRE_SUBSCRIBE = "hook_pre_subscribe";
 
@@ -270,9 +275,10 @@ class PluginHost {
 	 * @param mixed $args
 	 */
 	function run_hooks(string $hook, ...$args): void {
-		$method = strtolower($hook);
 
-		foreach ($this->get_hooks($hook) as $plugin) {
+		$method = strtolower((string)$hook);
+
+		foreach ($this->get_hooks((string)$hook) as $plugin) {
 			//Debug::log("invoking: " . get_class($plugin) . "->$hook()", Debug::$LOG_VERBOSE);
 
 			try {
@@ -291,9 +297,9 @@ class PluginHost {
 	 * @param mixed $check
 	 */
 	function run_hooks_until(string $hook, $check, ...$args): bool {
-		$method = strtolower($hook);
+		$method = strtolower((string)$hook);
 
-		foreach ($this->get_hooks($hook) as $plugin) {
+		foreach ($this->get_hooks((string)$hook) as $plugin) {
 			try {
 				$result = $plugin->$method(...$args);
 
@@ -315,9 +321,9 @@ class PluginHost {
 	 * @param mixed $args
 	 */
 	function run_hooks_callback(string $hook, Closure $callback, ...$args): void {
-		$method = strtolower($hook);
+		$method = strtolower((string)$hook);
 
-		foreach ($this->get_hooks($hook) as $plugin) {
+		foreach ($this->get_hooks((string)$hook) as $plugin) {
 			//Debug::log("invoking: " . get_class($plugin) . "->$hook()", Debug::$LOG_VERBOSE);
 
 			try {
@@ -336,9 +342,9 @@ class PluginHost {
 	 * @param mixed $args
 	 */
 	function chain_hooks_callback(string $hook, Closure $callback, &...$args): void {
-		$method = strtolower($hook);
+		$method = strtolower((string)$hook);
 
-		foreach ($this->get_hooks($hook) as $plugin) {
+		foreach ($this->get_hooks((string)$hook) as $plugin) {
 			//Debug::log("invoking: " . get_class($plugin) . "->$hook()", Debug::$LOG_VERBOSE);
 
 			try {
@@ -358,7 +364,7 @@ class PluginHost {
 	function add_hook(string $type, Plugin $sender, int $priority = 50): void {
 		$priority = (int) $priority;
 
-		if (!method_exists($sender, strtolower($type))) {
+		if (!method_exists($sender, strtolower((string)$type))) {
 			user_error(
 				sprintf("Plugin %s tried to register a hook without implementation: %s",
 					get_class($sender), $type),
@@ -422,7 +428,7 @@ class PluginHost {
 
 		asort($plugins);
 
-		$this->load(join(",", $plugins), $kind, $owner_uid, $skip_init);
+		$this->load(join(",", $plugins), (int)$kind, $owner_uid, $skip_init);
 	}
 
 	/**
diff --git a/index.php b/index.php
index 538346549516c841d55cdbf2de7dc17f71158944..2dbc078cd056e26fa3e8ff7df7d7f1da7f5cb34b 100644
--- a/index.php
+++ b/index.php
@@ -215,20 +215,13 @@
 						?>
 	            </select>
 
-					<div class="catchup-button" dojoType="fox.form.ComboButton" onclick="Feeds.catchupCurrent()">
-						<span><?= __('Mark as read') ?></span>
-						<div dojoType="dijit.DropDownMenu">
-							<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('1day')">
-									<?= __('Older than one day') ?>
-							</div>
-							<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('1week')">
-									<?= __('Older than one week') ?>
-							</div>
-							<div dojoType="dijit.MenuItem" onclick="Feeds.catchupCurrent('2week')">
-									<?= __('Older than two weeks') ?>
-							</div>
-						</div>
-					</div>
+					<select class="catchup-button" id="main-catchup-dropdown" dojoType="fox.form.Select"
+						data-prevent-value-change="true">
+						<option value=""><?= __('Mark as read') ?></option>
+						<option value="1day"><?= __('Older than one day') ?></option>
+						<option value="1week"><?= __('Older than one week') ?></option>
+						<option value="2week"><?= __('Older than two weeks') ?></option>
+					</select>
 
             </form>
 
diff --git a/js/Feeds.js b/js/Feeds.js
index 5ef554af08f292a2135cfb53728cd957a93d49f1..714eb77d25c9c380225fb012bb650fa822c6771c 100644
--- a/js/Feeds.js
+++ b/js/Feeds.js
@@ -282,6 +282,10 @@ const	Feeds = {
 			CommonDialogs.safeModeWarning();
 		}
 
+		dojo.connect(dijit.byId("main-catchup-dropdown"), 'onItemClick',
+			(item) => Feeds.catchupCurrent(item.option.value)
+		);
+
 		// bw_limit disables timeout() so we request initial counters separately
 		if (App.getInitParam("bw_limit")) {
 			this.requestCounters();
diff --git a/js/Headlines.js b/js/Headlines.js
index 7557676ee81bfeb0487d739e9cf458e8724a05f5..b64ba6bca147f281609a9447fe59b6b420626826 100755
--- a/js/Headlines.js
+++ b/js/Headlines.js
@@ -626,6 +626,12 @@ const Headlines = {
 		const search_query = Feeds._search_query ? Feeds._search_query.query : "";
 		const target = dijit.byId('toolbar-headlines');
 
+		// TODO: is this needed? destroyDescendants() below might take care of it (?)
+		if (this._headlinesSelectClickHandle)
+			dojo.disconnect(this._headlinesSelectClickHandle);
+
+		target.destroyDescendants();
+
 		if (tb && typeof tb == 'object') {
 			target.attr('innerHTML',
 			`
@@ -646,27 +652,37 @@ const Headlines = {
 				</span>
 				<span class='right'>
 					<span id='selected_prompt'></span>
-					<div class='select-articles-dropdown' dojoType='fox.form.DropDownButton' title='"${__('Select articles')}'>
-						<span>${__("Select...")}</span>
-						<div dojoType='dijit.Menu' style='display: none;'>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.select("all")'>${__('All')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.select("unread")'>${__('Unread')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.select("invert")'>${__('Invert')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.select("none")'>${__('None')}</div>
-						<div dojoType='dijit.MenuSeparator'></div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleUnread()'>${__('Toggle unread')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.selectionToggleMarked()'>${__('Toggle starred')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.selectionTogglePublished()'>${__('Toggle published')}</div>
-						<div dojoType='dijit.MenuSeparator'></div>
-						<div dojoType='dijit.MenuItem' onclick='Headlines.catchupSelection()'>${__('Mark as read')}</div>
-						<div dojoType='dijit.MenuItem' onclick='Article.selectionSetScore()'>${__('Set score')}</div>
-						${tb.plugin_menu_items}
+
+					<select class='select-articles-dropdown'
+						id='headlines-select-articles-dropdown'
+						data-prevent-value-change="true"
+						data-dropdown-skip-first="true"
+						dojoType="fox.form.Select"
+						title="${__('Show articles')}">
+						<option value='' selected="selected">${__("Select...")}</option>
+						<option value='headlines_select_all'>${__('All')}</option>
+						<option value='headlines_select_unread'>${__('Unread')}</option>
+						<option value='headlines_select_invert'>${__('Invert')}</option>
+						<option value='headlines_select_none'>${__('None')}</option>
+						<option></option>
+						<option value='headlines_selectionToggleUnread'>${__('Toggle unread')}</option>
+						<option value='headlines_selectionToggleMarked'>${__('Toggle starred')}</option>
+						<option value='headlines_selectionTogglePublished'>${__('Toggle published')}</option>
+						<option></option>
+						<option value='headlines_catchupSelection'>${__('Mark as read')}</option>
+						<option value='article_selectionSetScore'>${__('Set score')}</option>
+						${tb.plugin_menu_items != '' ?
+							`
+							<option></option>
+							${tb.plugin_menu_items}
+						` : ''}
 						${headlines.id === 0 && !headlines.is_cat ?
 							`
-							<div dojoType='dijit.MenuSeparator'></div>
-							<div dojoType='dijit.MenuItem' class='text-error' onclick='Headlines.deleteSelection()'>${__('Delete permanently')}</div>
+							<option></option>
+							<option class='text-error' value='headlines_deleteSelection'>${__('Delete permanently')}</option>
 							` : ''}
-					</div>
+					</select>
+
 					${tb.plugin_buttons}
 				</span>
 			`);
@@ -675,6 +691,48 @@ const Headlines = {
 		}
 
 		dojo.parser.parse(target.domNode);
+
+		this._headlinesSelectClickHandle = dojo.connect(dijit.byId("headlines-select-articles-dropdown"), 'onItemClick',
+			(item) => {
+				const action = item.option.value;
+
+				switch (action) {
+					case 'headlines_select_all':
+						Headlines.select('all');
+						break;
+					case 'headlines_select_unread':
+						Headlines.select('unread');
+						break;
+					case 'headlines_select_invert':
+						Headlines.select('invert');
+						break;
+					case 'headlines_select_none':
+						Headlines.select('none');
+						break;
+					case 'headlines_selectionToggleUnread':
+						Headlines.selectionToggleUnread();
+						break;
+					case 'headlines_selectionToggleMarked':
+						Headlines.selectionToggleMarked();
+						break;
+					case 'headlines_selectionTogglePublished':
+						Headlines.selectionTogglePublished();
+						break;
+					case 'headlines_catchupSelection':
+						Headlines.catchupSelection();
+						break;
+					case 'article_selectionSetScore':
+						Article.selectionSetScore();
+						break;
+					case 'headlines_deleteSelection':
+						Headlines.deleteSelection();
+						break;
+					default:
+						if (!PluginHost.run_until(PluginHost.HOOK_HEADLINE_TOOLBAR_SELECT_MENU_ITEM2, true, action))
+							console.warn('unknown headlines action', action);
+				}
+			}
+		);
 	},
 	onLoaded: function (reply, offset, append) {
 		console.log("Headlines.onLoaded: offset=", offset, "append=", append);
diff --git a/js/form/Select.js b/js/form/Select.js
index 530880e2da732eeb1722ccf4b182427d43af1db3..0c73cd52cc2c059bc51ea508c723ef21d8fc1b1b 100755
--- a/js/form/Select.js
+++ b/js/form/Select.js
@@ -1,8 +1,66 @@
-/* global dijit, define */
-define(["dojo/_base/declare", "dijit/form/Select"], function (declare) {
-	return declare("fox.form.Select", dijit.form.Select, {
+/* eslint-disable prefer-rest-params */
+/* global define */
+// FIXME: there probably is a better, more dojo-like notation for custom data- properties
+define(["dojo/_base/declare",
+	"dijit/form/Select",
+	"dojo/_base/lang", // lang.hitch
+	"dijit/MenuItem",
+	"dijit/MenuSeparator",
+	"dojo/aspect",
+	], function (declare, select, lang, MenuItem, MenuSeparator, aspect) {
+	return declare("fox.form.Select", select, {
 		focus: function() {
 			return; // Stop dijit.form.Select from keeping focus after closing the menu
 		},
+		startup: function() {
+         this.inherited(arguments);
+
+			if (this.attr('data-dropdown-skip-first') == 'true') {
+				aspect.before(this, "_loadChildren", () => {
+					this.options = this.options.splice(1);
+				});
+			}
+		},
+		// hook invoked when dropdown MenuItem is clicked
+		onItemClick: function(/*item, menu*/) {
+			//
+		},
+		_setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
+			if (this.attr('data-prevent-value-change') == 'true' && newValue != '')
+				return;
+
+			this.inherited(arguments);
+		},
+		// the only difference from dijit/form/Select is _onItemClicked() handler
+		_getMenuItemForOption: function(/*_FormSelectWidget.__SelectOption*/ option){
+         // summary:
+         //    For the given option, return the menu item that should be
+         //    used to display it.  This can be overridden as needed
+         if (!option.value && !option.label){
+            // We are a separator (no label set for it)
+            return new MenuSeparator({ownerDocument: this.ownerDocument});
+         } else {
+            // Just a regular menu option
+            const click = lang.hitch(this, "_setValueAttr", option);
+            const item = new MenuItem({
+               option: option,
+               label: (this.labelType === 'text' ? (option.label || '').toString()
+                  .replace(/&/g, '&amp;').replace(/</g, '&lt;') :
+                  option.label) || this.emptyLabel,
+               onClick: () => {
+						this.onItemClick(item, this.dropDown);
+
+						click();
+					},
+               ownerDocument: this.ownerDocument,
+               dir: this.dir,
+               textDir: this.textDir,
+               disabled: option.disabled || false
+            });
+            item.focusNode.setAttribute("role", "option");
+
+            return item;
+         }
+      },
 	});
 });