{"id":22591257,"url":"https://github.com/ersync/skeleton-loader","last_synced_at":"2026-02-06T06:02:34.491Z","repository":{"id":266950465,"uuid":"878506997","full_name":"ersync/skeleton-loader","owner":"ersync","description":"Seamless skeleton loaders to enhance visuals and user experience in Rails","archived":false,"fork":false,"pushed_at":"2025-01-02T16:29:10.000Z","size":166,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-17T10:59:02.833Z","etag":null,"topics":["gem","rails","ruby-on-rails","skeleton-loading","views"],"latest_commit_sha":null,"homepage":"https://rubygems.org/gems/skeleton-loader","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ersync.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-25T14:16:52.000Z","updated_at":"2025-01-02T16:29:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"13d945a3-4a51-4379-ad77-c4812f6e0465","html_url":"https://github.com/ersync/skeleton-loader","commit_stats":null,"previous_names":["ersync/skeleton-loader"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/ersync/skeleton-loader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersync%2Fskeleton-loader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersync%2Fskeleton-loader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersync%2Fskeleton-loader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersync%2Fskeleton-loader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ersync","download_url":"https://codeload.github.com/ersync/skeleton-loader/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ersync%2Fskeleton-loader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29153143,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T02:39:25.012Z","status":"ssl_error","status_checked_at":"2026-02-06T02:37:22.784Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gem","rails","ruby-on-rails","skeleton-loading","views"],"created_at":"2024-12-08T09:11:35.371Z","updated_at":"2026-02-06T06:02:34.462Z","avatar_url":"https://github.com/ersync.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Skeleton Loader\n\n[![Gem Version](https://badge.fury.io/rb/skeleton-loader.svg)](https://badge.fury.io/rb/skeleton-loader)\n[![CircleCI](https://dl.circleci.com/status-badge/img/circleci/8MamMcAVAVNWTcUqkjQk7R/Sh2DQkMWqqCv4MFvAmYWDL/tree/main.svg?style=svg\u0026circle-token=CCIPRJ_PF8xu3Svcj2Ro4D8jhjCi7_71b7c0a7c781e09fc7194cd58cca67aecdc111b5)](https://dl.circleci.com/status-badge/redirect/circleci/8MamMcAVAVNWTcUqkjQk7R/Sh2DQkMWqqCv4MFvAmYWDL/tree/main)\n![Test Coverage: 100%](https://img.shields.io/badge/Test%20Coverage-100%25-brightgreen)\n[![MIT License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT)\n\n**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.\n\n**⚠ 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.\n\n---\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Quick Start](#quick-start)\n- [Usage](#usage)\n- [JavaScript Integration](#javascript-integration)\n- [Configuration](#configuration)\n- [Code Quality](#code-quality)\n- [Roadmap](#roadmap)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n![1](https://github.com/user-attachments/assets/f6f91f55-1bfa-42eb-9e8c-41606eb8afd5)\n\n## Features\n\n- 🚀 **Seamless Rails integration:** Enhances loading transitions with minimal setup.\n- 🔨 **Universal skeletons:** Creates loading states in Rails views \u0026 JavaScript.\n- ⚙️ **Consistency:** Unified templates \u0026 options across both environments.\n- ⚡ **Lightweight \u0026 fast:** Designed to be fast and easy to implement with minimal dependencies.\n\n---\n\n## Installation\n\nTo install Skeleton Loader, add the following line to your Gemfile:\n\n```ruby\ngem \"skeleton-loader\"\n```\n\nThen, execute:\n\n```bash\nbundle install\n```\n\n### Requirements\n\n- Ruby 2.5 or higher\n- Rails 5.0 or higher\n- Asset Pipeline (for CSS handling)\n\n### Install Templates\n\nAdd predefined templates to your app with:\n\n```bash\nrails generate skeleton_loader:add_templates\n```\n\nThis command will place templates in `app/views/skeleton_loader/`, which you can customize as needed. \n\nAnd in case needed, you can revert to default templates by running:\n\n```bash\nrails generate skeleton_loader:reset_templates\n```\n\n---\n\n## Quick Start\n\nQuickly integrate Skeleton Loader into your Rails app with these steps:\n\n1. **Include Assets**\n\n   - **Rails 7 (Import Maps)**:\n     - In `config/importmap.rb`, add:\n       ```ruby\n       pin \"skeleton-loader\", to: \"skeleton_loader.js\"\n       ```\n     - In your JavaScript entry file, add:\n       ```javascript\n       import SkeletonLoader from \"skeleton-loader\"\n       ```\n    - In `app/assets/stylesheets/application.css`, add:\n        ```css\n        *= require skeleton_loader\n        ```\n   - **Rails 6 (Webpack)**:\n     - Run:\n       ```bash\n       npm install \"@ersync/skeleton-loader\"\n       ```\n     - In your JavaScript entry file, add:\n       ```javascript\n       import SkeletonLoader from \"skeleton-loader\"\n       ```\n\n   - **Rails 5 (Asset Pipeline)**:\n     - In `app/assets/javascripts/application.js`, add:\n       ```javascript\n       //= require skeleton_loader\n       ```\n     - In `app/assets/stylesheets/application.css`, add:\n       ```css\n       *= require skeleton_loader\n       ```\n\n2. **Use in Views**\n\n   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.\n\n   Example:\n   ```erb\n   \u003cdiv id=\"content-element\"\u003e\n     \u003c!-- Content that takes time to load --\u003e\n   \u003c/div\u003e\n   \u003c%= skeleton_loader(content_id: 'content-element', type: \"card\") %\u003e\n   ```\n\nFor more detailed instructions, refer to Usage section.\n\n---\n\n## Usage\n\nThe 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.\n\n### Pre-defined Templates\n\nSpecify `content_id` and, optionally, a template `type` and customization `options`.\n\n```erb\n\u003c%= skeleton_loader(content_id: 'content-element', \n  type: \"card\",\n  count: 5,\n  scale: 1.2,\n  animation_type: 'animation-pulse') %\u003e\n```\n\n### Custom Skeletons with a Block\n\nDefine your own HTML structure in a block. Note that `type` and `options` are not used.\n\n```erb\n\u003c%= skeleton_loader(content_id: 'content-element') do %\u003e\n  \u003cdiv class=\"custom-skeleton\"\u003e\n    \u003cdiv class=\"avatar skeleton-circle\"\u003e\u003c/div\u003e\n    \u003cdiv class=\"text-lines\"\u003e\u003c/div\u003e\n  \u003c/div\u003e\n\u003c% end %\u003e\n```\n\nSee [Configuration](#configuration) for all available options.\n\n---\n\n## JavaScript Integration\n\nSkeleton Loader also provides a JavaScript API to dynamically create skeletons independently of Rails views.\n\n\u003cdetails\u003e\n\u003csummary\u003e💡 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.\u003c/summary\u003e\n\n### 1. Basic Setup\n\nFirst, initialize the SkeletonLoader in your JavaScript:\n\n```javascript\nconst skeleton = new SkeletonLoader();\n```\n\n### 2. Creating Skeletons\n\nThere are two methods for creating skeletons using JavaScript:\n\n#### Using Pre-defined Templates\n\n```javascript\nconst loader = skeleton.render({\n  contentId,                    // Required. ID of the element to replace with skeleton\n  ...options                    // Optional. See configuration section for available options\n});\n```\n\n#### Creating Custom Skeletons\n\n```javascript\nconst loader = skeleton.renderCustom({\n  contentId,                    // Required. ID of the element to replace with skeleton\n  markup                        // Required. Custom HTML string for skeleton content\n});\n```\n\n### 3. Managing Loading States\n\nEach skeleton instance (both `render()` and `renderCustom()`) returns an object with these methods:\n\n- `isLoading()`: Returns the current loading state\n- `reveal()`: Removes skeleton and displays content\n\n```javascript\n// Check if still loading\nif (loader.isLoading()) {\n  // Do something while content loads\n}\n\n// Remove skeleton and show content\nloader.reveal();\n```\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003ePractical Examples\u003c/strong\u003e\u003c/summary\u003e\n\nHere's some example showing how to use the skeleton loader with an API call:\n\n```javascript\nasync function loadUserProfile(userId) {\n  // Create skeleton while loading\n  const loader = skeleton.render({\n    contentId: 'content-element',\n    type: 'profile'\n  });\n\n  try {\n    // Fetch your data\n    const response = await fetch(`/api/users/${userId}`);\n    const userData = await response.json();\n\n    // Update the DOM with your content\n    document.getElementById('content-element').innerHTML = createUserProfile(userData);\n\n    // Remove the skeleton\n    loader.reveal();\n  } catch (error) {\n    console.error('Failed to load user profile:', error);\n    loader.reveal(); // Always cleanup the skeleton\n  }\n}\n```\n\n```javascript\nasync function loadDashboard() {\n  // Create multiple skeletons\n  const loaders = {\n    profile: skeleton.render({ contentId: 'profile', type: 'profile', scale:1.2, width:250 }),\n    stats: skeleton.render({ contentId: 'stats', type: 'card', scale:1.3, animationType:\"sl-flow\" }),\n    activities: skeleton.render({ contentId: 'activities', type: 'list' })\n  };\n\n  // Load your data\n  const [profileData, statsData, activitiesData] = await Promise.all([\n    fetchProfile(),\n    fetchStats(),\n    fetchActivities()\n  ]);\n\n  // Update content and reveal each section\n  updateProfile(profileData);\n  loaders.profile.reveal();\n\n  updateStats(statsData);\n  loaders.stats.reveal();\n\n  updateActivities(activitiesData);\n  loaders.activities.reveal();\n}\n```\n\u003c/details\u003e\n\u003c/details\u003e\n\n---\n\n## Configuration\n\n### Options\n\nThe 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`).\n\n\n| Option | Type | Description | Default | Example |\n|--------|------|-------------|---------|---------|\n| `content_id` | String | Unique identifier for the skeleton loader container | `nil` | `\"content-element\"` |\n| `type` | String | Predefined template type (e.g., \"product\", \"profile\") | `\"default\"` | `\"product\"` |\n| `width` | Integer | Base width of a single skeleton item in pixels | Depends on `type` | `250` |\n| `count` | Integer | Number of skeleton items to render | Depends on `type` | `6` |\n| `per_row` | Integer | Number of skeleton items displayed per row | Depends on `type` | `4` |\n| `scale` | Float | Size multiplier for all skeleton item dimensions | `1.0` | `1.2` |\n| `animation_type` | String | Type of loading animation | `\"sl-gradient\"` | `\"sl-glow\"` |\n\n**Notes:**\n- `type` determines default layout and styling\n- `scale` affects width and spacing proportionally\n- `animation_type` supports different loading effect styles\n\n### Available Templates\n\nSkeleton Loader comes with several pre-built templates, each with their **default** configurations:\n\n| Template Type | Default Width | Count | Items Per Row |\n|--------------|---------------|-------|---------------|\n| `card`       | 200px         | 3     | 3            |\n| `comment`    | 900px         | 2     | 1            |\n| `default`    | 900px         | 1     | 1            |\n| `gallery`    | 320px         | 3     | 3            |\n| `paragraph`  | 900px         | 1     | 1            |\n| `product`    | 320px         | 3     | 3            |\n| `profile`    | 320px         | 3     | 3            |\n\nFor an interactive preview of available templates and animations, visit the [Live Demo](https://ersync.github.io/skeleton-loader/).\n\n### Available Animations\n\nChoose from several animation styles to match your design:\n- `sl-gradient` (default): Smooth gradient movement\n- `sl-shine`: Shimmer effect\n- `sl-pulse`: Fade in/out\n- `sl-flow`: Continuous flow\n- `sl-neon`: Subtle glow\n- `sl-breathing`: Gentle scaling\n\n### Application Defaults\n\nTo set application-wide defaults, create `config/initializers/skeleton_loader.rb`:\n\n```ruby\nSkeletonLoader.configure do |config|\n  # Override default template settings\n  config.templates[:product] = {\n          width: 400,\n          count: 6,\n          per_row: 3\n  }\n  # Global settings\n  config.scale = 1.0                     # Default: 1.0\n  config.animation_type = \"sl-gradient\"  # Default: \"sl-gradient\"\nend\n```\n\n### Advanced Configuration\n\nFor applications requiring custom HTML elements or styles:\n\n```ruby\nSkeletonLoader.configure do |config|\n  config.additional_allowed_tags = []                  # Default: []\n  config.additional_allowed_attributes = {}            # Default: {}\n  config.additional_allowed_css_properties = []        # Default: []\nend\n```\n\n---\n\n## Code Quality\n\nSkeleton Loader maintains code quality through:\n\n- **RSpec**: Comprehensive tests covering core functionality.\n- **CircleCI**: Continuous integration ensures all new changes meet quality standards.\n- **Rubocop**: Consistent linting aligns code with Ruby community conventions.\n\n---\n\n## Roadmap\n\nHere are some features I'd like to add when I have time:\n\n- **New Templates \u0026 Animations**: Expanding template and animation options.\n- **Turbo \u0026 Stimulus Support**: Enhancing compatibility with Rails Turbo and StimulusJS.\n- **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.\n\nSuggestions and contributions are welcome!\n\n---\n\n## Contributing\n\nTo contribute:\n\n1. Fork the repository.\n2. Create a new feature branch.\n3. Add tests for new features.\n4. Commit your changes and submit a pull request.\n\nPlease follow the [Code of Conduct](https://github.com/ersync/skeleton-loader/blob/main/CODE_OF_CONDUCT.md) for all contributions.\n\n---\n\n## License\n\nSkeleton Loader is licensed under the MIT License. See [LICENSE](https://github.com/ersync/skeleton-loader/blob/main/LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fersync%2Fskeleton-loader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fersync%2Fskeleton-loader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fersync%2Fskeleton-loader/lists"}