diff --git a/package-lock.json b/package-lock.json index 905ecc6..843d979 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,6 +7,7 @@ "name": "no-name", "license": "UNLICENSED", "dependencies": { + "@fortawesome/fontawesome-free": "6.7.2", "@vaadin/aura": "25.2.0", "@vaadin/common-frontend": "0.0.22", "@vaadin/react-components": "25.2.0", @@ -1754,6 +1755,15 @@ "tslib": "^2.4.0" } }, + "node_modules/@fortawesome/fontawesome-free": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz", + "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==", + "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)", + "engines": { + "node": ">=6" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", diff --git a/package.json b/package.json index 15d727d..d5ab112 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "license": "UNLICENSED", "type": "module", "dependencies": { + "@fortawesome/fontawesome-free": "6.7.2", "@vaadin/aura": "25.2.0", "@vaadin/common-frontend": "0.0.22", "@vaadin/react-components": "25.2.0", @@ -49,6 +50,7 @@ }, "vaadin": { "dependencies": { + "@fortawesome/fontawesome-free": "6.7.2", "@vaadin/aura": "25.2.0", "@vaadin/common-frontend": "0.0.22", "@vaadin/react-components": "25.2.0", @@ -93,8 +95,9 @@ "workbox-routing": "7.4.1", "workbox-strategies": "7.4.1" }, - "hash": "c759239a4f6d12f111d0cab12fe3ce6fdb558c5f8e2a3f33425bcfb33577e99b", + "hash": "54350847a380a8c1b6cc526f6f7eff8dd9253d848e38919e7e1b633cec9f3aca", "overrides": { + "@fortawesome/fontawesome-free": "$@fortawesome/fontawesome-free", "@vaadin/a11y-base": "25.2.0", "@vaadin/accordion": "25.2.0", "@vaadin/app-layout": "25.2.0", @@ -273,6 +276,7 @@ "workbox-build": { "glob": "13.0.6" }, - "apexcharts": "$apexcharts" + "apexcharts": "$apexcharts", + "@fortawesome/fontawesome-free": "$@fortawesome/fontawesome-free" } } \ No newline at end of file diff --git a/src/main/bundles/dev.bundle b/src/main/bundles/dev.bundle index ae23df9..459dfed 100644 Binary files a/src/main/bundles/dev.bundle and b/src/main/bundles/dev.bundle differ diff --git a/src/main/java/com/example/Application.java b/src/main/java/com/example/Application.java index 4d0a66b..6dc7811 100644 --- a/src/main/java/com/example/Application.java +++ b/src/main/java/com/example/Application.java @@ -4,6 +4,8 @@ import com.vaadin.flow.theme.aura.Aura; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import com.vaadin.flow.component.dependency.CssImport; +import com.vaadin.flow.component.dependency.NpmPackage; import com.vaadin.flow.component.dependency.StyleSheet; import com.vaadin.flow.component.page.AppShellConfigurator; import com.vaadin.flow.component.page.Push; @@ -12,6 +14,8 @@ import com.vaadin.flow.server.PWA; @SpringBootApplication @StyleSheet(Aura.STYLESHEET) @StyleSheet("styles.css") // Your custom styles +@NpmPackage(value = "@fortawesome/fontawesome-free", version = "6.7.2") +@CssImport("@fortawesome/fontawesome-free/css/all.min.css") @Push @PWA(name = "Dialect Charts", shortName = "Dialect", offlinePath = "offline.html") public class Application implements AppShellConfigurator { diff --git a/src/main/java/com/example/components/Fa.java b/src/main/java/com/example/components/Fa.java new file mode 100644 index 0000000..33c9ed3 --- /dev/null +++ b/src/main/java/com/example/components/Fa.java @@ -0,0 +1,34 @@ +package com.example.components; + +import com.vaadin.flow.component.icon.FontIcon; + +/** + * Font Awesome Free icon references, mirroring the ergonomics of + * {@code VaadinIcon.create()}. Backed by the {@code fa-*} CSS classes + * shipped in the bundled {@code @fortawesome/fontawesome-free} package. + * + *
Font Awesome paints glyphs via {@code content: var(--fa)} on + * {@code ::before}; the glyph-specific class (e.g. {@code fa-sun}) is what + * defines that {@code --fa} custom property, so both the family class + * ({@code fa-solid}) and the glyph class must be present. + */ +public enum Fa { + + MOON("fa-solid", "fa-moon"), + SUN("fa-solid", "fa-sun"), + DASHBOARD("fa-solid", "fa-gauge-high"), + FORM("fa-solid", "fa-rectangle-list"), + TABLE("fa-solid", "fa-table"), + GLOBE("fa-solid", "fa-globe"), + SEARCH("fa-solid", "fa-magnifying-glass"); + + private final String[] classes; + + Fa(String... classes) { + this.classes = classes; + } + + public FontIcon create() { + return new FontIcon(classes); + } +} diff --git a/src/main/java/com/example/views/MainLayout.java b/src/main/java/com/example/views/MainLayout.java index 45c4157..0ea2e4f 100644 --- a/src/main/java/com/example/views/MainLayout.java +++ b/src/main/java/com/example/views/MainLayout.java @@ -1,5 +1,6 @@ package com.example.views; +import com.example.components.Fa; import com.example.js.CommonJS; import com.vaadin.flow.component.UI; import com.vaadin.flow.component.applayout.AppLayout; @@ -7,7 +8,6 @@ import com.vaadin.flow.component.applayout.DrawerToggle; import com.vaadin.flow.component.button.Button; import com.vaadin.flow.component.button.ButtonVariant; import com.vaadin.flow.component.html.Span; -import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.menubar.MenuBar; import com.vaadin.flow.component.menubar.MenuBarVariant; import com.vaadin.flow.component.sidenav.SideNav; @@ -20,7 +20,7 @@ import java.util.Locale; @Layout public class MainLayout extends AppLayout { - private final Button themeToggle = new Button(VaadinIcon.MOON.create()); + private final Button themeToggle = new Button(Fa.MOON.create()); public MainLayout() { DrawerToggle toggle = new DrawerToggle(); @@ -44,11 +44,11 @@ public class MainLayout extends AppLayout { SideNav nav = new SideNav(); nav.addItem(new SideNavItem(getTranslation("nav.dashboard"), DashboardView.class, - VaadinIcon.DASHBOARD.create())); + Fa.DASHBOARD.create())); nav.addItem(new SideNavItem(getTranslation("nav.form"), FormView.class, - VaadinIcon.FORM.create())); + Fa.FORM.create())); nav.addItem(new SideNavItem(getTranslation("nav.table"), TableView.class, - VaadinIcon.TABLE.create())); + Fa.TABLE.create())); addToDrawer(nav); } @@ -57,7 +57,7 @@ public class MainLayout extends AppLayout { MenuBar menuBar = new MenuBar(); menuBar.addThemeVariants(MenuBarVariant.LUMO_TERTIARY_INLINE); - var root = menuBar.addItem(VaadinIcon.GLOBE_WIRE.create()); + var root = menuBar.addItem(Fa.GLOBE.create()); root.setAriaLabel(getTranslation("action.language")); root.getSubMenu().addItem(getTranslation("lang.de"), e -> switchLanguage(Locale.GERMAN)); @@ -73,6 +73,6 @@ public class MainLayout extends AppLayout { } private void applyIconFor(String theme) { - themeToggle.setIcon("dark".equals(theme) ? VaadinIcon.SUN_O.create() : VaadinIcon.MOON.create()); + themeToggle.setIcon("dark".equals(theme) ? Fa.SUN.create() : Fa.MOON.create()); } } diff --git a/src/main/java/com/example/views/TableView.java b/src/main/java/com/example/views/TableView.java index ba76e2f..f5a5f78 100644 --- a/src/main/java/com/example/views/TableView.java +++ b/src/main/java/com/example/views/TableView.java @@ -1,9 +1,9 @@ package com.example.views; import com.example.components.Card; +import com.example.components.Fa; import com.vaadin.flow.component.grid.Grid; import com.vaadin.flow.component.grid.dataview.GridListDataView; -import com.vaadin.flow.component.icon.VaadinIcon; import com.vaadin.flow.component.orderedlayout.VerticalLayout; import com.vaadin.flow.component.textfield.TextField; import com.vaadin.flow.data.value.ValueChangeMode; @@ -45,7 +45,7 @@ public class TableView extends VerticalLayout implements HasDynamicTitle { TextField suche = new TextField(); suche.setPlaceholder(getTranslation("table.search")); - suche.setPrefixComponent(VaadinIcon.SEARCH.create()); + suche.setPrefixComponent(Fa.SEARCH.create()); suche.setClearButtonVisible(true); suche.setValueChangeMode(ValueChangeMode.EAGER); suche.setWidthFull(); diff --git a/src/main/resources/META-INF/resources/styles.css b/src/main/resources/META-INF/resources/styles.css index eca9c26..fd72668 100644 --- a/src/main/resources/META-INF/resources/styles.css +++ b/src/main/resources/META-INF/resources/styles.css @@ -63,6 +63,17 @@ border-style: solid; } +/* Icon-only buttons (e.g. theme toggle): Font Awesome's icon-font metrics give + the button's label part an inflated line box, growing the button and pushing + the icon toward the top instead of centering it. Vaadin SVG icons didn't hit + this because they don't route through font line-height at all. */ +vaadin-button[theme~="icon"]::part(label) { + display: flex; + align-items: center; + justify-content: center; + height: 100%; +} + /* Top bar: solid white, opaque, divider + soft shadow below. Separates it from the sidebar/content instead of blending into one surface. */ vaadin-app-layout::part(navbar) {