Introduction
I am trying to build out Angular UI components using Storybook and am running into an issue where Storybook won't render any icons in the components. I am using Angular Icons, and they render properly when the component is called in the app-component.html
, but not when they are rendered within Storybook (from the card.component.stories.ts
).
Attempted solutions
I've looked into this post with a similar issue in React, but had no luck with the suggested comments within it.
When I inspect the console for a possible error, I get an error telling me 'ng-icon' is not a known element
. I referred to this question to try and solve this as I thought it might not be a Storybook-specific error but something else. However, the suggested answer did not fix my issue within Storybook.
I went back to the Angular Icons docs, and was able to get the icons to render in Storybook by making my component a standalone component (see here for more information on this and what Angular Icons suggests). However, this then caused all my global theming to be voided because I made the component a standalone component.
Where to go now?
So, back to square one with my issue. Not really sure where to go, but here a couple of thoughts that I had:
- The icons are actually compiled and rendered as SVGs. Maybe I need to toy with that idea within Storybook (this article was something I found quickly that looked like it might help)
- My inexperience with Angular is showing, and this is some easy fix that I don't know about ("Oh, you didn't import
foo
intobar
, which you have to do every time you are using modules within Angular" type issue) - This is a known bug (couldn't find anything saying this or anyone with a similar issue to this)
Code
Here is what my component looks like (this code is just for a proof of concept):
card.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-card',
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss']
})
export class CardComponent {
@Input() title: string = 'CardComponent';
@Input() date: string = '1.1.23';
@Input() status: string = 'New';
@Input() claimer: string = 'John';
@Input() selected: boolean = false;
public get classes(): string {
return this.selected ? 'selected' : 'deselected';
}
}
card.component.html
<div class="card" [ngClass]="classes">
<div class="card-header" [ngClass]="classes">
<h3>{{title}}</h3>
</div>
<div class="card-details" [ngClass]="classes">
<div class="column">
<ng-icon name="bootstrapCalendar3"></ng-icon>
<div class="column-value">{{date}}</div>
</div>
<!-- More of the same column element as above repeated here.
I removed it to narrow the focus on the question. -->
...
</div>
</div>
card.component.stories.ts
import { Story, Meta } from '@storybook/angular/types-6-0';
import { CardComponent } from "./card.component";
export default {
title: "CardComponent",
component: CardComponent,
argTypes: {
selected: { control: "boolean" },
title: { control: "text" },
date: { control: "text" },
status: { control: "text" },
claimer: { control: "text" },
},
} as Meta;
const Template: Story<CardComponent> = (args: CardComponent) => ({
props: args,
});
export const Selected = Template.bind({});
Selected.args = {
selected: true
};
card.component.scss
Not really sure the SCSS file is super important, as it's just my specific styling for the component and not the ng-icon
, so I've left it out.
app.module.ts
// There are more imports up here, but they are the
// boilerplate Angular imports, so I've left them out to try and make this shorter
...
import { NgIconsModule } from "@ng-icons/core";
import { bootstrapCalendar3, bootstrapActivity, bootstrapStar } from "@ng-icons/bootstrap-icons";
import { CardComponent } from './components/card/card.component';
@NgModule({
declarations: [
AppComponent,
CardComponent
],
imports: [
...,
NgIconsModule.withIcons({ bootstrapCalendar3, bootstrapActivity, bootstrapStar })
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Would love any and all help. I tried to make this clear, but again my inexperience with Angular might be showing through a lot here, so feel free to ask clarifying questions, and I can try to answer them. TYIA.