Browse Source

Task/extend toggle component to support icons (#7582)

* Extend toggle component to support icons

* Update changelog
pull/7529/head
Thomas Kaul 1 week ago
committed by GitHub
parent
commit
e61946cbb7
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      CHANGELOG.md
  2. 7
      apps/client/src/app/components/home-holdings/home-holdings.component.ts
  3. 3
      apps/client/src/app/components/markets/markets.component.ts
  4. 7
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  5. 2
      libs/common/src/lib/interfaces/index.ts
  6. 4
      libs/common/src/lib/interfaces/toggle-option.interface.ts
  7. 2
      libs/common/src/lib/types/index.ts
  8. 9
      libs/common/src/lib/types/toggle-option.type.ts
  9. 8
      libs/ui/src/lib/toggle/toggle.component.html
  10. 26
      libs/ui/src/lib/toggle/toggle.component.stories.ts
  11. 5
      libs/ui/src/lib/toggle/toggle.component.ts

6
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/), 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). 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 ## 3.46.0 - 2026-08-09
### Added ### Added

7
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 { import {
AssetProfileIdentifier, AssetProfileIdentifier,
PortfolioPosition, PortfolioPosition,
ToggleOption,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; import { hasPermission, permissions } from '@ghostfolio/common/permissions';
import { internalRoutes } from '@ghostfolio/common/routes/routes'; 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 { GfHoldingsTableComponent } from '@ghostfolio/ui/holdings-table';
import { DataService } from '@ghostfolio/ui/services'; import { DataService } from '@ghostfolio/ui/services';
import { GfToggleComponent } from '@ghostfolio/ui/toggle'; import { GfToggleComponent } from '@ghostfolio/ui/toggle';

3
apps/client/src/app/components/markets/markets.component.ts

@ -5,11 +5,10 @@ import {
HistoricalDataItem, HistoricalDataItem,
InfoItem, InfoItem,
MarketDataOfMarketsResponse, MarketDataOfMarketsResponse,
ToggleOption,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { hasPermission, permissions } from '@ghostfolio/common/permissions'; 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 { GfBenchmarkComponent } from '@ghostfolio/ui/benchmark';
import { GfFearAndGreedIndexComponent } from '@ghostfolio/ui/fear-and-greed-index'; import { GfFearAndGreedIndexComponent } from '@ghostfolio/ui/fear-and-greed-index';
import { GfLineChartComponent } from '@ghostfolio/ui/line-chart'; import { GfLineChartComponent } from '@ghostfolio/ui/line-chart';

7
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -13,7 +13,6 @@ import {
PortfolioInvestmentsResponse, PortfolioInvestmentsResponse,
PortfolioPerformance, PortfolioPerformance,
PortfolioPosition, PortfolioPosition,
ToggleOption,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { import {
@ -21,7 +20,11 @@ import {
hasReadRestrictedAccessPermission, hasReadRestrictedAccessPermission,
permissions permissions
} from '@ghostfolio/common/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 { translate } from '@ghostfolio/ui/i18n';
import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator'; import { GfPremiumIndicatorComponent } from '@ghostfolio/ui/premium-indicator';
import { DataService } from '@ghostfolio/ui/services'; import { DataService } from '@ghostfolio/ui/services';

2
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 { SymbolItem } from './symbol-item.interface';
import type { SymbolMetrics } from './symbol-metrics.interface'; import type { SymbolMetrics } from './symbol-metrics.interface';
import type { SystemMessage } from './system-message.interface'; import type { SystemMessage } from './system-message.interface';
import type { ToggleOption } from './toggle-option.interface';
import type { UserItem } from './user-item.interface'; import type { UserItem } from './user-item.interface';
import type { UserSettings } from './user-settings.interface'; import type { UserSettings } from './user-settings.interface';
import type { User } from './user.interface'; import type { User } from './user.interface';
@ -191,7 +190,6 @@ export {
SymbolItem, SymbolItem,
SymbolMetrics, SymbolMetrics,
SystemMessage, SystemMessage,
ToggleOption,
User, User,
UserItem, UserItem,
UserSettings, UserSettings,

4
libs/common/src/lib/interfaces/toggle-option.interface.ts

@ -1,4 +0,0 @@
export interface ToggleOption {
label: string;
value: string;
}

2
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 { RequestWithUser } from './request-with-user.type';
import type { SectorName } from './sector-name.type'; import type { SectorName } from './sector-name.type';
import type { SubscriptionOfferKey } from './subscription-offer-key.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 { UserWithSettings } from './user-with-settings.type';
import type { ViewMode } from './view-mode.type'; import type { ViewMode } from './view-mode.type';
@ -52,6 +53,7 @@ export type {
RequestWithUser, RequestWithUser,
SectorName, SectorName,
SubscriptionOfferKey, SubscriptionOfferKey,
ToggleOption,
UserWithSettings, UserWithSettings,
ViewMode ViewMode
}; };

9
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 }
);

8
libs/ui/src/lib/toggle/toggle.component.html

@ -12,8 +12,14 @@
!isLoading() && option.value !== optionFormControl.value !isLoading() && option.value !== optionFormControl.value
}" }"
[disabled]="isLoading()" [disabled]="isLoading()"
[title]="option.title ?? ''"
[value]="option.value" [value]="option.value"
>{{ option.label }}</mat-radio-button
> >
@if (option.iconName) {
<ion-icon class="d-block" [name]="option.iconName" />
} @else {
<span>{{ option.label }}</span>
}
</mat-radio-button>
} }
</mat-radio-group> </mat-radio-group>

26
libs/ui/src/lib/toggle/toggle.component.stories.ts

@ -1,17 +1,22 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms'; import { ReactiveFormsModule } from '@angular/forms';
import { MatRadioModule } from '@angular/material/radio'; import { MatRadioModule } from '@angular/material/radio';
import { IonIcon } from '@ionic/angular/standalone';
import { moduleMetadata } from '@storybook/angular'; import { moduleMetadata } from '@storybook/angular';
import type { Meta, StoryObj } 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'; import { GfToggleComponent } from './toggle.component';
addIcons({ gridOutline, reorderFourOutline });
export default { export default {
title: 'Toggle', title: 'Toggle',
component: GfToggleComponent, component: GfToggleComponent,
decorators: [ decorators: [
moduleMetadata({ moduleMetadata({
imports: [CommonModule, MatRadioModule, ReactiveFormsModule] imports: [CommonModule, IonIcon, MatRadioModule, ReactiveFormsModule]
}) })
] ]
} as Meta<GfToggleComponent>; } as Meta<GfToggleComponent>;
@ -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'
}
]
}
};

5
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 { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
@ -9,10 +9,11 @@ import {
} from '@angular/core'; } from '@angular/core';
import { FormControl, ReactiveFormsModule } from '@angular/forms'; import { FormControl, ReactiveFormsModule } from '@angular/forms';
import { MatRadioModule } from '@angular/material/radio'; import { MatRadioModule } from '@angular/material/radio';
import { IonIcon } from '@ionic/angular/standalone';
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
imports: [MatRadioModule, ReactiveFormsModule], imports: [IonIcon, MatRadioModule, ReactiveFormsModule],
selector: 'gf-toggle', selector: 'gf-toggle',
styleUrls: ['./toggle.component.scss'], styleUrls: ['./toggle.component.scss'],
templateUrl: './toggle.component.html' templateUrl: './toggle.component.html'

Loading…
Cancel
Save