baklava
baklava copied to clipboard
Notification Component
Design
Implementation
General usage example:
<bl-notification
variant="info"
caption="Info Caption"
description="Info Description"
permanent
swipe
>
Info Notification Component Text
</bl-notification>
Rules
Put some rules about how this component should behave and implemented
permanentattribute controls the component visibility. If true component stays on the screen, if false component disappears after 7 seconds. (For default it's false.) (If a user hover their mouse over component, countdown stops.)swipeattribute controls the component dismiss functionality. If true component can be dismissed by swipe to right. (For default it's false.)
API Reference:
bl-notification component
Notification component displays an informational message to users for a while with additional features if desired.
Description
Attributes
| Attribute | Description | Default Value |
|---|---|---|
variant (string) |
Decides variants of notification box ( info, success, warning, error ) |
"info" |
caption (string) |
Sets notification caption | - |
description (string) |
Sets notification description | - |
permanent (boolean) |
Stays component always on the screen | false |
swipe (boolean) |
Makes component swipeable to dismiss | false |
Notification Component Design Meeting Report
Date: 12.10.2022 15:30 (UTC+3)
- Notification component will cover uses cases that we previously named as Toast.
- Notifications will be temporary by default.
- Default duration will be decided.
- Duration can be set by the user.
- We'll consider setting default duration regarding to content length.
- Notification can be set as permanent. In this case Notification will be dismissed by a user action (close button)
- Notifications can be dismissed with swipe event (swipe down for small screens, swipe right for large screens)
- Close button will be optional.
- A progress will be shown in temporary mode.
- Dismiss progress will be paused when user hover on notification.
- Notification will be position on bottom on small screens, and top right (or top left regarding to text direction) on large screens.
- Notification will enter/leave screen with an animation. Comes/leaves from/to bottom on small screens, right on large screens.
- Multiple notifications would be visible with a vertical stack. New notifications will come to top on large screens, and will come to bottom on small screens.
- By default distance of the notification group to top and bottom of the screen will be defined on both small and large screens. On small screens maximum area will be kept as half of the screen height at most. These margins would be set by the user (top-distance, bottom-distance)
- Notifications can have multiple variants. Variants will be defined in design phase.
- Technically we may use Alert component inside Notification component since visually they may look very identical with some exceptions. This will be considered during design phase.
Here is Figma link for design & documentation, we are still working on the notification design for small screens.
Current design is heavily using our Alert component. But there are some arrangements to do first on Alert component. We have a separate issue for that. #318
I have 2 more issues that I found, I use alert and progress indicator component when making notification component so:
- Progress indicator needs to have more than 2 colors.
- Progress indicator border radius needs to be arrangeable.
How can we fix those problems?
When I check figma design, I see the component as same as our Alert component. Maybe notification component should just be a wrapper of alert component. Then variant, caption, description can be set with alert component.
<bl-notification permanent>
<bl-alert variant="success" caption="Message sent!">
Your message has been sent successfully!
<bl-button slot="action">Undo</bl-button>
</bl-alert>
</bl-notification>
Even progress indicator and auto dismissing functionality can be part of Alert component. Maybe notification component can just handle the positioning (and swipe to dismiss). What do you think? @buseselvi @onursert
Regarding to your questions:
- We can add a CSS variable to
progress-indicatorcomponent likeprogress-colorthat defaults to--bl-color-success. - If progress will be part of alert component, then border-radiuses can be handled by covering corners inside alert component borders.
We'll also need some events to track if a notification dismissed, showed-up etc. And I don't think that we need to set an attribute to enable swiping. If notification is not permanent (means can be dismissable) then dismissing always would be done via swiping or by pressing close icon.
We shouldn't use auto dismissing function on alert component because choosing one gets complicated and alerts don't work that way 🥲 Apart from that, if we can, we can use the alert component as base component for the notification. @muratcorlu @onursert
Hey,
The way I understand from the ADR, the usage of this component is similar to bl-dialog. We expect user to render it when they need it. I believe we should provide user with programmatic interface instead. Since the main usage of this component is mostly going to be errors on async actions. The usage example could be:
<bl-notification />
<script>
const notificationController = document.querySelector('bl-notification');
notificationController.addNotification({
caption: 'Error',
description: 'Something went wrong',
variant: 'error',
icon: true,
permanent: true,
action: {
label: 'Ok',
onClick: notification => {
// maybe wait for animation to end?
await notificationController.removeNotification(notification.id);
// or
await notification.remove()
},
},
});
</script>
Hi @ogunb,
Since we provide web components here, I think we should always try to keep providing a declarative way to implement basic functionality. But we can (should) also provide imperative ways of doing functionality, if it adds practical options.
So, maybe instead of using <bl-notification> for both ways, we can define a <bl-notification-container> component which has a method like you mentioned above. It can simple add bl-notification component in its template internally. That means, some developers can still just use bl-notification component to show and hide a notification in HTML easily (but putting and removing it to/from DOM) and some others can use this method to programmatically add notifications.
Even we can consider adding some extra methods as shortcuts like showAlert that will set some parameters with a predefined value for a "alert" type notification (like error variant, error icon, permenent true, etc).
I will be revising the ADR for this component in the upcoming days.
Here are some key points from our last update meeting:
- We are planning to introduce two components: a standalone
bl-notificationand abl-notification-container. - The container component will offer an interface for managing notifications and will handle their positioning.
- The question of whether the
bl-notificationshould dictate its own position is still open. Various ideas were discussed:- The
bl-notificationcomponent could publish and listen for events related to being opened/dismissed within the document, allowing it to determine the top position dynamically. - Alternatively, the
bl-notificationmight not have any positioning logic altogether, serving as a blank canvas. Users would then have the freedom to develop their own interfaces on top of it. - Another option is to restrict the use of
bl-notificationto being a child component ofbl-notification-container. In this scenario, the container would take charge of positioning. However, a potential drawback is that if multiple containers exist, notifications from different containers might overlap. Users should exercise caution in such cases.
- The
We created a quick and dirty POC w/ @CagriAldemir. It covers all cases mentioned before.
The concept is:
bl-notificationcomponent emits a global created and removed events.bl-notification-containerlistens these events and moves the components as its child or removes them.bl-notification-containerrenders them inside light dom so user can still access thebl-notificationelement.- If the user doesn't use
bl-notification-container,bl-notificationwill render on place. User can position and implement their own interface as they'd like.
Any feedback would be appreciated.
Template Usage
<bl-notification-container></bl-notification-container>
<bl-notification
id="notification"
caption="Welcome to Baklava!"
description="This is a notification"
variant="info"
icon
></bl-notification>
JS Usage
<bl-notification-container></bl-notification-container>
<script>
const el = document.querySelector("bl-notification-container");
el.addNotification({
caption: "Welcome to Baklava!",
description: "This is a notification",
variant: "info",
icon: true,
action: {
label: "Action",
onClick: notification => {
notification.dismiss();
},
},
});
</script>
Thank you for the work you've put into the Notification component and the PoC 🚀 . I'm impressed with the considerations you've incorporated. As we move forward, please keep in mind a few points to ensure we're meeting our standards:
- Ensure every notification is equipped with the correct ARIA roles, states, and properties. For clarity, roles like "alert" or "status" would be suitable in many contexts.
- It's essential that users can navigate to and interact with notifications using only their keyboards, with particular attention to the action buttons.
- Maintain a smooth user experience by ensuring that the appearance and dismissal of notifications do not result in jarring content shifts. @buseselvi can help us about this. 🙏
https://github.com/Trendyol/baklava/issues/617
We have the same issue as above. Murat suggested that Popover API could be used and it does solve the covering issue but, dialog element will prevent any action outside of it regardless of their placement on top layer. So the notifications becomes non-interactive.
I haven't figured out a workaround for this. Here is a codesanbox setup if anyone is willing to give it a shot.
My suggestion would be to ditch dialog element all together.
Have you tried dialog element with polyfilled=true attribute, is this problem still ocurring?
Nope. Since polyfilled version is actually a div and doesn't use the top layer; it will work, which is why I suggest ditching the dialog all together.
Design
bl-notification Implementation
General usage example:
<bl-notification
no-animation
duration="7"
></bl-notification>
<script>
const el = document.querySelector("bl-notification");
const addedNotification = el.addNotification({
caption: "Notification Caption",
description: "This is a notification",
variant: "warning",
icon: "academy",
primaryAction: {
label: "Action",
onClick: notification => {
notification.remove();
},
},
secondaryAction: {
label: "Action",
onClick: async notification => {
await notification.remove();
first.remove();
},
},
});
// some actions
addedNotification.remove();
// or
el.removeNotification(addedNotification.id);
</script>
Rules
durationattribute sets the default duration of notifications when not provided.no-animationattribute disables animation of notifications. Animations will respect the user's preferences regardless of this property.- Cards animate in from right on desktop and animate in from top on mobile (screens smaller than 480px).
- Last in card will be on top of the notification list on desktop, and last in card will be on bottom of the notification list on mobile.
- Cards has touch support on mobile. User can swipe to up to dismiss the notification.
- This component will act as an interface that will manage notifications. It will have two methods to add and remove notifications.
API Reference
Notification component acts as an interface that will manage notifications. It has two methods to add and remove notifications.
Attributes
| Attribute | Description | Default Value |
|---|---|---|
duration (number) |
Sets the default duration of notifications in seconds when not provided | 7 |
no-animation (boolean) |
Disables animation of notifications | false |
Methods
| Method | Description | Parameters | Return Value |
|---|---|---|---|
addNotification |
Adds a notification to the notification list | BlNotificationCard Props | The added notification object with remove method |
removeNotification |
Async method that removes a notification from the notification list after the animation is finished | Notification ID | A promise that resolves when the animation is finished |
bl-notification-card Implementation
General usage example:
<bl-notification-card
caption="Caption"
icon
variant="error"
permanent
duration="7"
closed
@bl-notification-card-request-close
@bl-notification-card-close
>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
<bl-button slot="primary-action">Action</bl-button>
<bl-button slot="secondary-action">Secondary Action</bl-button>
</bl-notification-card
Rules
durationattribute sets the duration of the notification in seconds. When the duration is over, the notification will be dismissed automatically.permanentattribute makes the notification permanent and it will not be dismissed automatically. User can still dismiss it manually.closedattribute makes the notification closed and it will not be displayed.captionattribute sets the caption of the notification.iconattribute sets the icon of the notification. Either boolean or icon name can be provided. True value will usebl-alertdefault.variantattribute sets the variant of the notification. Possible values areinfo,success,warning,error.primary-actionslot will be displayed as a primary action button.secondary-actionslot will be displayed as a secondary action button.bl-notification-card-request-closeevent will be fired when the notification is requested to be closed. If default prevented, the notification will not be closed.bl-notification-card-closeevent will be fired when the notification is closed.
API Reference
Notification card component is a component that will be used to display notifications.
Attributes
| Attribute | Description | Default Value |
|---|---|---|
duration (number) |
Sets the duration of the notification in seconds | 7 |
permanent (boolean) |
Makes the notification permanent and it will not be dismissed automatically | false |
closed (boolean) |
Makes the notification closed and it will not be displayed | false |
caption (string) |
Sets the caption of the notification | "" |
icon (string) |
Sets the icon of the notification | "" |
variant (string) |
Sets the variant of the notification | "" |
Slots
| Slot | Description |
|---|---|
default |
Will be displayed as the description of the notification |
primary-action |
Will be displayed as a primary action button |
secondary-action |
Will be displayed as a secondary action button |
Events
| Event | Description | Detail |
|---|---|---|
bl-notification-card-request-close |
Fired when the notification is requested to be closed | { source: "duration-ended" / "close-button" } |
bl-notification-card-close |
Fired when the notification is closed | { source: "duration-ended" / "close-button" } |
I think we should rename slot names that has been named as 'action' and 'action-secondary'. Primary-action and secondary-action fit better, imho.
:tada: This issue has been resolved in version 2.4.0-beta.3 :tada:
The release is available on:
Your semantic-release bot :package::rocket:
:tada: This issue has been resolved in version 3.0.0 :tada:
The release is available on:
Your semantic-release bot :package::rocket: