From e61946cbb7a4f4f7c3a0054eaa4dfb4378943aed Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Mon, 10 Aug 2026 07:39:33 +0200 Subject: [PATCH] Task/extend toggle component to support icons (#7582) * Extend toggle component to support icons * Update changelog --- CHANGELOG.md | 6 +++++ .../home-holdings/home-holdings.component.ts | 7 +++-- .../components/markets/markets.component.ts | 3 +-- .../analysis/analysis-page.component.ts | 7 +++-- libs/common/src/lib/interfaces/index.ts | 2 -- .../lib/interfaces/toggle-option.interface.ts | 4 --- libs/common/src/lib/types/index.ts | 2 ++ .../src/lib/types/toggle-option.type.ts | 9 +++++++ libs/ui/src/lib/toggle/toggle.component.html | 8 +++++- .../lib/toggle/toggle.component.stories.ts | 26 ++++++++++++++++++- libs/ui/src/lib/toggle/toggle.component.ts | 5 ++-- 11 files changed, 63 insertions(+), 16 deletions(-) delete mode 100644 libs/common/src/lib/interfaces/toggle-option.interface.ts create mode 100644 libs/common/src/lib/types/toggle-option.type.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a67ced1b8..5b9af6f4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Extended the toggle component to support icons + ## 3.46.0 - 2026-08-09 ### Added diff --git a/apps/client/src/app/components/home-holdings/home-holdings.component.ts b/apps/client/src/app/components/home-holdings/home-holdings.component.ts index bae154607..2a06f47ab 100644 --- a/apps/client/src/app/components/home-holdings/home-holdings.component.ts +++ b/apps/client/src/app/components/home-holdings/home-holdings.component.ts @@ -3,12 +3,15 @@ import { UserService } from '@ghostfolio/client/services/user/user.service'; import { AssetProfileIdentifier, PortfolioPosition, - ToggleOption, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { internalRoutes } from '@ghostfolio/common/routes/routes'; -import { HoldingType, HoldingsViewMode } from '@ghostfolio/common/types'; +import { + HoldingType, + HoldingsViewMode, + ToggleOption +} from '@ghostfolio/common/types'; import { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table'; import { DataService } from '@ghostfolio/ui/services'; import { GfToggleComponent } from '@ghostfolio/ui/toggle'; diff --git a/apps/client/src/app/components/markets/markets.component.ts b/apps/client/src/app/components/markets/markets.component.ts index 27f60d86a..7c69fede0 100644 --- a/apps/client/src/app/components/markets/markets.component.ts +++ b/apps/client/src/app/components/markets/markets.component.ts @@ -5,11 +5,10 @@ import { HistoricalDataItem, InfoItem, MarketDataOfMarketsResponse, - ToggleOption, User } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { FearAndGreedIndexMode } from '@ghostfolio/common/types'; +import { FearAndGreedIndexMode, ToggleOption } from '@ghostfolio/common/types'; import { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark'; import { GfFearAndGreedIndexComponent } from '@ghostfolio/ui/fear-and-greed-index'; import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts index d3e3d8a31..2c34dbcd7 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts @@ -13,7 +13,6 @@ import { PortfolioInvestmentsResponse, PortfolioPerformance, PortfolioPosition, - ToggleOption, User } from '@ghostfolio/common/interfaces'; import { @@ -21,7 +20,11 @@ import { hasReadRestrictedAccessPermission, permissions } from '@ghostfolio/common/permissions'; -import type { AiPromptMode, GroupBy } from '@ghostfolio/common/types'; +import type { + AiPromptMode, + GroupBy, + ToggleOption +} from '@ghostfolio/common/types'; import { translate } from '@ghostfolio/ui/i18n'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { DataService } from '@ghostfolio/ui/services'; diff --git a/libs/common/src/lib/interfaces/index.ts b/libs/common/src/lib/interfaces/index.ts index 008422f2d..62a038df0 100644 --- a/libs/common/src/lib/interfaces/index.ts +++ b/libs/common/src/lib/interfaces/index.ts @@ -94,7 +94,6 @@ import type { SubscriptionOffer } from './subscription-offer.interface'; import type { SymbolItem } from './symbol-item.interface'; import type { SymbolMetrics } from './symbol-metrics.interface'; import type { SystemMessage } from './system-message.interface'; -import type { ToggleOption } from './toggle-option.interface'; import type { UserItem } from './user-item.interface'; import type { UserSettings } from './user-settings.interface'; import type { User } from './user.interface'; @@ -191,7 +190,6 @@ export { SymbolItem, SymbolMetrics, SystemMessage, - ToggleOption, User, UserItem, UserSettings, diff --git a/libs/common/src/lib/interfaces/toggle-option.interface.ts b/libs/common/src/lib/interfaces/toggle-option.interface.ts deleted file mode 100644 index ca7b16bb2..000000000 --- a/libs/common/src/lib/interfaces/toggle-option.interface.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface ToggleOption { - label: string; - value: string; -} diff --git a/libs/common/src/lib/types/index.ts b/libs/common/src/lib/types/index.ts index f61bfdca7..22d772610 100644 --- a/libs/common/src/lib/types/index.ts +++ b/libs/common/src/lib/types/index.ts @@ -23,6 +23,7 @@ import type { PropertyKey } from './property-key.type'; import type { RequestWithUser } from './request-with-user.type'; import type { SectorName } from './sector-name.type'; import type { SubscriptionOfferKey } from './subscription-offer-key.type'; +import type { ToggleOption } from './toggle-option.type'; import type { UserWithSettings } from './user-with-settings.type'; import type { ViewMode } from './view-mode.type'; @@ -52,6 +53,7 @@ export type { RequestWithUser, SectorName, SubscriptionOfferKey, + ToggleOption, UserWithSettings, ViewMode }; diff --git a/libs/common/src/lib/types/toggle-option.type.ts b/libs/common/src/lib/types/toggle-option.type.ts new file mode 100644 index 000000000..1e0012432 --- /dev/null +++ b/libs/common/src/lib/types/toggle-option.type.ts @@ -0,0 +1,9 @@ +interface BaseToggleOption { + value: string; +} + +export type ToggleOption = BaseToggleOption & + ( + | { iconName: string; label?: never; title: string } + | { iconName?: never; label: string; title?: never } + ); diff --git a/libs/ui/src/lib/toggle/toggle.component.html b/libs/ui/src/lib/toggle/toggle.component.html index 3fe7d00ba..8ad5d75b3 100644 --- a/libs/ui/src/lib/toggle/toggle.component.html +++ b/libs/ui/src/lib/toggle/toggle.component.html @@ -12,8 +12,14 @@ !isLoading() && option.value !== optionFormControl.value }" [disabled]="isLoading()" + [title]="option.title ?? ''" [value]="option.value" - >{{ option.label }} + @if (option.iconName) { + + } @else { + {{ option.label }} + } + } diff --git a/libs/ui/src/lib/toggle/toggle.component.stories.ts b/libs/ui/src/lib/toggle/toggle.component.stories.ts index 36468ea3c..30af31c42 100644 --- a/libs/ui/src/lib/toggle/toggle.component.stories.ts +++ b/libs/ui/src/lib/toggle/toggle.component.stories.ts @@ -1,17 +1,22 @@ import { CommonModule } from '@angular/common'; import { ReactiveFormsModule } from '@angular/forms'; import { MatRadioModule } from '@angular/material/radio'; +import { IonIcon } from '@ionic/angular/standalone'; import { moduleMetadata } from '@storybook/angular'; import type { Meta, StoryObj } from '@storybook/angular'; +import { addIcons } from 'ionicons'; +import { gridOutline, reorderFourOutline } from 'ionicons/icons'; import { GfToggleComponent } from './toggle.component'; +addIcons({ gridOutline, reorderFourOutline }); + export default { title: 'Toggle', component: GfToggleComponent, decorators: [ moduleMetadata({ - imports: [CommonModule, MatRadioModule, ReactiveFormsModule] + imports: [CommonModule, IonIcon, MatRadioModule, ReactiveFormsModule] }) ] } as Meta; @@ -31,3 +36,22 @@ export const Default: Story = { ] } }; + +export const WithIcons: Story = { + args: { + defaultValue: 'TABLE', + isLoading: false, + options: [ + { + iconName: 'reorder-four-outline', + title: 'Table', + value: 'TABLE' + }, + { + iconName: 'grid-outline', + title: 'Chart', + value: 'CHART' + } + ] + } +}; diff --git a/libs/ui/src/lib/toggle/toggle.component.ts b/libs/ui/src/lib/toggle/toggle.component.ts index 9324b3be7..fe8db17a3 100644 --- a/libs/ui/src/lib/toggle/toggle.component.ts +++ b/libs/ui/src/lib/toggle/toggle.component.ts @@ -1,4 +1,4 @@ -import { ToggleOption } from '@ghostfolio/common/interfaces'; +import { ToggleOption } from '@ghostfolio/common/types'; import { ChangeDetectionStrategy, @@ -9,10 +9,11 @@ import { } from '@angular/core'; import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { MatRadioModule } from '@angular/material/radio'; +import { IonIcon } from '@ionic/angular/standalone'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - imports: [MatRadioModule, ReactiveFormsModule], + imports: [IonIcon, MatRadioModule, ReactiveFormsModule], selector: 'gf-toggle', styleUrls: ['./toggle.component.scss'], templateUrl: './toggle.component.html'