diff --git a/src/UI/Components/ActionCard.js b/src/UI/Components/ActionCard.js
new file mode 100644
index 000000000..8c65b9118
--- /dev/null
+++ b/src/UI/Components/ActionCard.js
@@ -0,0 +1,39 @@
+const Component = use('util.Component');
+
+export default def(class ActionCard extends Component {
+ static ID = 'ui.component.ActionCard';
+ static RENDER_MODE = Component.NO_SHADOW;
+
+ static PROPERTIES = {
+ title: {
+ value: 'Title'
+ },
+ info: {},
+ button_text: {},
+ button_style: {},
+ on_click: {},
+ style: {},
+ }
+
+ create_template ({ template }) {
+ $(template).html(/*html*/`
+
+
+ ${ this.get('title') }
+ ${
+ this.get('info')
+ }
+
+
+
+
+
+ `);
+ }
+
+ on_ready ({ listen }) {
+ $(this.dom_).find('button').on('click', this.get('on_click') || (() => {}));
+ }
+});
diff --git a/src/UI/Components/Frame.js b/src/UI/Components/Frame.js
new file mode 100644
index 000000000..446f4f166
--- /dev/null
+++ b/src/UI/Components/Frame.js
@@ -0,0 +1,20 @@
+const Component = use('util.Component');
+
+export default def(class Frame extends Component {
+ static ID = 'ui.component.Frame';
+ static RENDER_MODE = Component.NO_SHADOW;
+
+ static PROPERTIES = {
+ component: {},
+ }
+
+ on_ready ({ listen }) {
+ listen('component', component => {
+ this.dom_.innerHTML = '';
+ if ( ! component ) {
+ return;
+ }
+ component.attach(this.dom_);
+ });
+ }
+});
diff --git a/src/UI/Components/NotifCard.js b/src/UI/Components/NotifCard.js
new file mode 100644
index 000000000..737904e21
--- /dev/null
+++ b/src/UI/Components/NotifCard.js
@@ -0,0 +1,25 @@
+const Component = use('util.Component');
+
+export default def(class NotifCard extends Component {
+ static ID = 'ui.component.NotifCard';
+ static RENDER_MODE = Component.NO_SHADOW;
+
+ static PROPERTIES = {
+ text: { value: 'no text' },
+ style: {},
+ }
+
+ create_template ({ template }) {
+ $(template).html(/*html*/`
+
+
+ ${ this.get('text') }
+
+
+ `);
+ }
+
+ on_ready ({ listen }) {
+ $(this.dom_).find('button').on('click', this.get('on_click') || (() => {}));
+ }
+});
diff --git a/src/css/style.css b/src/css/style.css
index 2c2726635..7306345bb 100644
--- a/src/css/style.css
+++ b/src/css/style.css
@@ -3708,6 +3708,10 @@ fieldset[name=number-code] {
height: 45px;
}
+.thin-card {
+ padding: 0 15px;
+}
+
.settings-card strong {
font-weight: 500;
}
diff --git a/src/init_async.js b/src/init_async.js
index b738b9aa9..40aca629c 100644
--- a/src/init_async.js
+++ b/src/init_async.js
@@ -3,7 +3,10 @@ logger.info('start -> async initialization');
import './util/TeePromise.js';
import './util/Component.js';
+import './UI/Components/Frame.js';
import './UI/Components/Glyph.js';
+import './UI/Components/ActionCard.js';
+import './UI/Components/NotifCard.js';
logger.info('end -> async initialization');
globalThis.init_promise.resolve();