diff --git a/web/src/assets/styles/blocks.scss b/web/src/assets/styles/blocks.scss
index bafe238f42..e30dd7e91f 100644
--- a/web/src/assets/styles/blocks.scss
+++ b/web/src/assets/styles/blocks.scss
@@ -431,6 +431,32 @@ ul[data-type="agama/list"][role="grid"] {
}
}
+[data-type="agama/options-picker"] {
+ display: grid;
+ grid-template-columns: repeat(4, 1fr);
+ gap: var(--spacer-smaller);
+
+ [role="option"] {
+ cursor: pointer;
+ border: 1px solid var(--color-gray);
+ padding: var(--spacer-small);
+ border-block-end-width: 4px;
+
+ &[aria-selected="true"] {
+ background: var(--color-gray-light);
+ border-block-end-color: var(--color-primary);
+ }
+
+ >:first-child {
+ margin-block-end: var(--spacer-small);
+ }
+
+ >:last-child {
+ font-size: var(--fs-small);
+ }
+ }
+}
+
[role="dialog"] {
section:not([class^="pf-c"]) {
> svg:first-child {
diff --git a/web/src/components/core/OptionsPicker.jsx b/web/src/components/core/OptionsPicker.jsx
new file mode 100644
index 0000000000..55cc44f850
--- /dev/null
+++ b/web/src/components/core/OptionsPicker.jsx
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) [2024] SUSE LLC
+ *
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, contact SUSE LLC.
+ *
+ * To contact SUSE LLC about this file by physical or electronic mail, you may
+ * find current contact information at www.suse.com.
+ */
+
+import React from "react";
+
+/**
+ * Wrapper for OptionsPicker options
+ * @component
+ *
+ * @param {object} props
+ * @param {string} [props.title] - Text to be used as option title
+ * @param {string} [props.body] - Text to be used as option body
+ * @param {boolean} [props.isSelected=false] - Whether the option should be set as select of not
+ * @param {object} [props.props] - Other props sent to div#option node
+ */
+const Option = ({ title, body, isSelected = false, ...props }) => {
+ return (
+
+
{title}
+
{body}
+
+ );
+};
+
+/**
+ * Helper component to build rich options picker
+ * @component
+ *
+ * @param {object} props
+ * @param {string} [props.ariaLabel] - Text to be used as accessible label
+ * @param {Array