rails_tipjar 1.0.0 → 1.0.3
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 +4 -4
- data/README.md +19 -90
- data/app/helpers/tipjar_helper.rb +56 -67
- data/blog_post.md +28 -0
- data/lib/rails_tipjar/version.rb +1 -1
- data/lib/rails_tipjar.rb +0 -14
- data/rails_tipjar-1.0.2.gem +0 -0
- metadata +3 -4
- data/lib/generators/tipjar/install/install_generator.rb +0 -103
- data/lib/generators/tipjar/install/templates/tipjar.rb +0 -64
- data/lib/rails_tipjar/configuration.rb +0 -171
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2cf65e5b46d3527b6f4d02f39874a13b9ec8b3636191cdbde367a0f847c8f3d
|
4
|
+
data.tar.gz: 7e5b5761de2e05caba0ca882ae97eea676a7654aac6491e71af6614810b922af
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29ba3164a38e5c0928dea36950f9d77d37890f7bd376e1a0f747e1cdb6323d73fea0deac64b5121905ae5d8b0fce00f645a0b41566238a3c46f83a5736f13316
|
7
|
+
data.tar.gz: 7457b713ee24db04b984d86ec6f92be8a89ec6198b28f8777116be68cef3d99dd40c51715a19d3273f6aafa5710410e1ba6fcfb604446573d78534f131808442
|
data/README.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
A reusable, customizable tip jar feature for Rails applications. Add a beautiful tip jar to any Rails app with just a few lines of code! Works with any payment provider - Stripe, PayPal, Buy Me a Coffee, Ko-fi, or any custom payment link.
|
4
4
|
|
5
|
+
Hat example:
|
6
|
+
|Standard|Hovered|
|
7
|
+
------------------
|
8
|
+
|<img width="63" height="66" alt="Screenshot 2025-09-12 at 10 22 51 AM" src="https://github.com/user-attachments/assets/56ebad46-ce77-4a26-8d93-525ecea8ef6a" />|<img width="137" height="72" alt="Screenshot 2025-09-12 at 10 20 50 AM" src="https://github.com/user-attachments/assets/beebe18e-a5bb-486b-835b-0caf18813781" />|
|
9
|
+
|
5
10
|
## Features
|
6
11
|
|
7
12
|
- 🎨 Customizable floating button with multiple icon options (coffee, heart, star, dollar, jar)
|
@@ -11,7 +16,6 @@ A reusable, customizable tip jar feature for Rails applications. Add a beautiful
|
|
11
16
|
- 📱 Fully responsive design with inline styles (no CSS dependencies)
|
12
17
|
- 🎯 Multiple positioning options (bottom-right, bottom-left, top-right, top-left)
|
13
18
|
- 🌙 Light/Dark theme support for modal
|
14
|
-
- 📊 Built-in analytics tracking
|
15
19
|
- ⚡ Stimulus.js powered interactions
|
16
20
|
- 🔧 Zero configuration to get started
|
17
21
|
- 🚀 Simple mode: Direct link without modal
|
@@ -34,21 +38,12 @@ Add this gem to your Rails application's Gemfile:
|
|
34
38
|
# From RubyGems
|
35
39
|
gem 'rails_tipjar'
|
36
40
|
|
37
|
-
# Or from GitHub for latest features
|
38
|
-
gem 'rails_tipjar', git: 'https://github.com/justinpaulson/rails_tipjar'
|
39
|
-
```
|
40
|
-
|
41
41
|
Then execute:
|
42
42
|
|
43
43
|
```bash
|
44
44
|
bundle install
|
45
45
|
```
|
46
46
|
|
47
|
-
Optionally run the generator (only needed for backwards compatibility with v0.3.0 and earlier):
|
48
|
-
```bash
|
49
|
-
rails generate tipjar:install
|
50
|
-
```
|
51
|
-
|
52
47
|
## Quick Start
|
53
48
|
|
54
49
|
### 1. Create Payment Links
|
@@ -73,13 +68,13 @@ No configuration file needed! Simply use the helper in your views with all optio
|
|
73
68
|
Add directly to any view:
|
74
69
|
|
75
70
|
```erb
|
76
|
-
<!-- Basic usage with default
|
71
|
+
<!-- Basic usage with default jar icon -->
|
77
72
|
<%= tip_jar payment_link: 'https://your.payment.link' %>
|
78
73
|
|
79
74
|
<!-- With all customization options -->
|
80
75
|
<%= tip_jar payment_link: 'https://your.payment.link',
|
81
76
|
message: 'Support This Project', # Text shown on hover
|
82
|
-
icon: :heart, # :coffee, :heart, :star, :dollar, :jar, or custom SVG
|
77
|
+
icon: :heart, # :coffee, :heart, :star, :dollar, :jar, :hat, or custom SVG
|
83
78
|
position: :bottom_right, # :bottom_right, :bottom_left, :top_right, :top_left
|
84
79
|
color: '#8b5cf6', # Button background color
|
85
80
|
text_color: '#ffffff', # Button text color
|
@@ -104,8 +99,7 @@ Add directly to any view:
|
|
104
99
|
{ amount: 10, label: '$10', default: true },
|
105
100
|
{ amount: 25, label: '$25', default: false }
|
106
101
|
],
|
107
|
-
theme: :light
|
108
|
-
analytics_enabled: true %>
|
102
|
+
theme: :light %> # :light, :dark, :auto
|
109
103
|
|
110
104
|
<!-- Force modal mode with single link -->
|
111
105
|
<%= tip_jar payment_link: 'https://your.payment.link',
|
@@ -125,7 +119,7 @@ Add to `app/views/layouts/application.html.erb`:
|
|
125
119
|
</head>
|
126
120
|
<body>
|
127
121
|
<%= yield %>
|
128
|
-
|
122
|
+
|
129
123
|
<!-- Add floating tip jar button -->
|
130
124
|
<%= tip_jar payment_link: 'https://your.payment.link',
|
131
125
|
position: :bottom_right %>
|
@@ -135,18 +129,14 @@ Add to `app/views/layouts/application.html.erb`:
|
|
135
129
|
|
136
130
|
That's it! You now have a working tip jar on your site.
|
137
131
|
|
138
|
-
## Helper Options
|
139
|
-
|
140
|
-
All configuration is done directly in the view helper:
|
141
|
-
|
142
132
|
### Common Options
|
143
133
|
|
144
134
|
| Option | Description | Default | Values |
|
145
135
|
|--------|-------------|---------|--------|
|
146
136
|
| `payment_link` | Single payment URL for simple mode | - | URL string |
|
147
137
|
| `payment_links` | Hash of payment URLs for modal mode | - | Hash with keys like `:small`, `:medium`, `:large` |
|
148
|
-
| `message` / `button_text` | Text shown on button (on hover) | `"
|
149
|
-
| `icon` | Button icon | `:
|
138
|
+
| `message` / `button_text` | Text shown on button (on hover) | `"Tip Jar"` | String |
|
139
|
+
| `icon` | Button icon | `:jar` | `:coffee`, `:heart`, `:star`, `:dollar`, `:jar`, `:hat`, or custom SVG |
|
150
140
|
| `position` | Button position on screen | `:bottom_right` | `:bottom_right`, `:bottom_left`, `:top_right`, `:top_left` |
|
151
141
|
| `color` | Button background color | `"#3b82f6"` | Hex color string |
|
152
142
|
| `text_color` | Button text color | `"#ffffff"` | Hex color string |
|
@@ -163,7 +153,6 @@ All configuration is done directly in the view helper:
|
|
163
153
|
| `modal_description` | Modal description text | `"Your support helps..."` |
|
164
154
|
| `theme` | Modal color theme | `:light` |
|
165
155
|
| `custom_amounts` | Array of amount options | See example below |
|
166
|
-
| `analytics_enabled` | Track user interactions | `false` |
|
167
156
|
|
168
157
|
### Custom Amounts Example
|
169
158
|
|
@@ -175,36 +164,6 @@ custom_amounts: [
|
|
175
164
|
{ amount: 50, label: "$50", default: false }
|
176
165
|
]
|
177
166
|
|
178
|
-
## Additional Helpers
|
179
|
-
|
180
|
-
### Custom Tip Links
|
181
|
-
|
182
|
-
```erb
|
183
|
-
<!-- Create a custom tip link (requires initializer config) -->
|
184
|
-
<%= tipjar_link "Support this project", amount: :large %>
|
185
|
-
|
186
|
-
<!-- With custom styling -->
|
187
|
-
<%= tipjar_link "Tip $5", amount: :small, class: "btn btn-primary" %>
|
188
|
-
```
|
189
|
-
|
190
|
-
### Modal Only
|
191
|
-
|
192
|
-
```erb
|
193
|
-
<!-- Render just the modal (for custom triggers) -->
|
194
|
-
<%= tipjar_modal %>
|
195
|
-
```
|
196
|
-
|
197
|
-
## Backwards Compatibility
|
198
|
-
|
199
|
-
If you're upgrading from v0.3.0 or earlier and want to keep using the initializer-based configuration:
|
200
|
-
|
201
|
-
```erb
|
202
|
-
<!-- Use the deprecated tipjar_button helper -->
|
203
|
-
<%= tipjar_button %>
|
204
|
-
```
|
205
|
-
|
206
|
-
This requires having a `config/initializers/tipjar.rb` file. We recommend migrating to the new `tip_jar` helper with inline options for easier customization.
|
207
|
-
|
208
167
|
## Styling
|
209
168
|
|
210
169
|
As of v0.2.0, the gem is fully self-contained with inline styles - no external CSS required! The button works out of the box without any app-side styling.
|
@@ -236,20 +195,6 @@ As of v0.2.0, the gem is fully self-contained with inline styles - no external C
|
|
236
195
|
.tipjar-submit-button { }
|
237
196
|
```
|
238
197
|
|
239
|
-
## Analytics
|
240
|
-
|
241
|
-
When `analytics_enabled` is true, the following events are tracked:
|
242
|
-
|
243
|
-
- `tipjar_loaded` - Button loaded on page
|
244
|
-
- `tipjar_modal_opened` - User opened the modal
|
245
|
-
- `tipjar_amount_selected` - User selected an amount
|
246
|
-
- `tipjar_submitted` - User clicked to proceed to payment
|
247
|
-
|
248
|
-
Works automatically with:
|
249
|
-
- Google Analytics 4 (gtag)
|
250
|
-
- Plausible Analytics
|
251
|
-
- Custom events via `document.addEventListener('tipjar:event', ...)`
|
252
|
-
|
253
198
|
## Development
|
254
199
|
|
255
200
|
After checking out the repo:
|
@@ -267,17 +212,21 @@ gem 'rails_tipjar', path: '../path/to/rails_tipjar'
|
|
267
212
|
|
268
213
|
## Icon Options
|
269
214
|
|
270
|
-
The gem includes
|
271
|
-
- `:
|
215
|
+
The gem includes 6 built-in icons:
|
216
|
+
- `:jar` - Tip jar with animated coin (default)
|
217
|
+
- `:coffee` - Coffee cup with steam animation
|
272
218
|
- `:heart` - Heart shape
|
273
219
|
- `:star` - Star
|
274
220
|
- `:dollar` - Dollar sign in circle
|
275
|
-
- `:
|
221
|
+
- `:hat` - Upside-down busker hat with animated coin drop
|
276
222
|
|
277
223
|
You can also provide a custom SVG string for complete customization.
|
278
224
|
|
279
225
|
## Version History
|
280
226
|
|
227
|
+
- **v1.0.3** - Removed deprecated features: analytics, backwards compatibility helpers (tipjar_button, tipjar_link, tipjar_modal), and generators
|
228
|
+
- **v1.0.2** - Added new `:hat` icon option (busker-style upside-down hat with animated coin drop)
|
229
|
+
- **v1.0.1** - Changed default button text to "Tip Jar" and default icon to jar
|
281
230
|
- **v1.0.0** - Stable release with all configuration in view helper options (no initializer needed!)
|
282
231
|
- **v0.3.0** - Made payment provider agnostic (works with any payment link service)
|
283
232
|
- **v0.2.2** - Added color customization and pulse animation control
|
@@ -285,30 +234,10 @@ You can also provide a custom SVG string for complete customization.
|
|
285
234
|
- **v0.2.0** - Made gem fully self-contained with inline styles
|
286
235
|
- **v0.1.0** - Initial release
|
287
236
|
|
288
|
-
## Troubleshooting
|
289
|
-
|
290
|
-
### Button not appearing
|
291
|
-
|
292
|
-
1. Check that `<%= tipjar_button %>` is in your layout
|
293
|
-
2. Verify Stimulus is working in your app
|
294
|
-
3. Check browser console for JavaScript errors
|
295
|
-
|
296
|
-
### Modal not opening (modal mode only)
|
297
|
-
|
298
|
-
1. Ensure Stimulus controller is registered
|
299
|
-
2. Verify no z-index conflicts with your existing styles
|
300
|
-
3. Make sure `use_modal = true` if using single payment_link
|
301
|
-
|
302
|
-
### Payment links not working
|
303
|
-
|
304
|
-
1. Ensure your payment links are active with your provider
|
305
|
-
2. Check that URLs are correctly configured in initializer
|
306
|
-
3. Test links directly in browser
|
307
|
-
|
308
237
|
## Contributing
|
309
238
|
|
310
239
|
Bug reports and pull requests are welcome on GitHub at https://github.com/justinpaulson/rails_tipjar.
|
311
240
|
|
312
241
|
## License
|
313
242
|
|
314
|
-
The gem is available as open source under the terms of the MIT License.
|
243
|
+
The gem is available as open source under the terms of the MIT License.
|
@@ -6,8 +6,8 @@ module TipjarHelper
|
|
6
6
|
use_modal = options[:use_modal] || false
|
7
7
|
|
8
8
|
# Button configuration
|
9
|
-
message = options[:message] || options[:button_text] || "
|
10
|
-
icon = options[:icon] || :
|
9
|
+
message = options[:message] || options[:button_text] || "Tip Jar"
|
10
|
+
icon = options[:icon] || :jar
|
11
11
|
position = options[:position] || :bottom_right
|
12
12
|
color = options[:color] || "#3b82f6"
|
13
13
|
text_color = options[:text_color] || "#ffffff"
|
@@ -25,7 +25,6 @@ module TipjarHelper
|
|
25
25
|
{ amount: 25, label: "$25", default: false },
|
26
26
|
{ amount: 50, label: "$50", default: false }
|
27
27
|
]
|
28
|
-
analytics_enabled = options[:analytics_enabled] || false
|
29
28
|
|
30
29
|
# Ensure color has # prefix
|
31
30
|
color = "##{color}" unless color.start_with?('#')
|
@@ -45,7 +44,6 @@ module TipjarHelper
|
|
45
44
|
custom_amounts: custom_amounts,
|
46
45
|
button_class: custom_class,
|
47
46
|
z_index: z_index,
|
48
|
-
analytics_enabled: analytics_enabled,
|
49
47
|
color: color,
|
50
48
|
text_color: text_color,
|
51
49
|
pulse: pulse
|
@@ -68,35 +66,6 @@ module TipjarHelper
|
|
68
66
|
raise ArgumentError, "You must provide either :payment_link or :payment_links option to tip_jar helper"
|
69
67
|
end
|
70
68
|
end
|
71
|
-
|
72
|
-
# Deprecated - kept for backwards compatibility
|
73
|
-
def tipjar_button(options = {})
|
74
|
-
config = RailsTipjar.config if defined?(RailsTipjar)
|
75
|
-
|
76
|
-
if config && (config.payment_link || config.payment_links.any?)
|
77
|
-
# Use config from initializer for backwards compatibility
|
78
|
-
tip_jar(
|
79
|
-
payment_link: config.payment_link,
|
80
|
-
payment_links: config.payment_links.any? ? config.payment_links : nil,
|
81
|
-
use_modal: config.use_modal,
|
82
|
-
position: options[:position] || config.position,
|
83
|
-
icon: config.icon,
|
84
|
-
button_text: config.button_text,
|
85
|
-
color: config.color,
|
86
|
-
text_color: config.text_color,
|
87
|
-
pulse: config.pulse,
|
88
|
-
z_index: options[:z_index] || config.z_index,
|
89
|
-
class: options[:class] || config.button_class,
|
90
|
-
modal_title: config.modal_title,
|
91
|
-
modal_description: config.modal_description,
|
92
|
-
custom_amounts: config.custom_amounts,
|
93
|
-
theme: config.theme,
|
94
|
-
analytics_enabled: config.analytics_enabled
|
95
|
-
)
|
96
|
-
else
|
97
|
-
raise ArgumentError, "tipjar_button requires configuration. Use tip_jar helper with options instead."
|
98
|
-
end
|
99
|
-
end
|
100
69
|
|
101
70
|
private
|
102
71
|
|
@@ -149,8 +118,7 @@ module TipjarHelper
|
|
149
118
|
tipjar_theme_value: options[:theme],
|
150
119
|
tipjar_modal_title_value: options[:modal_title],
|
151
120
|
tipjar_modal_description_value: options[:modal_description],
|
152
|
-
tipjar_custom_amounts_value: options[:custom_amounts].to_json
|
153
|
-
tipjar_analytics_enabled_value: options[:analytics_enabled]
|
121
|
+
tipjar_custom_amounts_value: options[:custom_amounts].to_json
|
154
122
|
} do
|
155
123
|
render partial: "tipjar/button", locals: {
|
156
124
|
position: options[:position],
|
@@ -194,38 +162,6 @@ module TipjarHelper
|
|
194
162
|
end
|
195
163
|
end
|
196
164
|
|
197
|
-
def tipjar_link(text = nil, options = {})
|
198
|
-
config = RailsTipjar.config
|
199
|
-
text ||= config.button_text
|
200
|
-
amount = options[:amount] || :medium
|
201
|
-
|
202
|
-
link_url = if amount.is_a?(Symbol)
|
203
|
-
config.payment_links[amount]
|
204
|
-
else
|
205
|
-
config.payment_links[:custom] || config.payment_links[:medium]
|
206
|
-
end
|
207
|
-
|
208
|
-
link_options = {
|
209
|
-
target: "_blank",
|
210
|
-
rel: "noopener",
|
211
|
-
class: "tipjar-link #{options[:class]}",
|
212
|
-
data: {
|
213
|
-
tipjar_amount: amount,
|
214
|
-
tipjar_analytics: config.analytics_enabled
|
215
|
-
}
|
216
|
-
}
|
217
|
-
|
218
|
-
link_to text, link_url, link_options.merge(options.except(:amount, :class))
|
219
|
-
end
|
220
|
-
|
221
|
-
def tipjar_modal(options = {})
|
222
|
-
config = RailsTipjar.config
|
223
|
-
|
224
|
-
render partial: "tipjar/modal", locals: {
|
225
|
-
config: config,
|
226
|
-
options: options
|
227
|
-
}
|
228
|
-
end
|
229
165
|
|
230
166
|
def config_position_classes(position)
|
231
167
|
case position
|
@@ -358,6 +294,59 @@ module TipjarHelper
|
|
358
294
|
<ellipse cx="12" cy="1.5" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
359
295
|
</g>
|
360
296
|
</svg>'
|
297
|
+
when :hat
|
298
|
+
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
299
|
+
<defs>
|
300
|
+
<style>
|
301
|
+
@keyframes hat-coin-drop {
|
302
|
+
0% {
|
303
|
+
transform: translateY(0px);
|
304
|
+
opacity: 0;
|
305
|
+
}
|
306
|
+
10% {
|
307
|
+
opacity: 1;
|
308
|
+
transform: translateY(1px);
|
309
|
+
}
|
310
|
+
50% {
|
311
|
+
transform: translateY(8px);
|
312
|
+
opacity: 1;
|
313
|
+
}
|
314
|
+
80% {
|
315
|
+
transform: translateY(13px);
|
316
|
+
opacity: 1;
|
317
|
+
}
|
318
|
+
100% {
|
319
|
+
transform: translateY(14px);
|
320
|
+
opacity: 0;
|
321
|
+
}
|
322
|
+
}
|
323
|
+
.hat-coin-drop {
|
324
|
+
animation: hat-coin-drop 2.5s ease-in infinite;
|
325
|
+
}
|
326
|
+
</style>
|
327
|
+
</defs>
|
328
|
+
<!-- Upside down fedora/trilby style hat -->
|
329
|
+
<!-- Wide brim at top (since upside down) -->
|
330
|
+
<ellipse cx="12" cy="8" rx="9" ry="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
331
|
+
<!-- Brim edge detail -->
|
332
|
+
<path stroke-linecap="round" stroke-linejoin="round" fill="none" d="M3 8c0 0.5 0 0.5 0 0.5"/>
|
333
|
+
<path stroke-linecap="round" stroke-linejoin="round" fill="none" d="M21 8c0 0.5 0 0.5 0 0.5"/>
|
334
|
+
<!-- Crown of hat (narrower at bottom) -->
|
335
|
+
<path stroke-linecap="round" stroke-linejoin="round" fill="none" d="M6.5 8.5c0 0 0.5 8 1.5 9.5c0.5 0.75 1.5 1 4 1s3.5-0.25 4-1c1-1.5 1.5-9.5 1.5-9.5"/>
|
336
|
+
<!-- Inner opening visible from top -->
|
337
|
+
<ellipse cx="12" cy="9" rx="5.5" ry="1.3" stroke-linecap="round" stroke-linejoin="round" fill="none" opacity="0.4"/>
|
338
|
+
<!-- Hat crease/pinch detail -->
|
339
|
+
<path stroke-linecap="round" stroke-linejoin="round" fill="none" d="M10 10c0 0 0.2 5 0.3 6" opacity="0.3"/>
|
340
|
+
<path stroke-linecap="round" stroke-linejoin="round" fill="none" d="M14 10c0 0 -0.2 5 -0.3 6" opacity="0.3"/>
|
341
|
+
<!-- Coins sitting in the hat -->
|
342
|
+
<ellipse cx="11" cy="16" rx="1.3" ry="0.4" stroke-linecap="round" fill="none"/>
|
343
|
+
<ellipse cx="13" cy="15.5" rx="1.3" ry="0.4" stroke-linecap="round" fill="none"/>
|
344
|
+
<ellipse cx="12" cy="17" rx="1.2" ry="0.35" stroke-linecap="round" fill="none"/>
|
345
|
+
<!-- Animated falling coin -->
|
346
|
+
<g class="hat-coin-drop">
|
347
|
+
<ellipse cx="12" cy="3" rx="1.5" ry="0.5" stroke-linecap="round" fill="none"/>
|
348
|
+
</g>
|
349
|
+
</svg>'
|
361
350
|
else
|
362
351
|
# Allow custom SVG string
|
363
352
|
icon.to_s
|
data/blog_post.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# Content Busking: The Ad-Free Revolution We've Been Waiting For! 💎
|
2
|
+
|
3
|
+
Forget everything you know about monetizing your Rails apps – there's a new sheriff in town, and it's bringing busking into the digital age! Rails Tip Jar is the gem that's about to change how we support our favorite developers and content creators. No more intrusive pop-ups, no more tracking cookies, no more selling your soul (and your users' data) to the ad networks. Just a simple, elegant tip button that lets your grateful users show their appreciation with cold, hard cash!
|
4
|
+
|
5
|
+
I'm all in on this tipping revolution, folks. Every time I see this little tip jar icon on a website, my wallet will be unloading itself. Why? Because I know my money is going directly to the developer who put in the work (assuming they aren't also bombarding me with ads). It's personal, it's direct, and it feels *good*. Plus, let's be real – tipping culture isn't going anywhere in the USA, so we might as well embrace it in the digital realm as well! Plus, [no taxes on tips](https://www.congress.gov/bill/119th-congress/senate-bill/129) right??
|
6
|
+
|
7
|
+
The installation is dead simple – just `gem install rails_tipjar`, add a single line to your view, and boom, you're ready to receive the gratitude of the internet. No lengthy terms of service, no revenue sharing agreements, no minimum payout thresholds. Just pure, unadulterated tips flowing directly to you. Long live the tip jar, long live the independent developer, and long live the ad-free internet we all deserve! 🎉
|
8
|
+
|
9
|
+
## Quick Setup Guide
|
10
|
+
|
11
|
+
Getting started with [Rails Tip Jar](https://rubygems.org/gems/rails_tipjar) takes literally 30 seconds:
|
12
|
+
|
13
|
+
1. Add to your Gemfile: `gem 'rails_tipjar'`
|
14
|
+
2. Run `bundle install`
|
15
|
+
3. Drop this line wherever you want tips: `<%= tip_jar payment_link: 'https://your.payment.link' %>`
|
16
|
+
|
17
|
+
That's it! No configuration files, no initializers, nothing. Want to customize it? Just pass options directly:
|
18
|
+
|
19
|
+
```erb
|
20
|
+
<%= tip_jar payment_link: 'https://your.payment.link',
|
21
|
+
message: 'Support my work', # Custom button text (default: "Tip Jar")
|
22
|
+
icon: :heart, # Choose from 5 icons
|
23
|
+
color: '#8b5cf6', # Custom colors
|
24
|
+
pulse: true, # Pulsing animation
|
25
|
+
position: :bottom_left %> # Position on screen
|
26
|
+
```
|
27
|
+
|
28
|
+
The gem handles all the payment provider integration (works with Stripe, PayPal, Ko-fi, Buy Me a Coffee – literally any payment link), and includes beautiful inline styles so it looks perfect out of the box. No CSS dependencies, no JavaScript frameworks needed – just pure Rails helper goodness.
|
data/lib/rails_tipjar/version.rb
CHANGED
data/lib/rails_tipjar.rb
CHANGED
@@ -1,22 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "rails_tipjar/version"
|
4
|
-
require_relative "rails_tipjar/configuration"
|
5
4
|
require_relative "rails_tipjar/engine" if defined?(Rails)
|
6
5
|
|
7
6
|
module RailsTipjar
|
8
7
|
class Error < StandardError; end
|
9
|
-
|
10
|
-
class << self
|
11
|
-
attr_accessor :configuration
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.configure
|
15
|
-
self.configuration ||= Configuration.new
|
16
|
-
yield(configuration)
|
17
|
-
end
|
18
|
-
|
19
|
-
def self.config
|
20
|
-
self.configuration ||= Configuration.new
|
21
|
-
end
|
22
8
|
end
|
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_tipjar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Paulson
|
@@ -53,13 +53,12 @@ files:
|
|
53
53
|
- app/helpers/tipjar_helper.rb
|
54
54
|
- app/views/tipjar/_button.html.erb
|
55
55
|
- app/views/tipjar/_modal.html.erb
|
56
|
+
- blog_post.md
|
56
57
|
- config/importmap.rb
|
57
|
-
- lib/generators/tipjar/install/install_generator.rb
|
58
|
-
- lib/generators/tipjar/install/templates/tipjar.rb
|
59
58
|
- lib/rails_tipjar.rb
|
60
|
-
- lib/rails_tipjar/configuration.rb
|
61
59
|
- lib/rails_tipjar/engine.rb
|
62
60
|
- lib/rails_tipjar/version.rb
|
61
|
+
- rails_tipjar-1.0.2.gem
|
63
62
|
- sig/rails_tipjar.rbs
|
64
63
|
homepage: https://github.com/justinpaulson/rails_tipjar
|
65
64
|
licenses: []
|
@@ -1,103 +0,0 @@
|
|
1
|
-
require "rails/generators/base"
|
2
|
-
|
3
|
-
module Tipjar
|
4
|
-
module Generators
|
5
|
-
class InstallGenerator < Rails::Generators::Base
|
6
|
-
source_root File.expand_path("templates", __dir__)
|
7
|
-
|
8
|
-
desc "Creates an optional RailsTipjar initializer for backwards compatibility"
|
9
|
-
|
10
|
-
def copy_initializer
|
11
|
-
if yes?("Do you want to create an initializer file for backwards compatibility? (not recommended - use view helper options instead) [y/N]")
|
12
|
-
template "tipjar.rb", "config/initializers/tipjar.rb"
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def add_stimulus_controller
|
17
|
-
if File.exist?("app/javascript/controllers/index.js")
|
18
|
-
append_to_file "app/javascript/controllers/index.js" do
|
19
|
-
<<~JS
|
20
|
-
|
21
|
-
// Register Tip Jar controller
|
22
|
-
import TipjarController from "tipjar_controller"
|
23
|
-
application.register("tipjar", TipjarController)
|
24
|
-
JS
|
25
|
-
end
|
26
|
-
else
|
27
|
-
say "Please manually register the tipjar Stimulus controller in your application", :yellow
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def add_stylesheet
|
32
|
-
if File.exist?("app/assets/stylesheets/application.css")
|
33
|
-
append_to_file "app/assets/stylesheets/application.css" do
|
34
|
-
<<~CSS
|
35
|
-
|
36
|
-
/* Tip Jar Styles */
|
37
|
-
@import 'tipjar';
|
38
|
-
CSS
|
39
|
-
end
|
40
|
-
elsif File.exist?("app/assets/stylesheets/application.scss")
|
41
|
-
append_to_file "app/assets/stylesheets/application.scss" do
|
42
|
-
<<~SCSS
|
43
|
-
|
44
|
-
// Tip Jar Styles
|
45
|
-
@import 'tipjar';
|
46
|
-
SCSS
|
47
|
-
end
|
48
|
-
elsif File.exist?("app/assets/stylesheets/application.tailwind.css")
|
49
|
-
append_to_file "app/assets/stylesheets/application.tailwind.css" do
|
50
|
-
<<~CSS
|
51
|
-
|
52
|
-
/* Tip Jar Styles */
|
53
|
-
@import 'tipjar';
|
54
|
-
CSS
|
55
|
-
end
|
56
|
-
else
|
57
|
-
say "Please manually import 'tipjar' stylesheet in your application", :yellow
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def add_helper_to_application_controller
|
62
|
-
inject_into_file "app/controllers/application_controller.rb",
|
63
|
-
after: "class ApplicationController < ActionController::Base\n" do
|
64
|
-
" helper TipjarHelper\n"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def display_post_install_message
|
69
|
-
say "\n", :green
|
70
|
-
say "RailsTipjar has been successfully installed!", :green
|
71
|
-
say "\n"
|
72
|
-
say "Next steps:", :yellow
|
73
|
-
say "1. Create payment links with your preferred provider (Stripe, PayPal, Ko-fi, etc.)", :yellow
|
74
|
-
say "2. Add the tip jar to your views using the helper", :yellow
|
75
|
-
say "\n"
|
76
|
-
say "Example usage in your views:", :cyan
|
77
|
-
say <<~USAGE
|
78
|
-
<!-- Simple button with direct link -->
|
79
|
-
<%= tip_jar payment_link: 'https://your.payment.link' %>
|
80
|
-
|
81
|
-
<!-- With custom options -->
|
82
|
-
<%= tip_jar payment_link: 'https://your.payment.link',
|
83
|
-
message: 'Support This Project',
|
84
|
-
icon: :heart,
|
85
|
-
color: '#8b5cf6',
|
86
|
-
pulse: true %>
|
87
|
-
|
88
|
-
<!-- Modal with multiple payment amounts -->
|
89
|
-
<%= tip_jar payment_links: {
|
90
|
-
small: 'https://link-5',
|
91
|
-
medium: 'https://link-10',
|
92
|
-
large: 'https://link-25'
|
93
|
-
},
|
94
|
-
modal_title: 'Support my work',
|
95
|
-
position: :bottom_left %>
|
96
|
-
USAGE
|
97
|
-
say "\n"
|
98
|
-
say "For more options, see the README: https://github.com/justinpaulson/rails_tipjar", :cyan
|
99
|
-
say "\n"
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
RailsTipjar.configure do |config|
|
4
|
-
# Configure your payment links
|
5
|
-
# Works with any payment provider: Stripe, PayPal, Ko-fi, Buy Me a Coffee, etc.
|
6
|
-
#
|
7
|
-
# Simple mode - just one payment link:
|
8
|
-
# config.payment_link = "https://your-payment-provider.com/your-link"
|
9
|
-
#
|
10
|
-
# Modal mode - multiple payment links for different amounts:
|
11
|
-
config.payment_links = {
|
12
|
-
small: "https://REPLACE_WITH_YOUR_PAYMENT_LINK",
|
13
|
-
medium: "https://REPLACE_WITH_YOUR_PAYMENT_LINK",
|
14
|
-
large: "https://REPLACE_WITH_YOUR_PAYMENT_LINK",
|
15
|
-
custom: "https://REPLACE_WITH_YOUR_PAYMENT_LINK"
|
16
|
-
}
|
17
|
-
|
18
|
-
# Position of the tip jar button
|
19
|
-
# Options: :bottom_right, :bottom_left, :top_right, :top_left
|
20
|
-
config.position = :bottom_right
|
21
|
-
|
22
|
-
# Icon to display in the button
|
23
|
-
# Options: :coffee, :heart, :star, :dollar, or custom SVG string
|
24
|
-
config.icon = :coffee
|
25
|
-
|
26
|
-
# Theme for the modal
|
27
|
-
# Options: :light, :dark, :auto
|
28
|
-
config.theme = :light
|
29
|
-
|
30
|
-
# Button text (shown on hover)
|
31
|
-
config.button_text = "Buy me a coffee"
|
32
|
-
|
33
|
-
# Modal customization
|
34
|
-
config.modal_title = "Support my work"
|
35
|
-
config.modal_description = "Your support helps me continue creating and maintaining this project."
|
36
|
-
|
37
|
-
# Custom tip amounts to display in the modal
|
38
|
-
config.custom_amounts = [
|
39
|
-
{ amount: 5, label: "$5", default: false },
|
40
|
-
{ amount: 10, label: "$10", default: true },
|
41
|
-
{ amount: 25, label: "$25", default: false },
|
42
|
-
{ amount: 50, label: "$50", default: false }
|
43
|
-
]
|
44
|
-
|
45
|
-
# Additional CSS classes for the button
|
46
|
-
config.button_class = ""
|
47
|
-
|
48
|
-
# Z-index for the button and modal
|
49
|
-
config.z_index = 1000
|
50
|
-
|
51
|
-
# Enable analytics tracking
|
52
|
-
# Tracks: button clicks, modal opens, amount selections, and successful tips
|
53
|
-
# Works with Google Analytics 4 and Plausible out of the box
|
54
|
-
config.analytics_enabled = false
|
55
|
-
|
56
|
-
# Customize button colors (hex values)
|
57
|
-
# Default: blue background (#3b82f6) with white text (#ffffff)
|
58
|
-
# config.color = "#3b82f6"
|
59
|
-
# config.text_color = "#ffffff"
|
60
|
-
|
61
|
-
# Enable pulsing animation on the button
|
62
|
-
# Default: false (no animation)
|
63
|
-
# config.pulse = true
|
64
|
-
end
|
@@ -1,171 +0,0 @@
|
|
1
|
-
module RailsTipjar
|
2
|
-
class Configuration
|
3
|
-
attr_accessor :payment_links, :position, :icon, :theme, :button_text,
|
4
|
-
:modal_title, :modal_description, :custom_amounts,
|
5
|
-
:button_class, :z_index, :analytics_enabled, :payment_link,
|
6
|
-
:use_modal, :color, :text_color, :pulse
|
7
|
-
|
8
|
-
def initialize
|
9
|
-
# Simple mode - just one link
|
10
|
-
@payment_link = nil
|
11
|
-
@use_modal = false # Default to direct link when payment_link is set
|
12
|
-
|
13
|
-
# Legacy modal mode
|
14
|
-
@payment_links = {}
|
15
|
-
@position = :bottom_right
|
16
|
-
@icon = :coffee
|
17
|
-
@theme = :light
|
18
|
-
@button_text = "Buy me a coffee"
|
19
|
-
@modal_title = "Support my work"
|
20
|
-
@modal_description = "Your support helps me continue creating and maintaining this project."
|
21
|
-
@custom_amounts = [
|
22
|
-
{ amount: 5, label: "$5", default: false },
|
23
|
-
{ amount: 10, label: "$10", default: true },
|
24
|
-
{ amount: 25, label: "$25", default: false },
|
25
|
-
{ amount: 50, label: "$50", default: false }
|
26
|
-
]
|
27
|
-
@button_class = ""
|
28
|
-
@z_index = 1000
|
29
|
-
@analytics_enabled = false
|
30
|
-
@color = "#3b82f6" # Default blue color
|
31
|
-
@text_color = "#ffffff" # Default white text color
|
32
|
-
@pulse = false # Default no pulsing animation
|
33
|
-
end
|
34
|
-
|
35
|
-
def position_classes
|
36
|
-
case @position
|
37
|
-
when :bottom_right
|
38
|
-
"bottom-4 right-4"
|
39
|
-
when :bottom_left
|
40
|
-
"bottom-4 left-4"
|
41
|
-
when :top_right
|
42
|
-
"top-4 right-4"
|
43
|
-
when :top_left
|
44
|
-
"top-4 left-4"
|
45
|
-
else
|
46
|
-
"bottom-4 right-4"
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def icon_svg
|
51
|
-
case @icon
|
52
|
-
when :coffee
|
53
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
54
|
-
<defs>
|
55
|
-
<style>
|
56
|
-
@keyframes steam1 {
|
57
|
-
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
58
|
-
20% { opacity: 0.8; }
|
59
|
-
50% { opacity: 0.6; transform: translateY(-3px) translateX(1px); }
|
60
|
-
80% { opacity: 0.3; }
|
61
|
-
100% { opacity: 0; transform: translateY(-8px) translateX(-1px); }
|
62
|
-
}
|
63
|
-
@keyframes steam2 {
|
64
|
-
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
65
|
-
15% { opacity: 0.7; }
|
66
|
-
45% { opacity: 0.5; transform: translateY(-4px) translateX(-1px); }
|
67
|
-
75% { opacity: 0.2; }
|
68
|
-
100% { opacity: 0; transform: translateY(-9px) translateX(1px); }
|
69
|
-
}
|
70
|
-
@keyframes steam3 {
|
71
|
-
0% { opacity: 0; transform: translateY(0) translateX(0); }
|
72
|
-
25% { opacity: 0.6; }
|
73
|
-
55% { opacity: 0.4; transform: translateY(-3px) translateX(0.5px); }
|
74
|
-
85% { opacity: 0.1; }
|
75
|
-
100% { opacity: 0; transform: translateY(-7px) translateX(-0.5px); }
|
76
|
-
}
|
77
|
-
.steam1 { animation: steam1 3s ease-out infinite; }
|
78
|
-
.steam2 { animation: steam2 3s ease-out infinite 0.5s; }
|
79
|
-
.steam3 { animation: steam3 3s ease-out infinite 1s; }
|
80
|
-
</style>
|
81
|
-
</defs>
|
82
|
-
<!-- Steam wisps with wavy paths -->
|
83
|
-
<path class="steam1" d="M8 9c0.5-0.5 0.5-1 0-1.5s-0.5-1 0-1.5s0.5-1 0-1.5" stroke-linecap="round" fill="none" opacity="0"/>
|
84
|
-
<path class="steam2" d="M12 8.5c-0.3-0.4 -0.3-0.8 0-1.2s0.3-0.8 0-1.2s-0.3-0.8 0-1.2" stroke-linecap="round" fill="none" opacity="0"/>
|
85
|
-
<path class="steam3" d="M15.5 9c0.4-0.3 0.4-0.7 0-1s-0.4-0.7 0-1s0.4-0.7 0-1" stroke-linecap="round" fill="none" opacity="0"/>
|
86
|
-
<!-- Coffee cup body -->
|
87
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M6 10h12v7a3 3 0 01-3 3H9a3 3 0 01-3-3v-7z"/>
|
88
|
-
<!-- Cup handle -->
|
89
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M18 10h1.5a2.5 2.5 0 010 5H18"/>
|
90
|
-
<!-- Saucer -->
|
91
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M4 20h16"/>
|
92
|
-
<!-- Coffee surface detail -->
|
93
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M8 12h8" opacity="0.3"/>
|
94
|
-
</svg>'
|
95
|
-
when :heart
|
96
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
97
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M21 8.5c0-2.485-2.099-4.5-4.688-4.5-1.935 0-3.597 1.126-4.312 2.733-.715-1.607-2.377-2.733-4.313-2.733C5.1 4 3 6.015 3 8.5c0 7.5 9 11.5 9 11.5s9-4 9-11.5z" />
|
98
|
-
</svg>'
|
99
|
-
when :star
|
100
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
101
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z" />
|
102
|
-
</svg>'
|
103
|
-
when :dollar
|
104
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
105
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6v12m-3-2.818l.879.659c1.171.879 3.07.879 4.242 0 1.172-.879 1.172-2.303 0-3.182C13.536 12.219 12.768 12 12 12c-.725 0-1.45-.22-2.003-.659-1.106-.879-1.106-2.303 0-3.182s2.9-.879 4.006 0l.415.33M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
106
|
-
</svg>'
|
107
|
-
when :jar
|
108
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
|
109
|
-
<defs>
|
110
|
-
<style>
|
111
|
-
@keyframes tipjar-coin-drop-new {
|
112
|
-
0% {
|
113
|
-
transform: translateY(0px);
|
114
|
-
opacity: 0;
|
115
|
-
}
|
116
|
-
10% {
|
117
|
-
opacity: 1;
|
118
|
-
transform: translateY(2px);
|
119
|
-
}
|
120
|
-
30% {
|
121
|
-
transform: translateY(6px);
|
122
|
-
}
|
123
|
-
50% {
|
124
|
-
transform: translateY(10px);
|
125
|
-
opacity: 1;
|
126
|
-
}
|
127
|
-
70% {
|
128
|
-
transform: translateY(15.5px);
|
129
|
-
opacity: 1;
|
130
|
-
}
|
131
|
-
75% {
|
132
|
-
transform: translateY(16.3px);
|
133
|
-
opacity: 1;
|
134
|
-
}
|
135
|
-
80% {
|
136
|
-
transform: translateY(15.8px);
|
137
|
-
opacity: 0.8;
|
138
|
-
}
|
139
|
-
100% {
|
140
|
-
transform: translateY(16.3px);
|
141
|
-
opacity: 0;
|
142
|
-
}
|
143
|
-
}
|
144
|
-
.tipjar-coin-drop-new {
|
145
|
-
animation: tipjar-coin-drop-new 2.5s ease-in-out infinite;
|
146
|
-
}
|
147
|
-
</style>
|
148
|
-
</defs>
|
149
|
-
<!-- Jar lid -->
|
150
|
-
<rect x="9.5" y="3" width="5" height="1" rx="0.25" stroke-linecap="round" stroke-linejoin="round"/>
|
151
|
-
<!-- Jar threads/neck -->
|
152
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M10 4v0.8M14 4v0.8"/>
|
153
|
-
<!-- Jar body - much fatter with short taper -->
|
154
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M10 4.8h4M9 5.5c-1 0 -2 0.5 -2 1v12.5a2 2 0 002 2h6a2 2 0 002-2V6.5c0-0.5 -1-1 -2-1"/>
|
155
|
-
<!-- Coins at bottom - pile -->
|
156
|
-
<ellipse cx="10.5" cy="18.5" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
157
|
-
<ellipse cx="13.5" cy="18.3" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
158
|
-
<ellipse cx="12" cy="17.8" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
159
|
-
<ellipse cx="11" cy="19" rx="1.3" ry="0.4" stroke-linecap="round"/>
|
160
|
-
<ellipse cx="13" cy="19" rx="1.3" ry="0.4" stroke-linecap="round"/>
|
161
|
-
<!-- Falling coin - starts above jar outside -->
|
162
|
-
<g class="tipjar-coin-drop-new">
|
163
|
-
<ellipse cx="12" cy="1.5" rx="1.5" ry="0.5" stroke-linecap="round"/>
|
164
|
-
</g>
|
165
|
-
</svg>'
|
166
|
-
else
|
167
|
-
@icon
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|