Show a Notification
- Copy-Paste into Your Project
- Showing a Notification
- Theme Variants
- Position
- Duration
- Persistent Notifications with a Close Button
- Undoing an Action
- Centralizing Notification Logic
- When to Use Notifications
This article shows how to display brief messages to the user using the Notification component. It covers basic text notifications, theme variants for different severity levels, positioning, auto-close duration, and persistent notifications with close buttons. For the full API details, see the Notification reference documentation.
Copy-Paste into Your Project
A self-contained view that demonstrates common notification patterns:
Source code
Java
import com.vaadin.flow.component.Key;
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.notification.Notification;
import com.vaadin.flow.component.notification.NotificationVariant;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
@Route("notification-example")
class NotificationExampleView extends VerticalLayout {
public NotificationExampleView() {
// Simple text notification
Button infoButton = new Button("Show info", event ->
Notification.show("Task completed"));
// Success notification
Button successButton = new Button("Show success", event -> {
Notification notification = Notification.show("File uploaded");
notification.addThemeVariants(
NotificationVariant.SUCCESS);
});
// Error notification with a close button
Button errorButton = new Button("Show error", event -> {
Notification notification = new Notification();
notification.addThemeVariants(
NotificationVariant.ERROR);
notification.setDuration(0);
Span message = new Span("Upload failed. Check your connection.");
Button closeButton = new Button(
VaadinIcon.CLOSE.create(),
e -> notification.close());
closeButton.addThemeVariants(ButtonVariant.TERTIARY);
closeButton.addClickShortcut(Key.ESCAPE)
.listenOn(notification);
notification.add(
new HorizontalLayout(message, closeButton));
notification.open();
});
add(infoButton, successButton, errorButton);
}
}Showing a Notification
The simplest way to show a notification is the static Notification.show() method:
Source code
Java
Notification.show("Changes saved");This displays a text notification at the bottom of the viewport. It auto-closes after 5 seconds.
You can also specify the duration and position:
Source code
Java
Notification.show("Changes saved", 3000,
Notification.Position.TOP_END);Theme Variants
Theme variants give notifications a visual style that matches their purpose. Apply them with addThemeVariants():
Source code
Java
Notification notification = Notification.show("File uploaded");
notification.addThemeVariants(NotificationVariant.SUCCESS);The available theme variants are:
-
SUCCESS— completed actions, for example, "Record saved" -
ERROR— failures, for example, "Upload failed" -
WARNING— warnings, for example, "Session expiring soon" -
INFO— important informational messages
|
Tip
| Don’t overuse success notifications. If an action succeeds silently without side effects, a notification may not be necessary. |
Position
Notifications appear at the bottom center of the viewport by default. Change the position with setPosition():
Source code
Java
Notification notification = Notification.show("New message");
notification.setPosition(Notification.Position.TOP_END);Common positions:
-
BOTTOM_STARTorTOP_END— unobtrusive but noticeable. Good defaults for most notifications. -
MIDDLE— the most disruptive position. Reserve for important messages like errors. -
TOP_STRETCHorBOTTOM_STRETCH— span the full width of the viewport. Use for important messages that need more space.
Multiple simultaneous notifications stack vertically.
|
Tip
| Be consistent with positioning. Pick one or two positions and use them throughout your application. |
Duration
By default, Notification.show() auto-closes after 5000 milliseconds (5 seconds). Set a custom duration in milliseconds:
Source code
Java
Notification notification = Notification.show("Brief message");
notification.setDuration(3000);A duration of 0 makes the notification persistent — it stays visible until the user or your code closes it. Use persistent notifications for errors, warnings, and any notification with interactive content.
Source code
Java
Notification notification = new Notification();
notification.setDuration(0); 1
notification.add("Connection lost.");
notification.open();
// Later, when the connection is restored:
notification.close(); 2-
The notification stays visible until explicitly closed.
-
Call
close()to dismiss the notification programmatically.
|
Tip
| Keep the minimum duration at 5 seconds. Shorter durations are easy to miss, especially for longer messages. |
Persistent Notifications with a Close Button
Error and warning notifications should be persistent so the user has time to read them. Add a close button to let the user dismiss the notification. Notifications can also include action buttons for operations like Retry or Undo.
Assign keyboard shortcuts to action and close buttons so the user can respond without reaching for the notification. Use Escape for the close button and Enter for the primary action as a best practice. See Add Keyboard Shortcuts for details on the shortcut API.
The following example shows a persistent error notification with a Retry button and a close button, with keyboard shortcuts assigned to both:
Source code
Java
Notification notification = new Notification();
notification.addThemeVariants(NotificationVariant.ERROR);
notification.setDuration(0);
notification.setPosition(Notification.Position.MIDDLE);
Span message = new Span("Upload failed.");
Button retryButton = new Button("Retry", event -> {
retryUpload();
notification.close();
});
retryButton.addClickShortcut(Key.ENTER)
.listenOn(notification);
Button closeButton = new Button(
VaadinIcon.CLOSE.create(),
event -> notification.close());
closeButton.addThemeVariants(ButtonVariant.TERTIARY);
closeButton.addClickShortcut(Key.ESCAPE)
.listenOn(notification);
HorizontalLayout layout = new HorizontalLayout(
message, retryButton, closeButton);
layout.setAlignItems(Alignment.CENTER);
notification.add(layout);
notification.open();Undoing an Action
For actions that can’t be reverted once they’ve been performed, such as sending a message, you can give the user a short time to change their mind. Delay the action, show a notification with an Undo button, and cancel the delayed action if the user clicks it.
Schedule the delayed action in an application service, protected with method-level security like any other service method. The service returns the ScheduledFuture, so that the UI can cancel it:
Source code
Java
@Service
public class MessageService {
private final TaskScheduler taskScheduler;
private final TaskExecutor taskExecutor;
MessageService(TaskScheduler taskScheduler, TaskExecutor taskExecutor) {
this.taskScheduler = taskScheduler;
this.taskExecutor = taskExecutor;
}
@PreAuthorize("hasAuthority('permission:sendmessage')") 1
public ScheduledFuture<?> scheduleSend(String message, Duration delay) {
String sender = SecurityContextHolder.getContext()
.getAuthentication().getName(); 2
return taskScheduler.schedule( 3
() -> taskExecutor.execute(() -> send(sender, message)), 4
Instant.now().plus(delay));
}
private void send(String sender, String message) {
// Deliver the message
}
}-
Spring checks the permission when the user schedules the send, in the user’s own thread.
-
The send runs in a background thread, where the user’s security context isn’t available. Read the user while it still is, and pass it to the background task. See Security for details.
-
The
TaskSchedulerwaits for the delay before starting the send. See Task Scheduling for how to use it. -
The scheduler only triggers the send and hands it over to the
TaskExecutor. A slow send would otherwise block the scheduling thread pool, as explained in Task Scheduling Caveats.
The view schedules the send and shows the notification:
Source code
Java
private void sendMessage(String message) {
ScheduledFuture<?> sending = messageService.scheduleSend(message,
Duration.ofSeconds(5));
Notification notification = new Notification();
notification.setDuration(5000); 1
Button undoButton = new Button("Undo", event -> {
notification.close();
if (sending.cancel(false)) { 2
Notification.show("Message not sent");
} else {
Notification.show("The message can no longer be stopped");
}
});
HorizontalLayout layout = new HorizontalLayout(
new Span("Message sent"), undoButton);
layout.setAlignItems(Alignment.CENTER);
notification.add(layout);
notification.open();
}-
Unlike other notifications with interactive content, this one closes automatically: the Undo button is only useful while the action can still be cancelled, so the notification stays open for exactly that long.
-
cancel()returnsfalseonce the send has been handed over to theTaskExecutor. From then on, the action can’t be undone anymore.
If the action needs to update the UI when it’s performed, use server push as described in Server Push.
Centralizing Notification Logic
As your application grows, constructing notifications by hand in every view leads to inconsistency — different durations, positions, and styles across the codebase. Create a utility class with static methods so that every notification looks and behaves the same:
Source code
Java
public final class Notifications {
private Notifications() {}
public static void showSuccess(String message) {
Notification notification = Notification.show(message);
notification.addThemeVariants(NotificationVariant.SUCCESS);
notification.setPosition(Notification.Position.BOTTOM_START);
}
public static void showError(String message) {
Notification notification = new Notification();
notification.addThemeVariants(NotificationVariant.ERROR);
notification.setDuration(0);
notification.setPosition(Notification.Position.MIDDLE);
Span text = new Span(message);
Button closeButton = new Button(
VaadinIcon.CLOSE.create(),
event -> notification.close());
closeButton.addThemeVariants(ButtonVariant.TERTIARY);
closeButton.addClickShortcut(Key.ESCAPE)
.listenOn(notification);
HorizontalLayout layout = new HorizontalLayout(
text, closeButton);
layout.setAlignItems(Alignment.CENTER);
notification.add(layout);
notification.open();
}
public static void showRetryableError(String message,
Runnable retryAction) {
Notification notification = new Notification();
notification.addThemeVariants(NotificationVariant.ERROR);
notification.setDuration(0);
notification.setPosition(Notification.Position.MIDDLE);
Span text = new Span(message);
Button retryButton = new Button("Retry", event -> {
notification.close();
retryAction.run();
});
retryButton.addClickShortcut(Key.ENTER)
.listenOn(notification);
Button closeButton = new Button(
VaadinIcon.CLOSE.create(),
event -> notification.close());
closeButton.addThemeVariants(ButtonVariant.TERTIARY);
closeButton.addClickShortcut(Key.ESCAPE)
.listenOn(notification);
HorizontalLayout layout = new HorizontalLayout(
text, retryButton, closeButton);
layout.setAlignItems(Alignment.CENTER);
notification.add(layout);
notification.open();
}
}Then call them anywhere in your application:
Source code
Java
Notifications.showSuccess("Record saved");
Notifications.showError("Failed to save. Please try again.");
Notifications.showRetryableError("Upload failed.", () -> uploadFile());This keeps your notification behavior — position, duration, theme, and close button pattern — defined in one place. When you need to change how notifications work, you update the utility class instead of every call site.
When to Use Notifications
Notifications work best for brief, non-critical information that does not require the user to take immediate action.
Good uses:
-
Confirming completed actions ("Record saved", "Email sent")
-
Reporting non-critical failures with a retry option ("Upload failed")
-
Providing undo opportunities for reversible actions
Use something else when:
-
The message requires immediate user action — use a Dialog or Confirm Dialog instead
-
The content is longer than one or two lines — link to a detail page instead of cramming text into a notification
-
The error is a form validation issue — display validation errors inline on the field itself, not in a notification. Notifications disappear, but validation errors should remain visible until the user corrects them.
-
You are tempted to show a notification for every action — if an action succeeds without side effects, silence is often the best feedback