Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions articles/styling/advanced/npm-packages.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -108,4 +108,62 @@
}
----

[since:com.vaadin:vaadin@V24.9]
[#fonts-and-images-from-npm-with-npmpackage-annotation]
== Loading Fonts and Images from npm Packages Using the NpmPackage annotation
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No mention of CSS? I'm wondering because this would also replace the theme.json's importCss, or?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't thought about that, but you could of copy any css as an asset and then have a @CssImport for it to load the css.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll test around a bit and add the information to the document.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be out of scope.. but I wanted to mention it because the ticket from above says "In Vaadin 25 we are going to deprecated Theme annotation and features in theme.json, including importCss instruction that then needs a replacement." and I was wondering where my importCss replacement is :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a quick test it would seem that we don't need anything new as the following seems to work

@NpmPackage(value = "@fortawesome/fontawesome-free", version = "5.15.1")
@CssImport("@fortawesome/fontawesome-free/css/all.css")
@Route("theme")
public class ThemeView extends Div {
    public ThemeView() {
        Span sharp = new Span();
        sharp.addClassNames("fa-sharp","fa-solid","fa-user");
        sharp.getStyle().set("font-family", "'Font Awesome 5 Free'");
        add(sharp);
    }
}

But this might need some extra testing to see that it wasn't just a fluke or something in the test module enabling this..

Copy link
Contributor

@knoobie knoobie Aug 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for checking! Previously people could do it also like this:

{
  "parent": "my-base-theme",
  "importCss": ["@fortawesome/fontawesome-free/css/all.min.css"],
  "lumoImports": ["typography","color","spacing","badge","utility"]
}


[annotationname]`NpmPackage` has the field `assets` that makes it possible to copy assets from npm packages without the need for a custom theme or the `theme.json` file.

The difference between using the `theme.json` and annotation `assets` is the location.
Theme copies under the custom theme folder, but the annotation copies to the static folder.

The syntax for [annotationname]`NpmPackage` is the same as used for `theme.json`, `"asset/glob/pattern:local/target/path"`.
Multiple assets can be given for a single package annotation.

.Sample asset mapping with `NpmPackage` annotation
[source,java]
----
@NpmPackage(value = "@fortawesome/fontawesome-free", version = "5.15.1",
assets = {
"svgs/regular/**:fontawesome/icons"
})
@Tag("my-component")
public class MyComponent implements Component {
public MyComponent() {
add(new Image("VAADIN/static/fontawesome/icons/snowflake.svg",
"snowflake"));
}
}
----

[NOTE]
The assets from the [annotationname]`NpmPackage` annotation are copied to the static folder `VAADIN/static` instead of `VAADIN/static/themes/[themeName]/`

In the sample case the `svgs/regular/snowflake.svg` file from the `fortawesome` package is copied to `VAADIN/static/fontawesome/icons/snowflake.svg` and you should reference it with that path in the application code, including CSS stylesheets.
This difference is due to the custom theme call having the `themes/[themeName]/` in the request letting us know it is a theme resource, making it possible to prepend the static part.

Check warning on line 143 in articles/styling/advanced/npm-packages.adoc

View workflow job for this annotation

GitHub Actions / lint

[vale] reported by reviewdog 🐶 [Vaadin.We] Try to avoid using first-person plural like 'us'. Raw Output: {"message": "[Vaadin.We] Try to avoid using first-person plural like 'us'.", "location": {"path": "articles/styling/advanced/npm-packages.adoc", "range": {"start": {"line": 143, "column": 105}}}, "severity": "WARNING"}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ThemeResource still a thing, even after the deprecation of the ´@Theme` annotation? Also, talking about a “custom theme” might be problematic, referring to the old theme mechanics, rather than just regular stylesheets.

Suggested change
This difference is due to the custom theme call having the `themes/[themeName]/` in the request letting us know it is a theme resource, making it possible to prepend the static part.
This difference is due to the custom theme call having the `themes/[themeName]/` in the request letting Vaadin know it's a theme resource, making it possible to prepend the static part.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Theme annotation will be deprecated along the themes/[themeName] path but it's still supported. After deprecation, "theme resource folder" is relevant only for apps still using it. For those it's "custom theme" and for new apps it's just regular css.

This article could have a reference to https://vaadin.com/docs/latest/styling/advanced/npm-packages#styles-from-npm to make it clearer what "custom theme" mean.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see the text before talking about the difference. But since this is the documentation for Vaadin 25, I don't think we should mention deprecated APIs at all, but guide users to use just the supported APIs.

I would remove any mentions and comparisons to theme.json, custom themes and theme resources. @peholmst, would you agree?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! Don't mention anything deprecated. Only mention what's current and recommended.


== Loading Stylesheets from npm Packages Using the CssImport annotation

To load stylesheets form npm packages it is possible to use [annotation]`CssImport` targeting the stylesheet in `node_modules`.
For example to load `all.min.css` from `@fortawesome/fontawesome-free` an endpoint needs to be annotated as `@CssImport("@fortawesome/fontawesome-free/css/all.min.css")`

.Sample asset mapping with `NpmPackage` annotation
[source,java]
----
@NpmPackage(value = "@fortawesome/fontawesome-free", version = "5.15.1")
@CssImport("@fortawesome/fontawesome-free/css/all.min.css")
public class AppShell implements AppShellConfigurator {
}

@Tag("my-component")
public class MyComponent implements Component {
public MyComponent() {
Span userIcon = new Span();
userIcon.addClassNames("fa-sharp", "fa-solid", "fa-user");
userIcon.getStyle().set("font-family", "'Font Awesome 5 Free'");
add(userIcon);
}
}
----

[discussion-id]`3e46fe3b-00d6-4cf7-908c-342a364210db`