flash_messages_rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +40 -0
- data/MIT-LICENSE +21 -0
- data/README.md +270 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/flash_messages/controllers/flash_controller.js +59 -0
- data/app/views/flash_messages/_flash.html.erb +91 -0
- data/app/views/flash_messages/_flash_message.html.erb +40 -0
- data/lib/flash_messages/controller_helpers.rb +62 -0
- data/lib/flash_messages/engine.rb +23 -0
- data/lib/flash_messages/generators/flash_messages/install_generator.rb +54 -0
- data/lib/flash_messages/version.rb +3 -0
- data/lib/flash_messages/view_helper.rb +53 -0
- data/lib/flash_messages.rb +6 -0
- metadata +86 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d28f641343994d9b9114b83ebd4782493216536230e6e15512e5688df5bcc06e
|
|
4
|
+
data.tar.gz: 3986adde7e8466a33f001fff01daf031360512ab4a1bf409010d3680690684f2
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e37418fc2546f3808216223a9f69a9b09d9adef28cdfbd24ea1626ff546d70462e06d7a480cb7223e9cd4da4ea656d324d31d12684eb18b382aec9b64b92cfc6
|
|
7
|
+
data.tar.gz: 2e058e6f4fa76964c78692e8372ed0395ea1ec7fae594df1572f147cecb0ddf51cff3002d7856dbd2bb57e51346fb3ad7d7042acac525c33d20acfd238e73438
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2024-12-15
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release
|
|
12
|
+
- Flash message component with 4 types (success, error, warning, info)
|
|
13
|
+
- Auto-dismiss functionality with configurable duration
|
|
14
|
+
- Pause on hover feature
|
|
15
|
+
- Multiple message stacking
|
|
16
|
+
- Stimulus controller for animations
|
|
17
|
+
- Turbo Streams support
|
|
18
|
+
- Tailwind CSS styling
|
|
19
|
+
- Controller helper methods:
|
|
20
|
+
- `flash_and_redirect`
|
|
21
|
+
- `flash_and_render`
|
|
22
|
+
- `flash_turbo_stream`
|
|
23
|
+
- `flash_response`
|
|
24
|
+
- View helper for color and icon configuration
|
|
25
|
+
- Rails generator for easy installation
|
|
26
|
+
- Comprehensive documentation
|
|
27
|
+
- Example controllers
|
|
28
|
+
|
|
29
|
+
### Features
|
|
30
|
+
- Responsive design
|
|
31
|
+
- Customizable widths (per message or globally)
|
|
32
|
+
- Customizable auto-dismiss duration
|
|
33
|
+
- Clean, maintainable code
|
|
34
|
+
- Zero external dependencies beyond Rails
|
|
35
|
+
|
|
36
|
+
### Requirements
|
|
37
|
+
- Ruby on Rails 8.0+
|
|
38
|
+
- Tailwind CSS
|
|
39
|
+
- Stimulus (included in Rails 8)
|
|
40
|
+
- Turbo (included in Rails 8)
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 [Your Name]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Flash Messages
|
|
2
|
+
|
|
3
|
+
Beautiful, animated flash messages for Ruby on Rails 8 with Stimulus and Tailwind CSS.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✨ **4 Message Types** - Success, Error, Warning, Info with color-coding
|
|
8
|
+
- ⚡ **Auto-dismiss** - Configurable fade-out (default: 5 seconds)
|
|
9
|
+
- 🎯 **Pause on Hover** - Messages pause when you hover over them
|
|
10
|
+
- 📚 **Multiple Messages** - Stack beautifully with proper spacing
|
|
11
|
+
- 🔄 **Turbo Streams Ready** - Full support for AJAX updates
|
|
12
|
+
- 💅 **Tailwind Styled** - Beautiful, responsive design out of the box
|
|
13
|
+
- 🎮 **Stimulus Powered** - Clean, modern JavaScript
|
|
14
|
+
- 🛠️ **Helper Methods** - Simplify your controller code
|
|
15
|
+
|
|
16
|
+
## Requirements
|
|
17
|
+
|
|
18
|
+
- Ruby on Rails 8.0+
|
|
19
|
+
- Tailwind CSS
|
|
20
|
+
- Stimulus (included in Rails 8)
|
|
21
|
+
- Turbo (included in Rails 8)
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
Add this line to your application's Gemfile:
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
gem 'flash_messages'
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
And then execute:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bundle install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Run the installer:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
rails generate flash_messages:install
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Add to your layout (`app/views/layouts/application.html.erb`):
|
|
44
|
+
|
|
45
|
+
```erb
|
|
46
|
+
<body>
|
|
47
|
+
<%= render 'flash_messages/flash' %>
|
|
48
|
+
|
|
49
|
+
<%= yield %>
|
|
50
|
+
</body>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
### Basic Flash Messages
|
|
56
|
+
|
|
57
|
+
```ruby
|
|
58
|
+
class PostsController < ApplicationController
|
|
59
|
+
def create
|
|
60
|
+
@post = Post.new(post_params)
|
|
61
|
+
|
|
62
|
+
if @post.save
|
|
63
|
+
flash[:success] = "Post created successfully!"
|
|
64
|
+
redirect_to @post
|
|
65
|
+
else
|
|
66
|
+
flash[:error] = "Unable to create post."
|
|
67
|
+
render :new
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Using Helper Methods (Recommended)
|
|
74
|
+
|
|
75
|
+
The gem automatically adds helper methods to your controllers:
|
|
76
|
+
|
|
77
|
+
```ruby
|
|
78
|
+
class PostsController < ApplicationController
|
|
79
|
+
def create
|
|
80
|
+
@post = Post.new(post_params)
|
|
81
|
+
|
|
82
|
+
if @post.save
|
|
83
|
+
flash_and_redirect(:success, "Post created!", @post)
|
|
84
|
+
else
|
|
85
|
+
flash_and_render(:error, "Unable to create post.", :new)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Custom Width
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
# Small message (384px)
|
|
95
|
+
flash_and_redirect(:success, "Saved!", @post, width: 384)
|
|
96
|
+
|
|
97
|
+
# Large message (672px)
|
|
98
|
+
flash_and_render(:error, "Please fix these errors...", :new, width: 672)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### With Turbo Streams
|
|
102
|
+
|
|
103
|
+
```ruby
|
|
104
|
+
def update
|
|
105
|
+
if @post.update(post_params)
|
|
106
|
+
respond_to do |format|
|
|
107
|
+
format.html { flash_and_redirect(:success, "Updated!", @post) }
|
|
108
|
+
format.turbo_stream do
|
|
109
|
+
render turbo_stream: [
|
|
110
|
+
turbo_stream.replace("post_#{@post.id}", partial: "posts/post", locals: { post: @post }),
|
|
111
|
+
flash_turbo_stream(:success, "Updated!", width: 384)
|
|
112
|
+
]
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
else
|
|
116
|
+
flash_and_render(:error, "Unable to update.", :edit)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Complete CRUD Pattern
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
def create
|
|
125
|
+
@post = Post.new(post_params)
|
|
126
|
+
|
|
127
|
+
flash_response(
|
|
128
|
+
success: @post.save,
|
|
129
|
+
success_message: "Post created!",
|
|
130
|
+
error_message: "Unable to create post.",
|
|
131
|
+
success_path: @post,
|
|
132
|
+
error_template: :new,
|
|
133
|
+
turbo_success: -> {
|
|
134
|
+
render turbo_stream: [
|
|
135
|
+
turbo_stream.prepend("posts", partial: "posts/post", locals: { post: @post }),
|
|
136
|
+
flash_turbo_stream(:success, "Created!", width: 384)
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
end
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Helper Methods
|
|
144
|
+
|
|
145
|
+
### `flash_and_redirect(type, message, path, width: 448)`
|
|
146
|
+
|
|
147
|
+
Redirects with a flash message.
|
|
148
|
+
|
|
149
|
+
```ruby
|
|
150
|
+
flash_and_redirect(:success, "Post created!", @post)
|
|
151
|
+
flash_and_redirect(:error, "Not found", root_path, width: 672)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `flash_and_render(type, message, template, width: 448, status: :unprocessable_entity)`
|
|
155
|
+
|
|
156
|
+
Renders a template with a flash message.
|
|
157
|
+
|
|
158
|
+
```ruby
|
|
159
|
+
flash_and_render(:error, "Fix the errors", :new)
|
|
160
|
+
flash_and_render(:warning, "Check your input", :edit, width: 512)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### `flash_turbo_stream(type, message, width: 448, duration: 5000)`
|
|
164
|
+
|
|
165
|
+
Returns a turbo stream for appending a flash message.
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
render turbo_stream: [
|
|
169
|
+
turbo_stream.update("post", partial: "post"),
|
|
170
|
+
flash_turbo_stream(:success, "Done!", width: 384)
|
|
171
|
+
]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `flash_response(options)`
|
|
175
|
+
|
|
176
|
+
Handles complete CRUD response pattern.
|
|
177
|
+
|
|
178
|
+
**Options:**
|
|
179
|
+
- `success:` (required) - Boolean indicating success/failure
|
|
180
|
+
- `success_message:` (required) - Message to show on success
|
|
181
|
+
- `error_message:` (required) - Message to show on error
|
|
182
|
+
- `success_path:` - Where to redirect on success (HTML)
|
|
183
|
+
- `error_template:` - Template to render on error (HTML)
|
|
184
|
+
- `turbo_success:` - Lambda for Turbo Stream success response
|
|
185
|
+
- `turbo_error:` - Lambda for Turbo Stream error response
|
|
186
|
+
- `success_width:` - Width for success message (default: 384)
|
|
187
|
+
- `error_width:` - Width for error message (default: 672)
|
|
188
|
+
|
|
189
|
+
## Message Types
|
|
190
|
+
|
|
191
|
+
| Type | Alias | Color | Icon | Use Case |
|
|
192
|
+
|------|-------|-------|------|----------|
|
|
193
|
+
| `:success` | `:notice` | Green | ✓ | Successful actions |
|
|
194
|
+
| `:error` | `:danger` | Red | ✗ | Errors, failures |
|
|
195
|
+
| `:warning` | `:alert` | Yellow | ⚠ | Warnings, cautions |
|
|
196
|
+
| `:info` | - | Blue | ⓘ | Information |
|
|
197
|
+
|
|
198
|
+
## Customization
|
|
199
|
+
|
|
200
|
+
### Change Default Width
|
|
201
|
+
|
|
202
|
+
Edit the view partial to change the default width:
|
|
203
|
+
|
|
204
|
+
```ruby
|
|
205
|
+
# In your app, create:
|
|
206
|
+
# app/views/flash_messages/_flash.html.erb
|
|
207
|
+
|
|
208
|
+
# Copy from gem and modify:
|
|
209
|
+
default_width = 512 # Instead of 448
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Change Auto-Dismiss Duration
|
|
213
|
+
|
|
214
|
+
Override the Stimulus controller:
|
|
215
|
+
|
|
216
|
+
```javascript
|
|
217
|
+
// app/javascript/controllers/flash_controller.js
|
|
218
|
+
|
|
219
|
+
import FlashController from "flash_messages/controllers/flash_controller"
|
|
220
|
+
|
|
221
|
+
export default class extends FlashController {
|
|
222
|
+
static values = {
|
|
223
|
+
duration: { type: Number, default: 7000 } // 7 seconds
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Change Colors
|
|
229
|
+
|
|
230
|
+
Create your own helper to override colors:
|
|
231
|
+
|
|
232
|
+
```ruby
|
|
233
|
+
# app/helpers/application_helper.rb
|
|
234
|
+
|
|
235
|
+
module ApplicationHelper
|
|
236
|
+
def flash_message_config(type)
|
|
237
|
+
# Your custom colors here
|
|
238
|
+
super # Call the gem's method for types you don't override
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Width Reference
|
|
244
|
+
|
|
245
|
+
| Width (px) | Tailwind | Best For |
|
|
246
|
+
|------------|----------|----------|
|
|
247
|
+
| 320 | max-w-xs | Very short messages |
|
|
248
|
+
| 384 | max-w-sm | Short messages |
|
|
249
|
+
| 448 | max-w-md | **Default** - Balanced |
|
|
250
|
+
| 512 | max-w-lg | Longer messages |
|
|
251
|
+
| 672 | max-w-2xl | Detailed messages |
|
|
252
|
+
| 800+ | Custom | Very long content |
|
|
253
|
+
|
|
254
|
+
## Examples
|
|
255
|
+
|
|
256
|
+
See the `/examples` directory in the gem for complete controller examples.
|
|
257
|
+
|
|
258
|
+
## Development
|
|
259
|
+
|
|
260
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
|
|
261
|
+
|
|
262
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
263
|
+
|
|
264
|
+
## Contributing
|
|
265
|
+
|
|
266
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/yourusername/flash_messages.
|
|
267
|
+
|
|
268
|
+
## License
|
|
269
|
+
|
|
270
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
|
2
|
+
|
|
3
|
+
export default class extends Controller {
|
|
4
|
+
static values = {
|
|
5
|
+
duration: { type: Number, default: 5000 },
|
|
6
|
+
removeDelay: { type: Number, default: 500 } // Time for fade-out animation
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
connect() {
|
|
10
|
+
// Fade in animation
|
|
11
|
+
this.element.classList.remove('opacity-0', 'translate-y-[-1rem]')
|
|
12
|
+
this.element.classList.add('opacity-100', 'translate-y-0')
|
|
13
|
+
|
|
14
|
+
// Auto-dismiss after duration
|
|
15
|
+
this.timeoutId = setTimeout(() => {
|
|
16
|
+
this.close()
|
|
17
|
+
}, this.durationValue)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
disconnect() {
|
|
21
|
+
if (this.timeoutId) {
|
|
22
|
+
clearTimeout(this.timeoutId)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
close() {
|
|
27
|
+
// Clear timeout to prevent double-execution
|
|
28
|
+
if (this.timeoutId) {
|
|
29
|
+
clearTimeout(this.timeoutId)
|
|
30
|
+
this.timeoutId = null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Fade out animation
|
|
34
|
+
this.element.classList.remove('opacity-100', 'translate-y-0')
|
|
35
|
+
this.element.classList.add('opacity-0', 'translate-y-[-1rem]')
|
|
36
|
+
|
|
37
|
+
// Remove element after animation completes
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
this.element.remove()
|
|
40
|
+
}, this.removeDelayValue)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Pause auto-dismiss on hover
|
|
44
|
+
pause() {
|
|
45
|
+
if (this.timeoutId) {
|
|
46
|
+
clearTimeout(this.timeoutId)
|
|
47
|
+
this.timeoutId = null
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Resume auto-dismiss on mouse leave
|
|
52
|
+
resume() {
|
|
53
|
+
if (!this.timeoutId) {
|
|
54
|
+
this.timeoutId = setTimeout(() => {
|
|
55
|
+
this.close()
|
|
56
|
+
}, this.durationValue)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<%
|
|
2
|
+
# Default width for all flash messages (in pixels)
|
|
3
|
+
# Change this value to adjust the default width for plain HTML flash messages
|
|
4
|
+
default_width = 448 # 448px = max-w-md
|
|
5
|
+
%>
|
|
6
|
+
|
|
7
|
+
<div id="flash-messages" class="fixed top-4 left-1/2 transform -translate-x-1/2 z-50 w-full px-4 space-y-2">
|
|
8
|
+
<% flash.each do |type, message| %>
|
|
9
|
+
<%
|
|
10
|
+
# Handle both string messages and hash messages with options
|
|
11
|
+
if message.is_a?(Hash)
|
|
12
|
+
message_text = message[:message] || message["message"]
|
|
13
|
+
width_px = message[:width] || message["width"] || default_width
|
|
14
|
+
else
|
|
15
|
+
message_text = message
|
|
16
|
+
width_px = default_width
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Configure colors and icons based on flash type
|
|
20
|
+
config = case type.to_sym
|
|
21
|
+
when :notice, :success
|
|
22
|
+
{
|
|
23
|
+
bg: 'bg-green-50',
|
|
24
|
+
border: 'border-green-200',
|
|
25
|
+
text: 'text-green-800',
|
|
26
|
+
icon_bg: 'bg-green-100',
|
|
27
|
+
icon_color: 'text-green-600',
|
|
28
|
+
icon_path: 'M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
|
|
29
|
+
}
|
|
30
|
+
when :alert, :warning
|
|
31
|
+
{
|
|
32
|
+
bg: 'bg-yellow-50',
|
|
33
|
+
border: 'border-yellow-200',
|
|
34
|
+
text: 'text-yellow-800',
|
|
35
|
+
icon_bg: 'bg-yellow-100',
|
|
36
|
+
icon_color: 'text-yellow-600',
|
|
37
|
+
icon_path: 'M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z'
|
|
38
|
+
}
|
|
39
|
+
when :error, :danger
|
|
40
|
+
{
|
|
41
|
+
bg: 'bg-red-50',
|
|
42
|
+
border: 'border-red-200',
|
|
43
|
+
text: 'text-red-800',
|
|
44
|
+
icon_bg: 'bg-red-100',
|
|
45
|
+
icon_color: 'text-red-600',
|
|
46
|
+
icon_path: 'M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
|
|
47
|
+
}
|
|
48
|
+
else # info or default
|
|
49
|
+
{
|
|
50
|
+
bg: 'bg-blue-50',
|
|
51
|
+
border: 'border-blue-200',
|
|
52
|
+
text: 'text-blue-800',
|
|
53
|
+
icon_bg: 'bg-blue-100',
|
|
54
|
+
icon_color: 'text-blue-600',
|
|
55
|
+
icon_path: 'M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z'
|
|
56
|
+
}
|
|
57
|
+
end
|
|
58
|
+
%>
|
|
59
|
+
|
|
60
|
+
<div
|
|
61
|
+
data-controller="flash"
|
|
62
|
+
data-flash-duration-value="5000"
|
|
63
|
+
data-action="mouseenter->flash#pause mouseleave->flash#resume"
|
|
64
|
+
style="max-width: <%= width_px %>px; margin: 0 auto;"
|
|
65
|
+
class="<%= config[:bg] %> <%= config[:border] %> <%= config[:text] %> border rounded-lg shadow-lg p-4 flex items-start gap-3 opacity-0 translate-y-[-1rem] transition-all duration-500 ease-out"
|
|
66
|
+
>
|
|
67
|
+
<!-- Icon -->
|
|
68
|
+
<div class="<%= config[:icon_bg] %> rounded-lg p-2 flex-shrink-0">
|
|
69
|
+
<svg class="w-5 h-5 <%= config[:icon_color] %>" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
70
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="<%= config[:icon_path] %>"/>
|
|
71
|
+
</svg>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<!-- Message -->
|
|
75
|
+
<div class="flex-1 pt-0.5">
|
|
76
|
+
<p class="text-sm font-medium"><%= message_text %></p>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<!-- Close button -->
|
|
80
|
+
<button
|
|
81
|
+
data-action="click->flash#close"
|
|
82
|
+
class="flex-shrink-0 <%= config[:text] %> hover:opacity-70 transition-opacity"
|
|
83
|
+
type="button"
|
|
84
|
+
>
|
|
85
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
86
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
87
|
+
</svg>
|
|
88
|
+
</button>
|
|
89
|
+
</div>
|
|
90
|
+
<% end %>
|
|
91
|
+
</div>
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<%
|
|
2
|
+
# Default values
|
|
3
|
+
type ||= :info
|
|
4
|
+
message ||= ""
|
|
5
|
+
duration ||= 5000
|
|
6
|
+
width_px ||= 448 # Default 448px (equivalent to max-w-md)
|
|
7
|
+
|
|
8
|
+
config = flash_message_config(type)
|
|
9
|
+
%>
|
|
10
|
+
|
|
11
|
+
<div
|
|
12
|
+
data-controller="flash"
|
|
13
|
+
data-flash-duration-value="<%= duration %>"
|
|
14
|
+
data-action="mouseenter->flash#pause mouseleave->flash#resume"
|
|
15
|
+
style="max-width: <%= width_px %>px; margin: 0 auto;"
|
|
16
|
+
class="<%= config[:bg] %> <%= config[:border] %> <%= config[:text] %> border rounded-lg shadow-lg p-4 flex items-start gap-3 opacity-0 translate-y-[-1rem] transition-all duration-500 ease-out"
|
|
17
|
+
>
|
|
18
|
+
<!-- Icon -->
|
|
19
|
+
<div class="<%= config[:icon_bg] %> rounded-lg p-2 flex-shrink-0">
|
|
20
|
+
<svg class="w-5 h-5 <%= config[:icon_color] %>" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
21
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="<%= config[:icon_path] %>"/>
|
|
22
|
+
</svg>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- Message -->
|
|
26
|
+
<div class="flex-1 pt-0.5">
|
|
27
|
+
<p class="text-sm font-medium"><%= message %></p>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<!-- Close button -->
|
|
31
|
+
<button
|
|
32
|
+
data-action="click->flash#close"
|
|
33
|
+
class="flex-shrink-0 <%= config[:text] %> hover:opacity-70 transition-opacity"
|
|
34
|
+
type="button"
|
|
35
|
+
>
|
|
36
|
+
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
37
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
|
|
38
|
+
</svg>
|
|
39
|
+
</button>
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module FlashMessages
|
|
2
|
+
module ControllerHelpers
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
def flash_and_redirect(type, message, path, width: 448)
|
|
6
|
+
flash[type] = { message: message, width: width }
|
|
7
|
+
redirect_to path
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def flash_and_render(type, message, template, width: 448, status: :unprocessable_entity)
|
|
11
|
+
flash.now[type] = { message: message, width: width }
|
|
12
|
+
render template, status: status
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def flash_turbo_stream(type, message, width: 448, duration: 5000)
|
|
16
|
+
turbo_stream.append(
|
|
17
|
+
"flash-messages",
|
|
18
|
+
partial: "flash_messages/flash_message",
|
|
19
|
+
locals: {
|
|
20
|
+
type: type,
|
|
21
|
+
message: message,
|
|
22
|
+
width_px: width,
|
|
23
|
+
duration: duration
|
|
24
|
+
}
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def flash_response(success:, success_message:, error_message:, success_path: nil, error_template: nil, turbo_success: nil, turbo_error: nil, success_width: 384, error_width: 672)
|
|
29
|
+
if success
|
|
30
|
+
respond_to do |format|
|
|
31
|
+
format.html do
|
|
32
|
+
flash[:success] = { message: success_message, width: success_width }
|
|
33
|
+
redirect_to success_path if success_path
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
format.turbo_stream do
|
|
37
|
+
if turbo_success
|
|
38
|
+
turbo_success.call
|
|
39
|
+
else
|
|
40
|
+
render turbo_stream: flash_turbo_stream(:success, success_message, width: success_width)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
respond_to do |format|
|
|
46
|
+
format.html do
|
|
47
|
+
flash.now[:error] = { message: error_message, width: error_width }
|
|
48
|
+
render error_template, status: :unprocessable_entity if error_template
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
format.turbo_stream do
|
|
52
|
+
if turbo_error
|
|
53
|
+
turbo_error.call
|
|
54
|
+
else
|
|
55
|
+
render turbo_stream: flash_turbo_stream(:error, error_message, width: error_width)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module FlashMessages
|
|
2
|
+
class Engine < ::Rails::Engine
|
|
3
|
+
isolate_namespace FlashMessages
|
|
4
|
+
|
|
5
|
+
config.generators do |g|
|
|
6
|
+
g.test_framework :rspec
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Automatically add the concern to ApplicationController
|
|
10
|
+
initializer "flash_messages.load_controller_concern" do
|
|
11
|
+
ActiveSupport.on_load(:action_controller_base) do
|
|
12
|
+
include FlashMessages::ControllerHelpers
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Ensure helpers are available
|
|
17
|
+
initializer "flash_messages.load_helpers" do
|
|
18
|
+
ActiveSupport.on_load(:action_view) do
|
|
19
|
+
include FlashMessages::ViewHelper
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'rails/generators'
|
|
2
|
+
|
|
3
|
+
module FlashMessages
|
|
4
|
+
module Generators
|
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
|
6
|
+
source_root File.expand_path('../templates', __FILE__)
|
|
7
|
+
|
|
8
|
+
desc "Install Flash Messages component"
|
|
9
|
+
|
|
10
|
+
def copy_javascript_controller
|
|
11
|
+
say "Installing Stimulus controller...", :green
|
|
12
|
+
copy_file "../../../../app/assets/javascripts/flash_messages/controllers/flash_controller.js",
|
|
13
|
+
"app/javascript/controllers/flash_controller.js"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def show_readme
|
|
17
|
+
readme "README" if behavior == :invoke
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
|
|
22
|
+
def readme(path)
|
|
23
|
+
say "\n" + "="*70, :green
|
|
24
|
+
say "Flash Messages Installation Complete! 🎉", :green
|
|
25
|
+
say "="*70, :green
|
|
26
|
+
|
|
27
|
+
say "\n✅ Installed:", :cyan
|
|
28
|
+
say " • Stimulus controller (app/javascript/controllers/flash_controller.js)"
|
|
29
|
+
say " • View helpers (automatically loaded)"
|
|
30
|
+
say " • Controller helpers (automatically loaded)"
|
|
31
|
+
|
|
32
|
+
say "\n🚀 Next Step:", :cyan
|
|
33
|
+
say " Add this line to your layout (app/views/layouts/application.html.erb):"
|
|
34
|
+
say " Right after the <body> tag:\n", :yellow
|
|
35
|
+
say " <%= render 'flash_messages/flash' %>\n", :cyan
|
|
36
|
+
|
|
37
|
+
say "\n📖 Usage Examples:", :cyan
|
|
38
|
+
say " # Basic"
|
|
39
|
+
say " flash[:success] = 'Post created!'"
|
|
40
|
+
say " redirect_to @post\n"
|
|
41
|
+
|
|
42
|
+
say " # Using helpers"
|
|
43
|
+
say " flash_and_redirect(:success, 'Saved!', @post)"
|
|
44
|
+
say " flash_and_render(:error, 'Failed', :new)\n"
|
|
45
|
+
|
|
46
|
+
say " # With Turbo Streams"
|
|
47
|
+
say " flash_turbo_stream(:success, 'Updated!', width: 384)\n"
|
|
48
|
+
|
|
49
|
+
say "📚 Documentation: https://github.com/yourusername/flash_messages", :cyan
|
|
50
|
+
say "="*70 + "\n", :green
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module FlashMessages
|
|
2
|
+
module ViewHelper
|
|
3
|
+
# Generates a flash message that can be used in Turbo Stream responses
|
|
4
|
+
#
|
|
5
|
+
# Usage in controller:
|
|
6
|
+
# respond_to do |format|
|
|
7
|
+
# format.turbo_stream do
|
|
8
|
+
# render turbo_stream: turbo_stream.append("flash-messages", partial: "shared/flash_message",
|
|
9
|
+
# locals: { type: :success, message: "Record saved successfully!" })
|
|
10
|
+
# end
|
|
11
|
+
# end
|
|
12
|
+
def flash_message_config(type)
|
|
13
|
+
case type.to_sym
|
|
14
|
+
when :notice, :success
|
|
15
|
+
{
|
|
16
|
+
bg: 'bg-green-50',
|
|
17
|
+
border: 'border-green-200',
|
|
18
|
+
text: 'text-green-800',
|
|
19
|
+
icon_bg: 'bg-green-100',
|
|
20
|
+
icon_color: 'text-green-600',
|
|
21
|
+
icon_path: 'M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
|
|
22
|
+
}
|
|
23
|
+
when :alert, :warning
|
|
24
|
+
{
|
|
25
|
+
bg: 'bg-yellow-50',
|
|
26
|
+
border: 'border-yellow-200',
|
|
27
|
+
text: 'text-yellow-800',
|
|
28
|
+
icon_bg: 'bg-yellow-100',
|
|
29
|
+
icon_color: 'text-yellow-600',
|
|
30
|
+
icon_path: 'M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z'
|
|
31
|
+
}
|
|
32
|
+
when :error, :danger
|
|
33
|
+
{
|
|
34
|
+
bg: 'bg-red-50',
|
|
35
|
+
border: 'border-red-200',
|
|
36
|
+
text: 'text-red-800',
|
|
37
|
+
icon_bg: 'bg-red-100',
|
|
38
|
+
icon_color: 'text-red-600',
|
|
39
|
+
icon_path: 'M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z'
|
|
40
|
+
}
|
|
41
|
+
else # info or default
|
|
42
|
+
{
|
|
43
|
+
bg: 'bg-blue-50',
|
|
44
|
+
border: 'border-blue-200',
|
|
45
|
+
text: 'text-blue-800',
|
|
46
|
+
icon_bg: 'bg-blue-100',
|
|
47
|
+
icon_color: 'text-blue-600',
|
|
48
|
+
icon_path: 'M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z'
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: flash_messages_rails
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Virgo STYX
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: rails
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: 8.0.0
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: 8.0.0
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: rspec-rails
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '6.0'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '6.0'
|
|
40
|
+
description: A complete flash message system for Rails 8 with Stimulus, Turbo Streams
|
|
41
|
+
support, and Tailwind CSS styling. Features auto-dismiss, pause on hover, multiple
|
|
42
|
+
message types, and clean helper methods.
|
|
43
|
+
email:
|
|
44
|
+
- virgostyx@gmail.com
|
|
45
|
+
executables: []
|
|
46
|
+
extensions: []
|
|
47
|
+
extra_rdoc_files: []
|
|
48
|
+
files:
|
|
49
|
+
- CHANGELOG.md
|
|
50
|
+
- MIT-LICENSE
|
|
51
|
+
- README.md
|
|
52
|
+
- Rakefile
|
|
53
|
+
- app/assets/javascripts/flash_messages/controllers/flash_controller.js
|
|
54
|
+
- app/views/flash_messages/_flash.html.erb
|
|
55
|
+
- app/views/flash_messages/_flash_message.html.erb
|
|
56
|
+
- lib/flash_messages.rb
|
|
57
|
+
- lib/flash_messages/controller_helpers.rb
|
|
58
|
+
- lib/flash_messages/engine.rb
|
|
59
|
+
- lib/flash_messages/generators/flash_messages/install_generator.rb
|
|
60
|
+
- lib/flash_messages/version.rb
|
|
61
|
+
- lib/flash_messages/view_helper.rb
|
|
62
|
+
homepage: https://github.com/virgostyx/flash_messages_rails
|
|
63
|
+
licenses:
|
|
64
|
+
- MIT
|
|
65
|
+
metadata:
|
|
66
|
+
homepage_uri: https://github.com/virgostyx/flash_messages_rails
|
|
67
|
+
source_code_uri: https://github.com/virgostyx/flash_messages_rails
|
|
68
|
+
changelog_uri: https://github.com/virgostyx/flash_messages_rails/blob/main/CHANGELOG.md
|
|
69
|
+
rdoc_options: []
|
|
70
|
+
require_paths:
|
|
71
|
+
- lib
|
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
|
+
requirements:
|
|
74
|
+
- - ">="
|
|
75
|
+
- !ruby/object:Gem::Version
|
|
76
|
+
version: '0'
|
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
requirements: []
|
|
83
|
+
rubygems_version: 3.6.9
|
|
84
|
+
specification_version: 4
|
|
85
|
+
summary: Beautiful animated flash messages for Rails 8
|
|
86
|
+
test_files: []
|