https://github.com/ersync/skeleton-loader
Seamless skeleton loaders to enhance visuals and user experience in Rails
https://github.com/ersync/skeleton-loader
gem rails ruby-on-rails skeleton-loading views
Last synced: 5 months ago
JSON representation
Seamless skeleton loaders to enhance visuals and user experience in Rails
- Host: GitHub
- URL: https://github.com/ersync/skeleton-loader
- Owner: ersync
- License: mit
- Created: 2024-10-25T14:16:52.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2025-01-02T16:29:10.000Z (over 1 year ago)
- Last Synced: 2025-12-17T10:59:02.833Z (6 months ago)
- Topics: gem, rails, ruby-on-rails, skeleton-loading, views
- Language: Ruby
- Homepage: https://rubygems.org/gems/skeleton-loader
- Size: 162 KB
- Stars: 0
- Watchers: 1
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# Skeleton Loader
[](https://badge.fury.io/rb/skeleton-loader)
[](https://dl.circleci.com/status-badge/redirect/circleci/8MamMcAVAVNWTcUqkjQk7R/Sh2DQkMWqqCv4MFvAmYWDL/tree/main)

[](https://opensource.org/licenses/MIT)
**Skeleton Loader** is a Ruby on Rails gem for creating animated placeholders that enhance loading states. Whether rendered through Rails views or dynamically with JavaScript, these skeletons provide a seamless visual experience while content loads.
**⚠ Note:** Skeleton Loader is an experimental gem currently in early development, exploring the possibilities in the magical world of Rails gems. While loaders are ideally handled client-side, this gem aims to make it easy to add placeholders directly within the Rails realm.
---
## Table of Contents
- [Features](#features)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Usage](#usage)
- [JavaScript Integration](#javascript-integration)
- [Configuration](#configuration)
- [Code Quality](#code-quality)
- [Roadmap](#roadmap)
- [Contributing](#contributing)
- [License](#license)
---

## Features
- 🚀 **Seamless Rails integration:** Enhances loading transitions with minimal setup.
- 🔨 **Universal skeletons:** Creates loading states in Rails views & JavaScript.
- ⚙️ **Consistency:** Unified templates & options across both environments.
- ⚡ **Lightweight & fast:** Designed to be fast and easy to implement with minimal dependencies.
---
## Installation
To install Skeleton Loader, add the following line to your Gemfile:
```ruby
gem "skeleton-loader"
```
Then, execute:
```bash
bundle install
```
### Requirements
- Ruby 2.5 or higher
- Rails 5.0 or higher
- Asset Pipeline (for CSS handling)
### Install Templates
Add predefined templates to your app with:
```bash
rails generate skeleton_loader:add_templates
```
This command will place templates in `app/views/skeleton_loader/`, which you can customize as needed.
And in case needed, you can revert to default templates by running:
```bash
rails generate skeleton_loader:reset_templates
```
---
## Quick Start
Quickly integrate Skeleton Loader into your Rails app with these steps:
1. **Include Assets**
- **Rails 7 (Import Maps)**:
- In `config/importmap.rb`, add:
```ruby
pin "skeleton-loader", to: "skeleton_loader.js"
```
- In your JavaScript entry file, add:
```javascript
import SkeletonLoader from "skeleton-loader"
```
- In `app/assets/stylesheets/application.css`, add:
```css
*= require skeleton_loader
```
- **Rails 6 (Webpack)**:
- Run:
```bash
npm install "@ersync/skeleton-loader"
```
- In your JavaScript entry file, add:
```javascript
import SkeletonLoader from "skeleton-loader"
```
- **Rails 5 (Asset Pipeline)**:
- In `app/assets/javascripts/application.js`, add:
```javascript
//= require skeleton_loader
```
- In `app/assets/stylesheets/application.css`, add:
```css
*= require skeleton_loader
```
2. **Use in Views**
Use the `skeleton_loader` helper next to the content that loads slowly. Set `content_id` to the target element's ID and choose a `type` for the skeleton template.
Example:
```erb
<%= skeleton_loader(content_id: 'content-element', type: "card") %>
```
For more detailed instructions, refer to Usage section.
---
## Usage
The gem provides a primary view helper, `skeleton_loader`, which generates a div containing a skeleton next to the targeted content element. This skeleton will be hidden once the content element fully loads, providing a seamless loading experience.
### Pre-defined Templates
Specify `content_id` and, optionally, a template `type` and customization `options`.
```erb
<%= skeleton_loader(content_id: 'content-element',
type: "card",
count: 5,
scale: 1.2,
animation_type: 'animation-pulse') %>
```
### Custom Skeletons with a Block
Define your own HTML structure in a block. Note that `type` and `options` are not used.
```erb
<%= skeleton_loader(content_id: 'content-element') do %>
<% end %>
```
See [Configuration](#configuration) for all available options.
---
## JavaScript Integration
Skeleton Loader also provides a JavaScript API to dynamically create skeletons independently of Rails views.
💡 You only need this API if you're loading content asynchronously i.e. AJAX calls. For standard Rails views, use the Rails helper method instead.
### 1. Basic Setup
First, initialize the SkeletonLoader in your JavaScript:
```javascript
const skeleton = new SkeletonLoader();
```
### 2. Creating Skeletons
There are two methods for creating skeletons using JavaScript:
#### Using Pre-defined Templates
```javascript
const loader = skeleton.render({
contentId, // Required. ID of the element to replace with skeleton
...options // Optional. See configuration section for available options
});
```
#### Creating Custom Skeletons
```javascript
const loader = skeleton.renderCustom({
contentId, // Required. ID of the element to replace with skeleton
markup // Required. Custom HTML string for skeleton content
});
```
### 3. Managing Loading States
Each skeleton instance (both `render()` and `renderCustom()`) returns an object with these methods:
- `isLoading()`: Returns the current loading state
- `reveal()`: Removes skeleton and displays content
```javascript
// Check if still loading
if (loader.isLoading()) {
// Do something while content loads
}
// Remove skeleton and show content
loader.reveal();
```
Practical Examples
Here's some example showing how to use the skeleton loader with an API call:
```javascript
async function loadUserProfile(userId) {
// Create skeleton while loading
const loader = skeleton.render({
contentId: 'content-element',
type: 'profile'
});
try {
// Fetch your data
const response = await fetch(`/api/users/${userId}`);
const userData = await response.json();
// Update the DOM with your content
document.getElementById('content-element').innerHTML = createUserProfile(userData);
// Remove the skeleton
loader.reveal();
} catch (error) {
console.error('Failed to load user profile:', error);
loader.reveal(); // Always cleanup the skeleton
}
}
```
```javascript
async function loadDashboard() {
// Create multiple skeletons
const loaders = {
profile: skeleton.render({ contentId: 'profile', type: 'profile', scale:1.2, width:250 }),
stats: skeleton.render({ contentId: 'stats', type: 'card', scale:1.3, animationType:"sl-flow" }),
activities: skeleton.render({ contentId: 'activities', type: 'list' })
};
// Load your data
const [profileData, statsData, activitiesData] = await Promise.all([
fetchProfile(),
fetchStats(),
fetchActivities()
]);
// Update content and reveal each section
updateProfile(profileData);
loaders.profile.reveal();
updateStats(statsData);
loaders.stats.reveal();
updateActivities(activitiesData);
loaders.activities.reveal();
}
```
---
## Configuration
### Options
The following options can be passed to both the Rails view helper and JavaScript API. Note that Rails uses snake_case (e.g., `animation_type`), while JavaScript uses camelCase (e.g., `animationType`).
| Option | Type | Description | Default | Example |
|--------|------|-------------|---------|---------|
| `content_id` | String | Unique identifier for the skeleton loader container | `nil` | `"content-element"` |
| `type` | String | Predefined template type (e.g., "product", "profile") | `"default"` | `"product"` |
| `width` | Integer | Base width of a single skeleton item in pixels | Depends on `type` | `250` |
| `count` | Integer | Number of skeleton items to render | Depends on `type` | `6` |
| `per_row` | Integer | Number of skeleton items displayed per row | Depends on `type` | `4` |
| `scale` | Float | Size multiplier for all skeleton item dimensions | `1.0` | `1.2` |
| `animation_type` | String | Type of loading animation | `"sl-gradient"` | `"sl-glow"` |
**Notes:**
- `type` determines default layout and styling
- `scale` affects width and spacing proportionally
- `animation_type` supports different loading effect styles
### Available Templates
Skeleton Loader comes with several pre-built templates, each with their **default** configurations:
| Template Type | Default Width | Count | Items Per Row |
|--------------|---------------|-------|---------------|
| `card` | 200px | 3 | 3 |
| `comment` | 900px | 2 | 1 |
| `default` | 900px | 1 | 1 |
| `gallery` | 320px | 3 | 3 |
| `paragraph` | 900px | 1 | 1 |
| `product` | 320px | 3 | 3 |
| `profile` | 320px | 3 | 3 |
For an interactive preview of available templates and animations, visit the [Live Demo](https://ersync.github.io/skeleton-loader/).
### Available Animations
Choose from several animation styles to match your design:
- `sl-gradient` (default): Smooth gradient movement
- `sl-shine`: Shimmer effect
- `sl-pulse`: Fade in/out
- `sl-flow`: Continuous flow
- `sl-neon`: Subtle glow
- `sl-breathing`: Gentle scaling
### Application Defaults
To set application-wide defaults, create `config/initializers/skeleton_loader.rb`:
```ruby
SkeletonLoader.configure do |config|
# Override default template settings
config.templates[:product] = {
width: 400,
count: 6,
per_row: 3
}
# Global settings
config.scale = 1.0 # Default: 1.0
config.animation_type = "sl-gradient" # Default: "sl-gradient"
end
```
### Advanced Configuration
For applications requiring custom HTML elements or styles:
```ruby
SkeletonLoader.configure do |config|
config.additional_allowed_tags = [] # Default: []
config.additional_allowed_attributes = {} # Default: {}
config.additional_allowed_css_properties = [] # Default: []
end
```
---
## Code Quality
Skeleton Loader maintains code quality through:
- **RSpec**: Comprehensive tests covering core functionality.
- **CircleCI**: Continuous integration ensures all new changes meet quality standards.
- **Rubocop**: Consistent linting aligns code with Ruby community conventions.
---
## Roadmap
Here are some features I'd like to add when I have time:
- **New Templates & Animations**: Expanding template and animation options.
- **Turbo & Stimulus Support**: Enhancing compatibility with Rails Turbo and StimulusJS.
- **Builder Helper for Custom Skeletons:**: Introducing a helper to easily create custom skeletons (e.g., circles, rectangles, etc.) with customizable options, simplifying the process of designing custom skeletons.
Suggestions and contributions are welcome!
---
## Contributing
To contribute:
1. Fork the repository.
2. Create a new feature branch.
3. Add tests for new features.
4. Commit your changes and submit a pull request.
Please follow the [Code of Conduct](https://github.com/ersync/skeleton-loader/blob/main/CODE_OF_CONDUCT.md) for all contributions.
---
## License
Skeleton Loader is licensed under the MIT License. See [LICENSE](https://github.com/ersync/skeleton-loader/blob/main/LICENSE) for details.