├── .github
└── FUNDING.yml
├── README.md
├── example
├── index.html
├── script.js
└── style.css
├── saber-toast.css
└── saber-toast.js
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
4 | patreon: # Replace with a single Patreon username
5 | open_collective: # Replace with a single Open Collective username
6 | ko_fi: ahmed0saber # Replace with a single Ko-fi username
7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
9 | liberapay: # Replace with a single Liberapay username
10 | issuehunt: # Replace with a single IssueHunt username
11 | otechie: # Replace with a single Otechie username
12 | lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
13 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # saber-toast
2 |
3 | Saber Toast is a library for all your toasts
4 |
5 | ## example
6 |
7 | https://ahmed0saber.github.io/saber-toast/example/
8 |
9 | ## documentation on cssscript
10 |
11 | https://www.cssscript.com/stylish-toast-saber/
12 |
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Example | Saber Toast
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Example | Saber Toast
19 | Saber Toast is a library for all your toasts
20 |
21 | Fire Error
22 | Fire Success
23 | Fire Warn
24 | Fire Info
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/example/script.js:
--------------------------------------------------------------------------------
1 | document.querySelector(".success-btn").addEventListener('click', () => {
2 | saberToast.success({
3 | title: "تمت العملية بنجاح",
4 | text: "تم اضافة المنتج الى السلة",
5 | delay: 200,
6 | duration: 2600,
7 | rtl: true,
8 | position: "top-left"
9 | })
10 | })
11 |
12 | document.querySelector(".error-btn").addEventListener('click', () => {
13 | saberToast.error({
14 | title: "حدث خطأ ما",
15 | text: "يرجى المحاولة مرة اخرى",
16 | delay: 200,
17 | duration: 2600,
18 | rtl: true,
19 | position: "bottom-right"
20 | })
21 | })
22 |
23 | document.querySelector(".warn-btn").addEventListener('click', () => {
24 | saberToast.warn({
25 | title: "حدث خطأ ما",
26 | text: "يرجى المحاولة مرة اخرى",
27 | delay: 200,
28 | duration: 2600,
29 | rtl: true,
30 | position: "bottom-right"
31 | })
32 | })
33 |
34 | document.querySelector(".info-btn").addEventListener('click', () => {
35 | saberToast.info({
36 | title: "حدث خطأ ما",
37 | text: "يرجى المحاولة مرة اخرى",
38 | delay: 200,
39 | duration: 2600,
40 | rtl: true,
41 | position: "bottom-right"
42 | })
43 | })
--------------------------------------------------------------------------------
/example/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | position: relative;
6 | border: none;
7 | outline: none;
8 | font-family: 'Glory', 'Cairo', sans-serif;
9 | }
10 |
11 | body {
12 | min-height: 100vh;
13 | display: grid;
14 | place-items: center;
15 | background-color: #F7F7F7;
16 | padding: 12px;
17 | }
18 |
19 | main {
20 | padding: 12px;
21 | border: 2px solid #323232;
22 | width: 100%;
23 | max-width: 600px;
24 | border-radius: 6px;
25 | -webkit-border-radius: 6px;
26 | -moz-border-radius: 6px;
27 | -ms-border-radius: 6px;
28 | -o-border-radius: 6px;
29 | }
30 |
31 | .example h1 {
32 | color: #323232;
33 | font-size: 32px;
34 | }
35 |
36 | .example p {
37 | color: #323232;
38 | margin: 10px 0 16px 0;
39 | font-size: 22px;
40 | }
41 |
42 | .example .btns {
43 | display: flex;
44 | align-items: stretch;
45 | flex-wrap: wrap;
46 | gap: 12px;
47 | }
48 |
49 | .example button {
50 | padding: 12px;
51 | color: #F7F7F7;
52 | font-size: 20px;
53 | cursor: pointer;
54 | border-radius: 6px;
55 | -webkit-border-radius: 6px;
56 | -moz-border-radius: 6px;
57 | -ms-border-radius: 6px;
58 | -o-border-radius: 6px;
59 | width: calc(50% - 6px);
60 | }
61 |
62 | .example .error-btn {
63 | background-color: #dc3545;
64 | }
65 |
66 | .example .success-btn {
67 | background-color: #28a745;
68 | }
69 |
70 | .example .warn-btn {
71 | background-color: #BF9725;
72 | }
73 |
74 | .example .info-btn {
75 | background-color: #5953FF;
76 | }
--------------------------------------------------------------------------------
/saber-toast.css:
--------------------------------------------------------------------------------
1 | .saber-toasts-containers {
2 | position: fixed;
3 | width: 320px;
4 | display: flex;
5 | flex-direction: column;
6 | gap: 12px;
7 | direction: rtl;
8 | }
9 |
10 | .saber-toasts-container-bottom-right {
11 | right: 20px;
12 | bottom: 20px;
13 | }
14 |
15 | .saber-toasts-container-top-right {
16 | right: 20px;
17 | top: 20px;
18 | flex-direction: column-reverse;
19 | }
20 |
21 | .saber-toasts-container-bottom-left {
22 | left: 20px;
23 | bottom: 20px;
24 | }
25 |
26 | .saber-toasts-container-top-left {
27 | left: 20px;
28 | top: 20px;
29 | flex-direction: column-reverse;
30 | }
31 |
32 | .saber-toast {
33 | width: 320px;
34 | height: 80px;
35 | background-color: #FFF;
36 | box-shadow: 0px 0px 10px #0000001A;
37 | border-radius: 10px;
38 | -webkit-border-radius: 10px;
39 | -moz-border-radius: 10px;
40 | -ms-border-radius: 10px;
41 | -o-border-radius: 10px;
42 | display: flex;
43 | align-items: stretch;
44 | gap: 12px;
45 | }
46 |
47 | .saber-toast .right-border {
48 | width: 6px;
49 | border-radius: 0px 10px 10px 0px;
50 | -webkit-border-radius: 0px 10px 10px 0px;
51 | -moz-border-radius: 0px 10px 10px 0px;
52 | -ms-border-radius: 0px 10px 10px 0px;
53 | -o-border-radius: 0px 10px 10px 0px;
54 | margin: 0 0 0 2px;
55 | }
56 |
57 | .saber-toast .state-icon-holder {
58 | width: 40px;
59 | display: grid;
60 | place-items: center;
61 | }
62 |
63 | .saber-toast .state-icon {
64 | width: 40px;
65 | height: 40px;
66 | display: grid;
67 | place-items: center;
68 | border-radius: 50%;
69 | -webkit-border-radius: 50%;
70 | -moz-border-radius: 50%;
71 | -ms-border-radius: 50%;
72 | -o-border-radius: 50%;
73 | }
74 |
75 | .saber-toast .state-icon svg {
76 | width: 50%;
77 | }
78 |
79 | .saber-toast .text-container {
80 | display: flex;
81 | flex-direction: column;
82 | justify-content: center;
83 | gap: 6px;
84 | flex: 1;
85 | }
86 |
87 | .saber-toast .title {
88 | font-size: 12px;
89 | }
90 |
91 | .saber-toast .text {
92 | font-size: 13px;
93 | color: #18181A;
94 | font-weight: bold;
95 | }
96 |
97 | .saber-toast .close-icon-holder {
98 | padding: 12px;
99 | }
100 |
101 | .saber-toast .close-icon {
102 | width: 22px;
103 | height: 22px;
104 | background-color: #F1F1F1;
105 | border-radius: 50%;
106 | -webkit-border-radius: 50%;
107 | -moz-border-radius: 50%;
108 | -ms-border-radius: 50%;
109 | -o-border-radius: 50%;
110 | display: grid;
111 | place-items: center;
112 | cursor: pointer;
113 | }
114 |
115 | .saber-toast .close-icon svg {
116 | width: 70%;
117 | color: rgba(0, 0, 0, 0.5);
118 | }
119 |
120 | @media (max-width: 520px) {
121 | .saber-toasts-containers {
122 | width: 240px;
123 | }
124 |
125 | .saber-toast {
126 | width: 240px;
127 | height: 66px;
128 | gap: 8px;
129 | }
130 |
131 | .saber-toast .state-icon-holder {
132 | width: 30px;
133 | }
134 |
135 | .saber-toast .state-icon {
136 | width: 30px;
137 | height: 30px;
138 | }
139 |
140 | .saber-toast .title {
141 | font-size: 11px;
142 | }
143 |
144 | .saber-toast .text {
145 | font-size: 12px;
146 | }
147 |
148 | .saber-toast .text-container {
149 | gap: 3px;
150 | }
151 |
152 | .saber-toast .close-icon-holder {
153 | padding: 8px;
154 | }
155 |
156 | .saber-toast .close-icon {
157 | width: 18px;
158 | height: 18px;
159 | }
160 | }
--------------------------------------------------------------------------------
/saber-toast.js:
--------------------------------------------------------------------------------
1 | const initSaberToast = () => {
2 | const bottomRightContainer = document.createElement('div')
3 | bottomRightContainer.classList.add('saber-toasts-container-bottom-right')
4 | bottomRightContainer.classList.add('saber-toasts-containers')
5 | document.body.append(bottomRightContainer)
6 |
7 | const topRightContainer = document.createElement('div')
8 | topRightContainer.classList.add('saber-toasts-container-top-right')
9 | topRightContainer.classList.add('saber-toasts-containers')
10 | document.body.append(topRightContainer)
11 |
12 | const bottomLeftContainer = document.createElement('div')
13 | bottomLeftContainer.classList.add('saber-toasts-container-bottom-left')
14 | bottomLeftContainer.classList.add('saber-toasts-containers')
15 | document.body.append(bottomLeftContainer)
16 |
17 | const topLeftContainer = document.createElement('div')
18 | topLeftContainer.classList.add('saber-toasts-container-top-left')
19 | topLeftContainer.classList.add('saber-toasts-containers')
20 | document.body.append(topLeftContainer)
21 | }
22 | initSaberToast()
23 |
24 | class SaberToast {
25 | constructor() {
26 | this.color = ""
27 | this.icon = ""
28 | this.iconBackground = ""
29 | }
30 | success(params) {
31 | this.color = "#52BF5A"
32 | this.icon = ` `
33 | this.iconBackground = "rgba(82, 191, 90, 0.15)"
34 | this.fire(params)
35 | }
36 | error(params) {
37 | this.color = "#F96666"
38 | this.icon = ` `
39 | this.iconBackground = "rgba(249, 102, 102, 0.15)"
40 | this.fire(params)
41 | }
42 | warn(params) {
43 | this.color = "#BF9725"
44 | this.icon = ` `
45 | this.iconBackground = "rgba(191, 151, 37, 0.15)"
46 | this.fire(params)
47 | }
48 | info(params) {
49 | this.color = "#5953FF"
50 | this.icon = ` `
51 | this.iconBackground = "rgba(89, 83, 255, 0.15)"
52 | this.fire(params)
53 | }
54 | fire(params) {
55 | const DEFAULT_RTL = document.querySelector('html').getAttribute('dir')?.toLowerCase() === 'rtl';
56 | const { title, text, delay, duration, rtl, position } = { title: "", text: "", delay: 200, duration: 2600, rtl: DEFAULT_RTL, position: "bottom-right", ...params }
57 | const div = document.createElement('div')
58 | div.classList.add('saber-toast')
59 | div.style.textAlign = rtl ? "right" : "left"
60 | div.innerHTML = `
61 |
62 |
63 |
64 | ${this.icon}
65 |
66 |
67 |
68 |
69 | ${title}
70 |
71 |
72 | ${text}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 | `
83 |
84 | let isRight
85 | switch (position) {
86 | case "bottom-right":
87 | document.querySelector('.saber-toasts-container-bottom-right').append(div)
88 | isRight = true
89 | break
90 | case "top-right":
91 | document.querySelector('.saber-toasts-container-top-right').append(div)
92 | isRight = true
93 | break
94 | case "bottom-left":
95 | document.querySelector('.saber-toasts-container-bottom-left').append(div)
96 | isRight = false
97 | break
98 | case "top-left":
99 | document.querySelector('.saber-toasts-container-top-left').append(div)
100 | isRight = false
101 | break
102 | default:
103 | document.querySelector('.saber-toasts-container-bottom-right').append(div)
104 | isRight = true
105 | }
106 |
107 | if (isRight) {
108 | div.style.right = "-320px"
109 | } else {
110 | div.style.left = "-320px"
111 | }
112 |
113 | div.style.transitionDuration = `${delay}ms`
114 | setTimeout(() => {
115 | if (isRight) {
116 | div.style.right = "0px"
117 | } else {
118 | div.style.left = "0px"
119 | }
120 | }, 10)
121 |
122 | let mySecondTimeout = setTimeout(() => {
123 | div.style.transitionDuration = `${delay}ms`
124 | if (isRight) {
125 | div.style.right = "-320px"
126 | } else {
127 | div.style.left = "-320px"
128 | }
129 | }, delay + duration)
130 | let myThirdTimeout = setTimeout(() => {
131 | div.remove()
132 | }, 2 * delay + duration)
133 |
134 | div.addEventListener("mouseover", () => {
135 | clearTimeout(mySecondTimeout)
136 | clearTimeout(myThirdTimeout)
137 | })
138 | div.addEventListener("mouseout", () => {
139 | mySecondTimeout = setTimeout(() => {
140 | div.style.transitionDuration = `${delay}ms`
141 | if (isRight) {
142 | div.style.right = "-320px"
143 | } else {
144 | div.style.left = "-320px"
145 | }
146 | }, delay + duration)
147 | myThirdTimeout = setTimeout(() => {
148 | div.remove()
149 | }, 2 * delay + duration)
150 | })
151 |
152 | div.querySelector(".close-icon").addEventListener("click", () => {
153 | div.style.transitionDuration = `${delay}ms`
154 | setTimeout(() => {
155 | if (isRight) {
156 | div.style.right = "-320px"
157 | } else {
158 | div.style.left = "-320px"
159 | }
160 | setTimeout(() => {
161 | div.remove()
162 | }, delay)
163 | }, 10)
164 | })
165 | }
166 | }
167 |
168 | const saberToast = new SaberToast()
169 |
--------------------------------------------------------------------------------