diff --git a/addon/components/o-s-s/layout/sidebar/group.hbs b/addon/components/o-s-s/layout/sidebar/group.hbs
index f59b938fb..f72c50d12 100644
--- a/addon/components/o-s-s/layout/sidebar/group.hbs
+++ b/addon/components/o-s-s/layout/sidebar/group.hbs
@@ -60,6 +60,7 @@
@hasNotifications={{item.hasNotifications}}
@link={{item.link}}
@routePrefix={{item.routePrefix}}
+ @tag={{item.tag}}
@lockedAction={{item.lockedAction}}
@action={{item.action}}
@disableAutoActive={{item.disableAutoActive}}
diff --git a/addon/components/o-s-s/layout/sidebar/group.stories.js b/addon/components/o-s-s/layout/sidebar/group.stories.js
index 69008cd91..c17eecbad 100644
--- a/addon/components/o-s-s/layout/sidebar/group.stories.js
+++ b/addon/components/o-s-s/layout/sidebar/group.stories.js
@@ -92,7 +92,8 @@ const defaultArgs = {
hasNotifications: true,
locked: false,
link: 'http://upfluence.com',
- lockedAction: action('lockedAction')
+ lockedAction: action('lockedAction'),
+ tag: { label: 'New', skin: 'chat-gpt', plain: true }
}
]
};
diff --git a/addon/components/o-s-s/layout/sidebar/group.ts b/addon/components/o-s-s/layout/sidebar/group.ts
index dc9b2001e..c37a7538e 100644
--- a/addon/components/o-s-s/layout/sidebar/group.ts
+++ b/addon/components/o-s-s/layout/sidebar/group.ts
@@ -3,6 +3,8 @@ import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { scheduleOnce } from '@ember/runloop';
+import type { SidebarItemTag } from '@upfluence/oss-components/components/o-s-s/layout/sidebar/item';
+
export type GroupItem = {
icon?: string;
locked?: boolean;
@@ -13,6 +15,7 @@ export type GroupItem = {
active: boolean;
dataControlName?: string;
disableAutoActive?: boolean;
+ tag?: SidebarItemTag;
lockedAction?(): unknown;
action?(): void;
};
diff --git a/addon/components/o-s-s/layout/sidebar/item.hbs b/addon/components/o-s-s/layout/sidebar/item.hbs
index c4ee48e28..c56390b53 100644
--- a/addon/components/o-s-s/layout/sidebar/item.hbs
+++ b/addon/components/o-s-s/layout/sidebar/item.hbs
@@ -28,6 +28,17 @@
{{@label}}
+ {{#if @tag}}
+
+ {{/if}}
+
{{#if this.hasNotifications}}
{{/if}}
diff --git a/addon/components/o-s-s/layout/sidebar/item.stories.js b/addon/components/o-s-s/layout/sidebar/item.stories.js
index a47c6bae7..8c4c56ad2 100644
--- a/addon/components/o-s-s/layout/sidebar/item.stories.js
+++ b/addon/components/o-s-s/layout/sidebar/item.stories.js
@@ -75,6 +75,16 @@ export default {
type: 'boolean'
}
},
+ tag: {
+ description: 'A tag to display next to the label, passed down to OSS::Tag (label, skin, icon, plain)',
+ table: {
+ type: {
+ summary: '{ label?: string; skin?: string; icon?: string; plain?: boolean }'
+ },
+ defaultValue: { summary: 'undefined' }
+ },
+ control: { type: 'object' }
+ },
lockedAction: {
description: 'Function to be called on click when item is locked',
table: {
@@ -125,8 +135,8 @@ const Template = (args) => ({
+ @expanded={{this.expanded}} @tag={{this.tag}}
+ @lockedAction={{this.lockedAction}}
@action={{this.action}} />
`,
@@ -152,3 +162,10 @@ BasicUsage.args = defaultArgs;
export const WithNamedBlockIcon = IconNamedBlockTemplate.bind({});
WithNamedBlockIcon.args = defaultArgs;
+
+export const WithTag = Template.bind({});
+WithTag.args = {
+ ...defaultArgs,
+ expanded: true,
+ tag: { label: 'New', skin: 'chat-gpt', plain: true }
+};
diff --git a/addon/components/o-s-s/layout/sidebar/item.ts b/addon/components/o-s-s/layout/sidebar/item.ts
index f61149a3e..0c8545ffe 100644
--- a/addon/components/o-s-s/layout/sidebar/item.ts
+++ b/addon/components/o-s-s/layout/sidebar/item.ts
@@ -3,13 +3,15 @@ import { action } from '@ember/object';
import type { OSSTagArgs } from '@upfluence/oss-components/components/o-s-s/tag';
+export type SidebarItemTag = Pick;
+
interface OSSLayoutSidebarItemArgs {
link: string;
routePrefix?: string;
icon?: string;
locked?: boolean;
hasNotifications?: boolean;
- tag?: Pick;
+ tag?: SidebarItemTag;
expanded?: boolean;
label?: string;
disableAutoActive?: boolean;
diff --git a/app/styles/organisms/sidebar.less b/app/styles/organisms/sidebar.less
index 4cafb5e42..18d5fc518 100644
--- a/app/styles/organisms/sidebar.less
+++ b/app/styles/organisms/sidebar.less
@@ -128,6 +128,14 @@ a.oss-sidebar-item {
}
}
+ &__tag {
+ position: absolute;
+ top: -6px;
+ right: 0;
+ opacity: 0;
+ transition: opacity 300ms ease-in-out;
+ }
+
&__notification {
width: 3px;
height: 3px;
@@ -170,6 +178,10 @@ a.oss-sidebar-item {
width: fit-content;
opacity: 1;
}
+
+ .oss-sidebar-item__tag {
+ opacity: 1;
+ }
}
&:focus:not(&.active):not(:hover),
diff --git a/tests/integration/components/o-s-s/layout/sidebar/group-test.ts b/tests/integration/components/o-s-s/layout/sidebar/group-test.ts
index 2acf2d216..189614622 100644
--- a/tests/integration/components/o-s-s/layout/sidebar/group-test.ts
+++ b/tests/integration/components/o-s-s/layout/sidebar/group-test.ts
@@ -219,4 +219,34 @@ module('Integration | Component | o-s-s/layout/sidebar/group', function (hooks)
assert.dom('.oss-sidebar-group > div .oss-sidebar-item .oss-sidebar-item__icon i').hasClass('fa-ship');
});
});
+
+ module('an item has a tag', function (hooks) {
+ hooks.beforeEach(function () {
+ this.expanded = true;
+ this.items = [
+ {
+ icon: 'far fa-search',
+ link: '/search',
+ active: false,
+ hasNotifications: false,
+ label: 'Search',
+ tag: { label: 'New', skin: 'chat-gpt', plain: true }
+ }
+ ];
+ });
+
+ test('the tag is propagated to the underlying item', async function (assert) {
+ await renderComponent();
+
+ assert
+ .dom('.oss-sidebar-group .oss-sidebar-group__items-container .oss-sidebar-item__tag')
+ .hasText('New');
+ assert
+ .dom('.oss-sidebar-group .oss-sidebar-group__items-container .oss-sidebar-item__tag')
+ .hasClass('upf-tag--chat-gpt');
+ assert
+ .dom('.oss-sidebar-group .oss-sidebar-group__items-container .oss-sidebar-item__tag')
+ .hasClass('upf-tag--plain');
+ });
+ });
});
diff --git a/tests/integration/components/o-s-s/layout/sidebar/item-test.ts b/tests/integration/components/o-s-s/layout/sidebar/item-test.ts
index 0343470c2..358d6150e 100644
--- a/tests/integration/components/o-s-s/layout/sidebar/item-test.ts
+++ b/tests/integration/components/o-s-s/layout/sidebar/item-test.ts
@@ -67,6 +67,26 @@ module('Integration | Component | oss/layout/sidebar/item', function (hooks) {
assert.dom('.oss-sidebar-item__label').hasText('Label');
});
});
+
+ module('Tag', () => {
+ test('Default value for tag is undefined', async function (assert) {
+ await render(hbs``);
+ assert.dom('.oss-sidebar-item__tag').doesNotExist();
+ });
+
+ test('When tag is passed, it is rendered as a direct child of the item with all its args', async function (assert) {
+ this.tag = { label: 'New', skin: 'chat-gpt', icon: 'fa-star', plain: true };
+ await render(hbs``);
+
+ assert.dom('.oss-sidebar-item > .oss-sidebar-item__tag').exists();
+ assert.dom('.oss-sidebar-item__tag').hasClass('upf-tag');
+ assert.dom('.oss-sidebar-item__tag').hasClass('upf-tag--chat-gpt');
+ assert.dom('.oss-sidebar-item__tag').hasClass('upf-tag--plain');
+ assert.dom('.oss-sidebar-item__tag').hasClass('upf-tag--xs');
+ assert.dom('.oss-sidebar-item__tag i').hasClass('fa-star');
+ assert.dom('.oss-sidebar-item__tag').hasText('New');
+ });
+ });
});
module('Actions', function (hooks) {