diff --git a/addons/rose/addon/components/rose/nav/tab.js b/addons/rose/addon/components/rose/nav/tab.js
new file mode 100644
index 000000000..c4c84358c
--- /dev/null
+++ b/addons/rose/addon/components/rose/nav/tab.js
@@ -0,0 +1,7 @@
+import Component from '@ember/component';
+import layout from '../../../templates/components/rose/nav/tab';
+
+export default Component.extend({
+ layout,
+ tagName: '',
+});
diff --git a/addons/rose/addon/components/rose/nav/tab.stories.mdx b/addons/rose/addon/components/rose/nav/tab.stories.mdx
new file mode 100644
index 000000000..6a9b6889e
--- /dev/null
+++ b/addons/rose/addon/components/rose/nav/tab.stories.mdx
@@ -0,0 +1,43 @@
+import { Meta, Story, Preview } from '@storybook/addon-docs/blocks';
+import { hbs } from 'ember-cli-htmlbars';
+import { action } from '@storybook/addon-actions';
+import { text, boolean, select } from '@storybook/addon-knobs';
+
+
+
+# Tab
+
+A tab item component with ability to configure icon, title, and badge sections.
+
+```html
+
+```
+
+
+ {{
+ template: hbs`
+ `,
+ context: {
+ title: text('title', 'Tab item'),
+ badge: text('badge', '3'),
+ icon: select(
+ 'icon',
+ {
+ 'info-circle-outline': 'info-circle-outline',
+ 'user-square-fill': 'user-square-fill',
+ 'check-circle-outline': 'check-circle-outline',
+ 'copy-action': 'copy-action',
+ 'unfold-more': 'unfold-more',
+ 'unfold-less': 'unfold-less',
+ },
+ 'info-circle-outline'
+ ),
+ disabled: boolean('disabled', false)
+ },
+ }}
+
diff --git a/addons/rose/addon/styles/rose/components/nav/_index.scss b/addons/rose/addon/styles/rose/components/nav/_index.scss
index 0abffa8bd..b56832ff9 100644
--- a/addons/rose/addon/styles/rose/components/nav/_index.scss
+++ b/addons/rose/addon/styles/rose/components/nav/_index.scss
@@ -1 +1,2 @@
@import "sidebar";
+@import 'tab';
diff --git a/addons/rose/addon/styles/rose/components/nav/_tab.scss b/addons/rose/addon/styles/rose/components/nav/_tab.scss
new file mode 100644
index 000000000..8bbad4116
--- /dev/null
+++ b/addons/rose/addon/styles/rose/components/nav/_tab.scss
@@ -0,0 +1,53 @@
+@use '../../variables/sizing';
+@use '../../utilities/type';
+
+.rose-nav-tab {
+ @include type.type(s);
+ display: inline-block;
+ background-color: var(--subtle);
+
+ .rose-nav-tab-link {
+ text-decoration: none;
+ color: var(--ui-gray);
+ display: inline-block;
+ padding: sizing.rems(s) sizing.rems(m);
+ border-bottom: sizing.rems(xxxs) solid var(--subtle);
+
+ &.rose-nav-tab-link-disabled {
+ cursor: not-allowed;
+ pointer-events: none;
+ color: var(--ui-gray-subtler-2);
+ }
+
+ &:active, &.active {
+ color: var(--action);
+ border-color: var(--action);
+ background-color: var(--subtle);
+ }
+
+ &:hover {
+ color: var(--ui-gray);
+ border-color: var(--ui-gray-subtler-2);
+ background-color: var(--ui-gray-subtler-4);
+ }
+
+ &:hover:active {
+ color: var(--action);
+ border-color: var(--action);
+ background-color: var(--ui-gray-subtler-4);
+ }
+ }
+
+ .rose-nav-tab-icon {
+ svg {
+ width: sizing.rems(m);
+ height: sizing.rems(m);
+ vertical-align: sub;
+ }
+ }
+
+ .rose-nav-tab-badge {
+ @include type.type(xs);
+ margin-left: sizing.rems(xxs);
+ }
+}
diff --git a/addons/rose/addon/templates/components/rose/nav/tab.hbs b/addons/rose/addon/templates/components/rose/nav/tab.hbs
new file mode 100644
index 000000000..3d1c5e4cd
--- /dev/null
+++ b/addons/rose/addon/templates/components/rose/nav/tab.hbs
@@ -0,0 +1,22 @@
+
+
+ {{#if @icon}}
+ {{inline-svg @icon}}
+ {{/if}}
+
+ {{#if @title}}
+ {{@title}}
+ {{/if}}
+
+ {{#if @badge}}
+ {{@badge}}
+ {{/if}}
+
+
+ {{yield}}
+
diff --git a/addons/rose/app/components/rose/nav/tab.js b/addons/rose/app/components/rose/nav/tab.js
new file mode 100644
index 000000000..92c7185e3
--- /dev/null
+++ b/addons/rose/app/components/rose/nav/tab.js
@@ -0,0 +1 @@
+export { default } from 'rose/components/rose/nav/tab';
diff --git a/addons/rose/tests/dummy/app/templates/index.hbs b/addons/rose/tests/dummy/app/templates/index.hbs
index ec3965039..08352c8df 100644
--- a/addons/rose/tests/dummy/app/templates/index.hbs
+++ b/addons/rose/tests/dummy/app/templates/index.hbs
@@ -198,5 +198,7 @@
+
+
diff --git a/addons/rose/tests/integration/components/rose/nav/tab-test.js b/addons/rose/tests/integration/components/rose/nav/tab-test.js
new file mode 100644
index 000000000..963b31b17
--- /dev/null
+++ b/addons/rose/tests/integration/components/rose/nav/tab-test.js
@@ -0,0 +1,50 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render, find } from '@ember/test-helpers';
+import hbs from 'htmlbars-inline-precompile';
+
+module('Integration | Component | rose/nav/tab', function (hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function (assert) {
+ await render(hbs``);
+ assert.ok(find('a'));
+ assert.ok(find('.rose-nav-tab'));
+ assert.ok(find('.rose-nav-tab-link'));
+ assert.notOk(find('.rose-nav-tab-icon'));
+ assert.notOk(find('.rose-nav-tab-badge'));
+ assert.notOk(find('.rose-nav-tab-link-disabled'));
+ });
+
+ test('it renders with title', async function (assert) {
+ await render(hbs``);
+ assert.equal(find('a').title, 'Tab title');
+ assert.equal(find('.rose-nav-tab-link').textContent.trim(), 'Tab title');
+ });
+
+ test('it renders with icon', async function (assert) {
+ await render(hbs``);
+ assert.ok(find('svg'));
+ assert.ok(find('.rose-nav-tab-icon'));
+ });
+
+ test('it renders with badge', async function (assert) {
+ await render(hbs``);
+ assert.ok(find('.rose-nav-tab-badge'));
+ assert.equal(find('.rose-nav-tab-badge').textContent.trim(), '3');
+ });
+
+ test('it render with attributes', async function (assert) {
+ await render(hbs``);
+ assert.ok(find('#tab'));
+ });
+
+ test('it renders disabled', async function (assert) {
+ this.set('disabled', true);
+ await render(hbs``);
+ assert.ok(find('.rose-nav-tab-link-disabled'));
+
+ this.set('disabled', false);
+ assert.notOk(find('.rose-nav-tab-link-disabled'));
+ });
+});
diff --git a/ui/core/app/styles/app.scss b/ui/core/app/styles/app.scss
index 667cc9039..56c8e3df1 100644
--- a/ui/core/app/styles/app.scss
+++ b/ui/core/app/styles/app.scss
@@ -64,4 +64,12 @@
width: 100%;
}
}
+
+ .tabs {
+ border-bottom: 2px solid #bac1cc;
+ display: flex;
+ flex-wrap: wrap;
+ flex-direction: row;
+ margin-bottom: 10px;
+ }
}
diff --git a/ui/core/app/templates/orgs/org/projects/project.hbs b/ui/core/app/templates/orgs/org/projects/project.hbs
index 4c360b74c..3b20217e0 100644
--- a/ui/core/app/templates/orgs/org/projects/project.hbs
+++ b/ui/core/app/templates/orgs/org/projects/project.hbs
@@ -7,7 +7,11 @@
{{@model.name}}
- {{@model.name}}
+ {{t "resources.project.settings"}}
+
+
+
+