diff --git a/flet_contrib/notify/README.md b/flet_contrib/notify/README.md
new file mode 100644
index 0000000..62ce3df
--- /dev/null
+++ b/flet_contrib/notify/README.md
@@ -0,0 +1,496 @@
+# Notify - Pop-up In-App Notifications
+
+`Notify` control is used to display information using a pop-up in-app notification.
+
+`Notify` control inherits from [`Container`](https://flet.dev/docs/controls/container).
+
+Recommended to add notify to the page on top of other controls
+
+## Examples
+
+
+
+

+
+
+```python
+from flet import *
+
+from flet_contrib.notify import NotifyMode, NotifyOpenDirection, Notify
+
+def main(page: Page):
+
+ def open_notify(e):
+ notify.open(e.control.text, 'Message', 'Header') # open notify with 'e.control.text' mode
+
+ page.add(
+ Row(
+ tight=True,
+ controls=[
+ TextButton('test', on_click=open_notify),
+ TextButton('warning', on_click=open_notify),
+ TextButton('error', on_click=open_notify)
+ ]
+ )
+ )
+
+ page.window.width = 700
+ page.window.height = 500
+
+ page.vertical_alignment = 'center'
+ page.horizontal_alignment = 'center'
+
+ notify = Notify(
+ modes=[
+ NotifyMode( # register NotifyMode object with default parameters
+ name='test'
+ ),
+ NotifyMode( # register NotifyMode object with half of parameters
+ name='warning',
+ color='deeppurple500',
+ icon=Icons.WARNING_ROUNDED
+ ),
+ NotifyMode( # register NotifyMode object with almost all parameters
+ name='error',
+ color='red900',
+ icon=Icons.ERROR_ROUNDED,
+ icon_color='bluegrey800',
+ header_color='bluegrey800',
+ message_color='bluegrey900'
+ )
+ ],
+ open_direction=NotifyOpenDirection.BOTTOM_TO_TOP,
+ bottom_to_top_end=Offset(0, 2.9), # set custom end offset. Because default is not enough
+ divider_visible=False # turn off divider visibility
+ )
+
+ page.add(notify)
+
+app(target=main)
+```
+
+## Properties
+
+### `modes`
+
+List of notification modes.
+
+### `open_time`
+
+Notification display time.
+
+Defaults to `3`
+
+### `open_direction`
+
+Notification animation direction
+
+Defaults to `NotifyOpenDirection.BOTTOM_TO_TOP`
+
+### `width`
+
+Width of main notification container
+
+Defaults to `300`
+
+### `height`
+
+Height of main notification container
+
+Defaults to `60`
+
+### `header_width`
+
+Width of header control
+
+Defaults to `240`
+
+### `message_width`
+
+Width of message control
+
+Defaults to `240`
+
+### `theme`
+
+Theme of `Notify` object
+
+Defaults to `NotifyTheme()`
+
+### `padding`
+
+Padding of main notification container
+
+Defaults to `12`
+
+### `row_spacing`
+
+Spacing between controls in a row (`Icon`, `VerticalDivider`, `Text`)
+
+Defaults to `15`
+
+### `row_alignment`
+
+Alignment of controls in a row (`Icon`, `VerticalDivider`, `Text`)
+
+Defaults to `'start'`
+
+### `text_column_spacing`
+
+Spacing between text controls in a column (`header`, `message`)
+
+Defaults to `1`
+
+### `text_column_alignment`
+
+Alignment of text controls in a column (`header`, `message`)
+
+Defaults to `'start'`
+
+### `border_width`
+
+Width of borders of main notification container
+
+Defaults to `1`
+
+### `border_radius`
+
+Radius of rounding corners of main notification container
+
+Defaults to `10`
+
+### `border_color`
+
+Color of borders of main notification container
+
+Defaults to `'grey800`
+
+### `divider_visible`
+
+Visibility of divider between icon and text
+
+Defaults to `True`
+
+### `bottom_to_top_start`
+
+Custom start offset for `NotifyOpenDirection.BOTTOM_TO_TOP` direction.
+
+Defaults to `DefaultOffsets.bottom_to_top_start`
+
+### `bottom_to_top_end`
+
+Custom end offset for `NotifyOpenDirection.BOTTOM_TO_TOP` direction.
+
+Defaults to `DefaultOffsets.bottom_to_top_end`
+
+### `bottom_right_to_left_start`
+
+Custom start offset for `NotifyOpenDirection.BOTTOM_RIGHT_TO_LEFT` direction.
+
+Defaults to `DefaultOffsets.bottom_right_to_left_start`
+
+### `bottom_right_to_left_end`
+
+Custom end offset for `NotifyOpenDirection.BOTTOM_RIGHT_TO_LEFT` direction.
+
+Defaults to `DefaultOffsets.bottom_right_to_left_end`
+
+### `bottom_left_to_right_start`
+
+Custom start offset for `NotifyOpenDirection.BOTTOM_LEFT_TO_RIGHT` direction.
+
+Defaults to `DefaultOffsets.bottom_left_to_right_start`
+
+### `bottom_left_to_right_end`
+
+Custom end offset for `NotifyOpenDirection.BOTTOM_LEFT_TO_RIGHT` direction.
+
+Defaults to `DefaultOffsets.bottom_left_to_right_end`
+
+### `top_to_bottom_start`
+
+Custom start offset for `NotifyOpenDirection.TOP_TO_BOTTOM` direction.
+
+Defaults to `DefaultOffsets.top_to_bottom_start`
+
+### `top_to_bottom_end`
+
+Custom end offset for `NotifyOpenDirection.TOP_TO_BOTTOM` direction.
+
+Defaults to `DefaultOffsets.top_to_bottom_end`
+
+### `top_right_to_left_start`
+
+Custom start offset for `NotifyOpenDirection.TOP_RIGHT_TO_LEFT` direction.
+
+Defaults to `DefaultOffsets.top_right_to_left_start`
+
+### `top_right_to_left_end`
+
+Custom end offset for `NotifyOpenDirection.TOP_RIGHT_TO_LEFT` direction.
+
+Defaults to `DefaultOffsets.top_right_to_left_end`
+
+### `top_left_to_right_start`
+
+Custom start offset for `NotifyOpenDirection.TOP_LEFT_TO_RIGHT` direction.
+
+Defaults to `DefaultOffsets.top_left_to_right_start`
+
+### `top_left_to_right_end`
+
+Custom end offset for `NotifyOpenDirection.TOP_LEFT_TO_RIGHT` direction.
+
+Defaults to `DefaultOffsets.top_left_to_right_end`
+
+## Functions
+
+### **`open(mode: NotifyMode | str, message_text: str, header_text: str = None) -> None`**
+
+Notification display function.
+
+**Parameters**
+- `mode` - `NotifyMode` object or the name of `NotifyMode` object passed in the `modes` parameter earlier.
+- `message_text` - Message text to display.
+- `header_text` - Header text to display (*Optional).
+
+### **`_reveal() -> None`**
+
+Function to remove transparency from main notification container.
+
+### **`_get_mode(name: str) -> NotifyMode | None`**
+
+Function for getting the `NotifyMode` object loaded into the `modes` list.
+
+### **`_set_mode(mode: NotifyMode) -> None`**
+
+Notification formatting function.
+- *Edits the appearance of main notification container. Based on passed mode.*
+
+**Parameters**
+- `mode` - `NotifyMode` object, which will change the appearance of main notification container.
+
+### **`__set_direction(direction: NotifyOpenDirection, upd: bool = True) -> None`**
+
+A function for specifying direction of notification animation.
+
+**Parameters**
+- `direction` - New notification animation direction.
+
+### **`__draw() -> None`**
+
+Notification animation function.
+
+# NotifyMode
+A `dataclass` that describes basic appearance parameters for `Notify` object.
+
+This allows you to change appearance of notifications by using `NotifyMode.name` as a parameter for the `Notify.open()`.
+
+## Properties
+
+### `name`
+The name by which this `NotifyMode` instance will be available in future.
+
+Defaults to `'mode{randint(100, 500)}'`
+
+### `color`
+Background color of main notification container.
+
+Defaults to `'black'`
+
+### `gradient`
+Gradient of main notification container.
+
+Defaults to `None`
+
+### `icon`
+Notification icon.
+
+Defaults to `Icons.INFO_ROUNDED`
+
+### `icon_color`
+Notification icon color.
+
+Defaults to `'white70'`
+
+### `header_color`
+Header text color.
+
+Defaults to `'white70'`
+
+### `message_color`
+Message text color.
+
+Defaults to `'white60'`
+
+### `divider_color`
+Color of divider that separates icon and text.
+
+Defaults to `'grey800'`
+
+# NotifyTheme
+A `dataclass` that describes parameters of a `Notify` and its elements.
+
+## Properties
+
+### `header_size`
+Size of header text.
+
+Defaults to `11`
+
+### `header_weight`
+Font weight of header text.
+
+Defaults to `'bold'`
+
+### `header_text_align`
+Alignment of header text.
+
+Defaults to `'left'`
+
+### `message_size`
+Size of message text.
+
+Defaults to `10`
+
+### `message_weight`
+Font weight of message text.
+
+Defaults to `'w500'`
+
+### `message_text_align`
+Alignment of message text.
+
+Defaults to `'left'`
+
+### `text_animate_opacity`
+Text controls opacity animation speed (`header`, `message`).
+
+Defaults to `400`
+
+### `divider_width`
+Width of divider between icon and text.
+
+Defaults to `1`
+
+### `divider_thickness`
+Thickness of divider between icon and text.
+
+Defaults to `2`
+
+### `animate`
+Animation of main notification container.
+
+Defaults to `Animation(600, 'decelerate')`
+
+### `animate_offset`
+Main notification container offset animation speed.
+
+Defaults to `400`
+
+### `animate_opacity`
+Main notification container opacity animation speed.
+
+Defaults to `400`
+
+# NotifyOpenDirection
+Enum of notification display directions.
+
+Each NotifyOpenDirection value has its own 2 offsets.
+
+
+
+ Directions and Offsets cheat sheet
+
+
+
+## Properties
+
+### `BOTTOM_TO_TOP`
+From bottom to top direction, centered, at bottom
+
+### `BOTTOM_RIGHT_TO_LEFT`
+From right to left direction, at bottom
+
+### `BOTTOM_LEFT_TO_RIGHT`
+From left to right direction, at bottom
+
+### `TOP_TO_BOTTOM`
+From top to bottom direction, centered, at top
+
+### `TOP_RIGHT_TO_LEFT`
+From right to left direction, at top
+
+### `TOP_LEFT_TO_RIGHT`
+From left to right direction, at top
+
+# DefaultOffsets
+Enum of basic offsets for beginning and end of animation.
+
+`Start offset` - offset at which the animation begins.
+
+`End offset` - offset at which the animation ends.
+
+## Properties
+
+### `bottom_to_top_start`
+From bottom to top, centered, at bottom. Start offset.
+
+Defaults to `Offset(0, 9)`
+
+### `bottom_to_top_end`
+From bottom to top, centered, at bottom. End offset.
+
+Defaults to `Offset(0, 4.1)`
+
+### `bottom_right_to_left_start`
+From right to left, at bottom. Start offset.
+
+Defaults to `Offset(2, 4.1)`
+
+### `bottom_right_to_left_end`
+From right to left, at bottom. End offset.
+
+Defaults to `Offset(0.625, 4.1)`
+
+### `bottom_left_to_right_start`
+From left to right, at bottom. Start offset.
+
+Defaults to `Offset(-2, 4.1)`
+
+### `bottom_left_to_right_end`
+From left to right, at bottom. End offset.
+
+Defaults to `Offset(-0.625, 4.1)`
+
+### `top_to_bottom_start`
+From top to bottom, centered, at top. Start offset.
+
+Defaults to `Offset(0, -9)`
+
+### `top_to_bottom_end`
+From top to bottom, centered, at top. End offset.
+
+Defaults to `Offset(0, -4.1)`
+
+### `top_right_to_left_start`
+From right to left, at top. Start offset.
+
+Defaults to `Offset(2, -4.1)`
+
+### `top_right_to_left_end`
+From right to left, at top. End offset.
+
+Defaults to `Offset(0.625, -4.1)`
+
+### `top_left_to_right_start`
+From left to right, at top. Start offset.
+
+Defaults to `Offset(-2, -4.1)`
+
+### `top_left_to_right_end`
+From left to right, at top. End offset.
+
+Defaults to `Offset(-0.625, -4.1)`
+
+
diff --git a/flet_contrib/notify/__init__.py b/flet_contrib/notify/__init__.py
new file mode 100644
index 0000000..2b69e21
--- /dev/null
+++ b/flet_contrib/notify/__init__.py
@@ -0,0 +1,3 @@
+from flet_contrib.notify.src.notify import (
+ NotifyMode, NotifyTheme, NotifyOpenDirection, DefaultOffsets, Notify
+)
\ No newline at end of file
diff --git a/flet_contrib/notify/examples/notify_directions_example.py b/flet_contrib/notify/examples/notify_directions_example.py
new file mode 100644
index 0000000..fd80a11
--- /dev/null
+++ b/flet_contrib/notify/examples/notify_directions_example.py
@@ -0,0 +1,60 @@
+from flet import *
+
+from flet_contrib.notify import NotifyMode, NotifyOpenDirection, Notify
+
+def main(page: Page):
+
+ def open_notify(e):
+ notify.open('test', 'Message', 'Header') # open notify with 'test' mode
+
+ def notify_direction_change(e):
+ notify.open_direction = NotifyOpenDirection.__getattribute__(NotifyOpenDirection, e.control.value)
+
+ page.add(
+ Column(
+ tight=True,
+ controls=[
+ Dropdown(
+ value='BOTTOM_TO_TOP',
+ options=[
+ DropdownOption('BOTTOM_TO_TOP'),
+ DropdownOption('BOTTOM_RIGHT_TO_LEFT'),
+ DropdownOption('BOTTOM_LEFT_TO_RIGHT'),
+ DropdownOption('TOP_TO_BOTTOM'),
+ DropdownOption('TOP_RIGHT_TO_LEFT'),
+ DropdownOption('TOP_LEFT_TO_RIGHT'),
+ ], on_change=notify_direction_change
+ ),
+ TextButton('open', on_click=open_notify),
+ ]
+ ),
+ )
+
+ page.window.width = 700
+ page.window.height = 500
+
+ page.vertical_alignment = 'center'
+ page.horizontal_alignment = 'center'
+
+ notify = Notify(
+ modes=[
+ NotifyMode(name='test') # register NotifyMode object with default parameters
+ ],
+ open_direction=NotifyOpenDirection.BOTTOM_TO_TOP,
+ bottom_to_top_end=Offset(0, 2.4), # set custom end offset. Because default is not enough
+ bottom_right_to_left_start=Offset(3, 2.4),
+ bottom_right_to_left_end=Offset(0.625, 2.4),
+ bottom_left_to_right_start=Offset(-3, 2.4),
+ bottom_left_to_right_end=Offset(-0.625, 2.4),
+ top_to_bottom_start=Offset(0, -6),
+ top_to_bottom_end=Offset(0, -4.1),
+ top_right_to_left_start=Offset(3, -4.1),
+ top_right_to_left_end=Offset(0.625, -4.1),
+ top_left_to_right_start=Offset(-3, -4.1),
+ top_left_to_right_end=Offset(-0.625, -4.1),
+ divider_visible=False # turn off divider visibility
+ )
+
+ page.add(notify)
+
+app(target=main)
\ No newline at end of file
diff --git a/flet_contrib/notify/examples/notify_example.py b/flet_contrib/notify/examples/notify_example.py
new file mode 100644
index 0000000..8ca9ab6
--- /dev/null
+++ b/flet_contrib/notify/examples/notify_example.py
@@ -0,0 +1,53 @@
+from flet import *
+
+from flet_contrib.notify import NotifyMode, NotifyOpenDirection, Notify
+
+def main(page: Page):
+
+ def open_notify(e):
+ notify.open(e.control.text, 'Message', 'Header') # open notify with 'e.control.text' mode
+
+ page.add(
+ Row(
+ tight=True,
+ controls=[
+ TextButton('test', on_click=open_notify),
+ TextButton('warning', on_click=open_notify),
+ TextButton('error', on_click=open_notify)
+ ]
+ )
+ )
+
+ page.window.width = 700
+ page.window.height = 500
+
+ page.vertical_alignment = 'center'
+ page.horizontal_alignment = 'center'
+
+ notify = Notify(
+ modes=[
+ NotifyMode( # register NotifyMode object with default parameters
+ name='test'
+ ),
+ NotifyMode( # register NotifyMode object with half of parameters
+ name='warning',
+ color='deeppurple500',
+ icon=Icons.WARNING_ROUNDED
+ ),
+ NotifyMode( # register NotifyMode object with almost all parameters
+ name='error',
+ color='red900',
+ icon=Icons.ERROR_ROUNDED,
+ icon_color='bluegrey800',
+ header_color='bluegrey800',
+ message_color='bluegrey900'
+ )
+ ],
+ open_direction=NotifyOpenDirection.BOTTOM_TO_TOP,
+ bottom_to_top_end=Offset(0, 2.9), # set custom end offset. Because default is not enough
+ divider_visible=False # turn off divider visibility
+ )
+
+ page.add(notify)
+
+app(target=main)
\ No newline at end of file
diff --git a/flet_contrib/notify/examples/notify_with_text_example.py b/flet_contrib/notify/examples/notify_with_text_example.py
new file mode 100644
index 0000000..ffc91b8
--- /dev/null
+++ b/flet_contrib/notify/examples/notify_with_text_example.py
@@ -0,0 +1,41 @@
+from flet import *
+
+from flet_contrib.notify import NotifyMode, NotifyOpenDirection, Notify
+
+def main(page: Page):
+
+ def open_notify(e):
+ notify.open('test', message.value, header.value) # open notify with 'test' mode
+
+ header = TextField(label='Header', value='Header')
+ message = TextField(label='Message', value='Message')
+
+ page.add(
+ Column(
+ tight=True,
+ controls=[
+ header,
+ message,
+ TextButton('open', on_click=open_notify),
+ ]
+ ),
+ )
+
+ page.window.width = 700
+ page.window.height = 500
+
+ page.vertical_alignment = 'center'
+ page.horizontal_alignment = 'center'
+
+ notify = Notify(
+ modes=[
+ NotifyMode(name='test') # register NotifyMode object with default parameters
+ ],
+ open_direction=NotifyOpenDirection.BOTTOM_TO_TOP,
+ bottom_to_top_end=Offset(0, 1.95), # set custom end offset. Because default is not enough
+ divider_visible=False # turn off divider visibility
+ )
+
+ page.add(notify)
+
+app(target=main)
\ No newline at end of file
diff --git a/flet_contrib/notify/examples/notify_without_header_example.py b/flet_contrib/notify/examples/notify_without_header_example.py
new file mode 100644
index 0000000..b266376
--- /dev/null
+++ b/flet_contrib/notify/examples/notify_without_header_example.py
@@ -0,0 +1,35 @@
+from flet import *
+
+from flet_contrib.notify import NotifyMode, Notify
+
+def main(page: Page):
+
+ def open_notify(e):
+ notify.open('test', 'Notification without header') # open notify with 'test' mode
+
+ page.add(
+ Row(
+ tight=True,
+ controls=[
+ TextButton('notify without header', on_click=open_notify)
+ ]
+ )
+ )
+
+ page.window.width = 700
+ page.window.height = 500
+
+ page.vertical_alignment = 'center'
+ page.horizontal_alignment = 'center'
+
+ notify = Notify(
+ modes=[
+ NotifyMode(name='test') # register NotifyMode object with default parameters
+ ],
+ bottom_to_top_end=Offset(0, 2.9), # set custom end offset. Because default is not enough
+ divider_visible=False # turn off divider visibility
+ )
+
+ page.add(notify)
+
+app(target=main)
\ No newline at end of file
diff --git a/flet_contrib/notify/media/action.gif b/flet_contrib/notify/media/action.gif
new file mode 100644
index 0000000..3d7ac78
Binary files /dev/null and b/flet_contrib/notify/media/action.gif differ
diff --git a/flet_contrib/notify/media/default_notify.png b/flet_contrib/notify/media/default_notify.png
new file mode 100644
index 0000000..d271fe6
Binary files /dev/null and b/flet_contrib/notify/media/default_notify.png differ
diff --git a/flet_contrib/notify/media/directions_n_offsets_sheet.jpg b/flet_contrib/notify/media/directions_n_offsets_sheet.jpg
new file mode 100644
index 0000000..c5810f2
Binary files /dev/null and b/flet_contrib/notify/media/directions_n_offsets_sheet.jpg differ
diff --git a/flet_contrib/notify/media/error_notify.png b/flet_contrib/notify/media/error_notify.png
new file mode 100644
index 0000000..e4d89b3
Binary files /dev/null and b/flet_contrib/notify/media/error_notify.png differ
diff --git a/flet_contrib/notify/media/warning_notify.png b/flet_contrib/notify/media/warning_notify.png
new file mode 100644
index 0000000..5492489
Binary files /dev/null and b/flet_contrib/notify/media/warning_notify.png differ
diff --git a/flet_contrib/notify/src/notify.py b/flet_contrib/notify/src/notify.py
new file mode 100644
index 0000000..6b9aebe
--- /dev/null
+++ b/flet_contrib/notify/src/notify.py
@@ -0,0 +1,536 @@
+from flet import *
+from typing import Optional
+from dataclasses import dataclass, field
+from random import randint
+from enum import Enum
+from time import sleep
+
+
+@dataclass
+class NotifyMode():
+ """A **`dataclass`** that describes basic appearance parameters for **`Notify`** object.
+
+ This allows you to change appearance of notifications by using **`NotifyMode.name`** as a parameter for the **`Notify.open()`**
+
+ :param str name: The name by which this **`NotifyMode`** instance will be available in future
+ \n - Defaults to **`'mode{randint(100, 500)}'`**
+ :param Colors | str color: Background colors of main notification container
+ \n - Defaults to **`'black`**
+ :param LinearGradient | RadialGradient | SweepGradient gradient: Gradient of main notification container
+ \n - Defaults to **`None`**
+ :param Icons | str icon: Notification icon
+ \n - Defaults to **`Icons.INFO_ROUNDED`**
+ :param Colors | str icon_color: Icon color
+ \n - Defaults to **`'white70'`**
+ :param Colors | str header_color: Header text color
+ \n - Defaults to **`'white70'`**
+ :param Colors | str message_color: Message text color
+ \n - Defaults to **`'white60'`**
+ :param Colors | str divider_color: Color of divider that separates icon and text
+ \n - Defaults to **`'grey800'`**
+ """
+
+ name: str = 'mode{0}'.format(str(randint(100, 500)))
+
+ color: Optional[Colors | str] = 'black'
+ gradient: Optional[LinearGradient | RadialGradient | SweepGradient] = None
+ icon: Optional[Icons | str] = Icons.INFO_ROUNDED
+ icon_color: Optional[Colors | str] = 'white70'
+ header_color: Optional[Colors | str] = 'white70'
+ message_color: Optional[Colors | str] = 'white60'
+ divider_color: Optional[Colors | str] = 'grey800'
+
+
+@dataclass
+class NotifyTheme():
+ """A **`dataclass`** that describes appearance of a **`Notify`** and its elements
+
+ :param Optional[int | float] header_size: Size of header text
+ \n - Defaults to **`11`**
+ :param Optional[FontWeight | str] header_weight: Font weight of header text
+ \n - Defaults to **`'bold`**
+ :param Optional[TextAlign | str] header_text_align: Alignment of header text
+ \n - Defaults to **`'left'`**
+ :param Optional[int | float] message_size: Size of message text
+ \n - Defaults to **`10`**
+ :param Optional[FontWeight | str] message_weight: Font weight of message text
+ \n - Defaults to **`'w500'`**
+ :param Optional[TextAlign | str] message_text_align: Alignment of message text
+ \n - Defaults to **`'left`**
+ :param Optional[int | float] text_animate_opacity: Text controls opacity animation speed (**`header`**, **`message`**)
+ \n - Defaults to **`400`**
+ :param Optional[int | float] divider_width: Width of divider between icon and text
+ \n - Defaults to **`1`**
+ :param Optional[int | float] divider_thickness: Thickness of divider between icon and text
+ \n - Defaults to **`2`**
+ :param Optional[Animation] animate: Animation of main notification container
+ \n - Defaults to **`Animation(600, 'decelerate')`**
+ :param Optional[int | float] animate_offset: Main notification container offset animation speed
+ \n - Defaults to **`400`**
+ :param Optional[int | float] animate_opacity: Main notification container opacity animation speed
+ \n - Defaults to **`400`**
+ """
+
+ header_size: Optional[int | float] = 11
+ header_weight: Optional[FontWeight | str] = 'bold'
+ header_text_align: Optional[TextAlign | str] = 'left'
+ message_size: Optional[int | float] = 10
+ message_weight: Optional[FontWeight | str] = 'w500'
+ message_text_align: Optional[TextAlign | str] = 'left'
+ text_animate_opacity: Optional[int | float] = 400
+ divider_width: Optional[int | float] = 1
+ divider_thickness: Optional[int | float] = 2
+ animate: Optional[Animation] = field(default_factory=lambda : Animation(600, 'decelerate'))
+ animate_offset: Optional[int | float] = 400
+ animate_opacity: Optional[int | float] = 400
+
+
+class NotifyOpenDirection(Enum):
+ """.. Enum:: of notification display directions
+ - **BOTTOM_TO_TOP** - From bottom to top direction, centered, at bottom
+ - **BOTTOM_RIGHT_TO_LEFT** - From right to left direction, at bottom
+ - **BOTTOM_LEFT_TO_RIGHT** - From left to right direction, at bottom
+ - **TOP_TO_BOTTOM** - From top to bottom direction, centered, at top
+ - **TOP_RIGHT_TO_LEFT** - From right to left direction, at top
+ - **TOP_LEFT_TO_RIGHT** - From left to right direction, at top
+ """
+
+ BOTTOM_TO_TOP = 'bottom_to_top'
+ BOTTOM_RIGHT_TO_LEFT = 'bottom_right_to_left'
+ BOTTOM_LEFT_TO_RIGHT = 'bottom_left_to_right'
+ TOP_TO_BOTTOM = 'top_to_bottom'
+ TOP_RIGHT_TO_LEFT = 'top_right_to_left'
+ TOP_LEFT_TO_RIGHT = 'top_left_to_right'
+
+
+@dataclass
+class DefaultOffsets():
+ """**`Enum`** of basic offsets for beginning and end of animation
+
+ \n`Start offset` - offset at which the animation begins
+ \n`End offset` - offset at which the animation ends.
+
+ - **bottom_to_top_start**
+ - From bottom to top, centered, at bottom. Start offset
+ - Defaults to **`Offset(0, 9)`**
+ - **bottom_to_top_end**
+ - From bottom to top, centered, at bottom. End offset
+ - Defaults to **`Offset(0, 4.1)`**
+ - **bottom_right_to_left_start**
+ - From right to left, at bottom. Start offset
+ - Defaults to **`Offset(2, 4.1)`**
+ - **bottom_right_to_left_end**
+ - From right to left, at bottom. End offset
+ - Defaults to **`Offset(0.625, 4.1)`**
+ - **bottom_left_to_right_start**
+ - From left to right, at bottom. Start offset
+ - Defaults to **`Offset(-2, 4.1)`**
+ - **bottom_left_to_right_end**
+ - From left to right, at bottom. End offset
+ - Defaults to **`Offset(-0.625, 4.1)`**
+ - **top_to_bottom_start**
+ - From top to bottom, centered, at top. Start offset
+ - Defaults to **`Offset(0, -9)`**
+ - **top_to_bottom_end**
+ - From top to bottom, centered, at top. End offset
+ - Defaults to **`Offset(0, -4.1)`**
+ - **top_right_to_left_start**
+ - From right to left, at top. Start offset
+ - Defaults to **`Offset(2, -4.1)`**
+ - **top_right_to_left_end**
+ - From right to left, at top. End offset
+ - Defaults to **`Offset(0.625, -4.1)`**
+ - **top_left_to_right_start**
+ - From left to right, at top. Start offset
+ - Defaults to **`Offset(-2, -4.1)`**
+ - **top_left_to_right_end**
+ - From left to right, at top. End offset
+ - Defaults to **`Offset(-0.625, -4.1)`**
+ """
+ bottom_to_top_start = Offset(0, 9)
+ bottom_to_top_end = Offset(0, 4.1)
+ bottom_right_to_left_start = Offset(2, 4.1)
+ bottom_right_to_left_end = Offset(0.625, 4.1)
+ bottom_left_to_right_start = Offset(-2, 4.1)
+ bottom_left_to_right_end = Offset(-0.625, 4.1)
+ top_to_bottom_start = Offset(0, -9)
+ top_to_bottom_end = Offset(0, -4.1)
+ top_right_to_left_start = Offset(2, -4.1)
+ top_right_to_left_end = Offset(0.625, -4.1)
+ top_left_to_right_start = Offset(-2, -4.1)
+ top_left_to_right_end = Offset(-0.625, -4.1)
+
+
+class Notify(Container):
+ """Main **`class`** of notifications. Based on **`Container`**
+
+ :param list[NotifyMode] modes: List of notification modes
+ :param Optional[int | float] open_time: Notification display time
+ \n - Defaults to **`3`**
+ :param Optional[NotifyOpenDirection] open_direction: Notification animation direction
+ \n - Defaults to **`NotifyOpenDirection.BOTTOM_TO_TOP`**
+ :param Optional[int | float] width: Width of main notification container
+ \n - Defaults to **`300
+ :param Optional[int | float] height: Height of main notification container
+ \n - Defaults to **`60`**
+ :param Optional[int | float] header_width: Width of header control
+ \n - Defaults to **`240`**
+ :param Optional[int | float] message_width: Width of message control
+ \n - Defaults to **`240`**
+ :param Optional[NotifyTheme] theme: Theme of **`Notify`** object
+ \n - Defaults to **`NotifyTheme()`**
+ :param Optional[int | float] padding: Padding of main notification container
+ \n - Defaults to **`12`**
+ :param Optional[int | float] row_spacing: Spacing between controls in a row (**`Icon`**, **`VerticalDivider`**, **`Text`**)
+ \n - Defaults to **`15`**
+ :param Optional[MainAxisAlignment | str] row_alignment: Alignment of controls in a row (**`Icon`**, **`VerticalDivider`**, **`Text`**)
+ \n - Defaults to **`'start'`**
+ :param Optional[int | float] text_column_spacing: Spacing between text controls in a column (**`header`**, **`message`**)
+ \n - Defaults to **`1`**
+ :param Optional[MainAxisAlignment | str] text_column_alignment: Alignment of text controls in a column (**`header`**, **`message`**)
+ \n - Defaults to **`'start'`**
+ :param Optional[int | float] border_width: Width of borders of main notification container
+ \n - Defaults to **`1`**
+ :param Optional[int | float] border_radius: Radius of rounding corners of main notification container
+ \n - Defaults to **`10`**
+ :param Optional[Colors | str] border_color: Color of borders of main notification container
+ \n - Defaults to **`'grey800`**
+ :param Optional[bool] divider_visible: Visibility of divider between icon and text
+ \n - Defaults to **`True`**
+ :param Optional[Offset] bottom_to_top_start: Custom start offset for `from bottom to top, centered, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_to_top_start`**
+ :param Optional[Offset] bottom_to_top_end: Custom end offset for `from bottom to top, centered, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_to_top_end`**
+ :param Optional[Offset] bottom_right_to_left_start: Custom start offset for `from right to left, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_right_to_left_start`**
+ :param Optional[Offset] bottom_right_to_left_end: Custom end offset for `from right to left, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_right_to_left_end`**
+ :param Optional[Offset] bottom_left_to_right_start: Custom start offset for `from left to right, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_left_to_right_start`**
+ :param Optional[Offset] bottom_left_to_right_end: Custom end offset for `from left to right, at bottom` direction
+ \n - Defaults to **`DefaultOffsets.bottom_left_to_right_end`**
+ :param Optional[Offset] top_to_bottom_start: Custom start offset for `from top to bottom, centered, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_to_bottom_start`**
+ :param Optional[Offset] top_to_bottom_end: Custom end offset for `from top to bottom, centered, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_to_bottom_end`**
+ :param Optional[Offset] top_right_to_left_start: Custom start offset for `from right to left, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_right_to_left_start`**
+ :param Optional[Offset] top_right_to_left_end: Custom end offset for `from right to left, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_right_to_left_end`**
+ :param Optional[Offset] top_left_to_right_start: Custom start offset for `from left to right, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_left_to_right_start`**
+ :param Optional[Offset] top_left_to_right_end: Custom end offset for `from left to right, at top` direction
+ \n - Defaults to **`DefaultOffsets.top_left_to_right_end`**
+ """
+
+ def __init__(
+ self,
+ modes: list[NotifyMode],
+ open_time: Optional[int | float] = 3,
+ open_direction: Optional[NotifyOpenDirection] = NotifyOpenDirection.BOTTOM_TO_TOP,
+ width: Optional[int | float] = 300,
+ height: Optional[int | float] = 60,
+ header_width: Optional[int | float] = 240,
+ message_width: Optional[int | float] = 240,
+ theme: Optional[NotifyTheme] = NotifyTheme(),
+ padding: Optional[int |float] = 12,
+ row_spacing: Optional[int | float] = 15,
+ row_alignment: Optional[MainAxisAlignment | str] = 'start',
+ text_column_spacing: Optional[int | float] = 1,
+ text_column_alignment: Optional[MainAxisAlignment | str] = 'start',
+ border_width: Optional[int | float] = 1,
+ border_radius: Optional[int | float] = 10,
+ border_color: Optional[Colors | str] = 'grey800',
+ divider_visible: Optional[bool] = True,
+ bottom_to_top_start: Optional[Offset] = DefaultOffsets.bottom_to_top_start,
+ bottom_to_top_end: Optional[Offset] = DefaultOffsets.bottom_to_top_end,
+ bottom_right_to_left_start: Optional[Offset] = DefaultOffsets.bottom_right_to_left_start,
+ bottom_right_to_left_end: Optional[Offset] = DefaultOffsets.bottom_right_to_left_end,
+ bottom_left_to_right_start: Optional[Offset] = DefaultOffsets.bottom_left_to_right_start,
+ bottom_left_to_right_end: Optional[Offset] = DefaultOffsets.bottom_left_to_right_end,
+ top_to_bottom_start: Optional[Offset] = DefaultOffsets.top_to_bottom_start,
+ top_to_bottom_end: Optional[Offset] = DefaultOffsets.top_to_bottom_end,
+ top_right_to_left_start: Optional[Offset] = DefaultOffsets.top_right_to_left_start,
+ top_right_to_left_end: Optional[Offset] = DefaultOffsets.top_right_to_left_end,
+ top_left_to_right_start: Optional[Offset] = DefaultOffsets.top_left_to_right_start,
+ top_left_to_right_end: Optional[Offset] = DefaultOffsets.top_left_to_right_end
+ ):
+
+ self.theme = theme
+
+ self.__open_time = open_time
+ self.__open_direction = open_direction
+
+ self.__bottom_to_top_start = bottom_to_top_start
+ self.__bottom_to_top_end = bottom_to_top_end
+ self.__bottom_right_to_left_start = bottom_right_to_left_start
+ self.__bottom_right_to_left_end = bottom_right_to_left_end
+ self.__bottom_left_to_right_start = bottom_left_to_right_start
+ self.__bottom_left_to_right_end = bottom_left_to_right_end
+ self.__top_to_bottom_start = top_to_bottom_start
+ self.__top_to_bottom_end = top_to_bottom_end
+ self.__top_right_to_left_start = top_right_to_left_start
+ self.__top_right_to_left_end = top_right_to_left_end
+ self.__top_left_to_right_start = top_left_to_right_start
+ self.__top_left_to_right_end = top_left_to_right_end
+
+ self.__set_direction(self.__open_direction, False)
+
+ self.modes = modes
+ self.__default_mode = NotifyMode('default')
+
+ self.leading = Icon(
+ name=self.__default_mode.icon
+ )
+ self.divider = VerticalDivider(
+ width=self.theme.divider_width,
+ thickness=self.theme.divider_thickness,
+ visible=divider_visible
+ )
+ self.header = Text(
+ value='header',
+ size=self.theme.header_size,
+ weight=self.theme.header_weight,
+ width=header_width,
+ text_align=self.theme.header_text_align
+ )
+ self.message = Text(
+ value='message',
+ size=self.theme.message_size,
+ weight=self.theme.message_weight,
+ width=message_width,
+ text_align=self.theme.message_text_align
+ )
+
+ super().__init__(
+ content=Row(
+ controls=[
+ self.leading,
+ self.divider,
+ Column(
+ spacing=text_column_spacing,
+ alignment=text_column_alignment,
+ controls=[
+ self.header,
+ self.message
+ ],
+ )
+ ],
+ opacity=0,
+ animate_opacity=self.theme.text_animate_opacity,
+ spacing=row_spacing,
+ alignment=row_alignment
+ ),
+ opacity=0,
+
+ offset=self.__start,
+
+ width=width,
+ height=height,
+
+ padding=padding,
+
+ bgcolor=self.__default_mode.color if (self.__default_mode.color and
+ not self.__default_mode.gradient) else None,
+
+ gradient=self.__default_mode.gradient if (self.__default_mode.gradient and
+ not self.__default_mode.color) else None,
+
+ border=Border(
+ BorderSide(width=border_width, color=border_color),
+ BorderSide(width=border_width, color=border_color),
+ BorderSide(width=border_width, color=border_color),
+ BorderSide(width=border_width, color=border_color)
+ ),
+ border_radius=border_radius,
+
+ animate=self.theme.animate,
+ animate_offset=self.theme.animate_offset,
+ animate_opacity=self.theme.animate_opacity
+ )
+
+ def open(self, mode: NotifyMode | str, message_text: str, header_text: str = None) -> None:
+ """Notification display function
+
+ :param header_text: Header text to display
+ :type header_text: str
+ :param message_text: Message text to display
+ :type message_text: str
+ :param mode: NotifyMode for formatting notification.
+ \n **`NotifyMode`** object or the name of **`NotifyMode`** object passed in the **`modes`** parameter earlier
+ :type mode: NotifyMode | str
+ """
+
+ if (isinstance(mode, NotifyMode)):
+ self._set_mode(mode)
+ self.header.value = header_text
+ self.message.value = message_text
+ elif (isinstance(mode, str)):
+ if (mode := self._get_mode(mode)):
+ self._set_mode(mode)
+ self.header.value = header_text
+ self.message.value = message_text
+ if (not header_text):
+ self.header.visible = False
+ elif (not self.header.visible):
+ self.header.visible = True
+ self.__draw()
+
+ def __draw(self) -> None:
+ """Notification animation function"""
+
+ if (self.offset != self.__end):
+ self.opacity = 1
+ self.content.opacity = 1
+ self.offset = self.__end
+ self.update()
+ sleep(self.__open_time)
+ self.opacity = 0
+ self.content.opacity = 0
+ self.offset = self.__start
+ self.update()
+
+ def _reveal(self) -> None:
+ """Function to remove transparency from main notification container.
+
+ Can be used to calculate **`offsets`**
+ """
+
+ self.opacity = 1
+ self.content.opacity = 1
+ self.update()
+
+ def __set_direction(self, direction: NotifyOpenDirection, upd: bool = True) -> None:
+ """A function for specifying direction of notification animation
+
+ :param direction:
+ :type direction: NotifyOpenDirection
+ """
+
+ match(direction):
+ case NotifyOpenDirection.BOTTOM_TO_TOP:
+ self.__start, self.__end = (self.__bottom_to_top_start, self.__bottom_to_top_end)
+ case NotifyOpenDirection.BOTTOM_RIGHT_TO_LEFT:
+ self.__start, self.__end = (self.__bottom_right_to_left_start, self.__bottom_right_to_left_end)
+ case NotifyOpenDirection.BOTTOM_LEFT_TO_RIGHT:
+ self.__start, self.__end = (self.__bottom_left_to_right_start, self.__bottom_left_to_right_end)
+ case NotifyOpenDirection.TOP_TO_BOTTOM:
+ self.__start, self.__end = (self.__top_to_bottom_start, self.__top_to_bottom_end)
+ case NotifyOpenDirection.TOP_RIGHT_TO_LEFT:
+ self.__start, self.__end = (self.__top_right_to_left_start, self.__top_right_to_left_end)
+ case NotifyOpenDirection.TOP_LEFT_TO_RIGHT:
+ self.__start, self.__end = (self.__top_left_to_right_start, self.__top_left_to_right_end)
+ case _:
+ self.__start, self.__end = (self.__bottom_to_top_start, self.__bottom_to_top_end)
+
+ if (upd):
+ if (self.opacity == 0):
+ self.offset = self.__start
+ if (self.page): self.update()
+
+ def _set_mode(self, mode: NotifyMode) -> None:
+ """Notification formatting function
+
+ :param mode: Formatting mode
+ :type mode: NotifyMode
+ """
+
+ self.bgcolor = mode.color if (mode.color and
+ not mode.gradient) else None
+ self.gradient = mode.gradient if (mode.gradient) else None
+ self.leading.name = mode.icon
+ self.leading.color = mode.icon_color
+ self.divider.color = mode.divider_color
+ self.header.color = mode.header_color
+ self.message.color = mode.message_color
+ if (self.page): self.update()
+
+ def _get_mode(self, name: str) -> NotifyMode | None:
+ """Function for getting the **`NotifyMode`** object loaded into the **`modes`** list"""
+
+ for mode in self.modes:
+ if (mode.name == name):
+ return mode
+
+ # open_timeout
+ @property
+ def open_time(self):
+ """Notification display time
+
+ :returns: int | float
+ """
+
+ return self.__open_time
+
+ @open_time.setter
+ def open_time(self, value):
+ """Notification display time
+
+ :param value:
+ :type value: int | float
+ """
+
+ self.__open_time = value
+
+ # start
+ @property
+ def start(self):
+ """Notification animation start offset
+
+ :returns: Offset
+ """
+
+ return self.__start
+
+ @start.setter
+ def start(self, value):
+ """Notification animation start offset
+
+ :param value:
+ :type value: Offset
+ """
+
+ self.__start = value
+
+ # end
+ @property
+ def end(self):
+ """Notification animation end offset
+
+ :returns: Offset
+ """
+
+ return self.__end
+
+ @end.setter
+ def end(self, value):
+ """Notification animation end offset
+
+ :param value:
+ :type value: Offset
+ """
+
+ self.__end = value
+
+ # open_direction
+ @property
+ def open_direction(self):
+ """Notification animation direction
+
+ :returns: NotifyOpenDirection
+ """
+
+ return self.__open_direction
+
+ @open_direction.setter
+ def open_direction(self, value):
+ """Notification animation direction
+
+ :param value:
+ :type value: NotifyOpenDirection
+ """
+
+ if (self.__open_direction != value):
+ self.__set_direction(value)
+
+ self.__open_direction = value
\ No newline at end of file