{"id":20510897,"url":"https://github.com/martinzamuner/overlastic","last_synced_at":"2025-07-03T14:40:58.215Z","repository":{"id":59172408,"uuid":"535758132","full_name":"martinzamuner/overlastic","owner":"martinzamuner","description":"Fantastically easy overlays, dialog modals and slide-out-panes using Hotwire.","archived":false,"fork":false,"pushed_at":"2023-10-10T11:46:21.000Z","size":236,"stargazers_count":15,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-18T17:54:53.585Z","etag":null,"topics":["dialogs","hotwire","modals","overlays","panes","rails","ruby","turbo"],"latest_commit_sha":null,"homepage":"","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/martinzamuner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"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}},"created_at":"2022-09-12T16:36:28.000Z","updated_at":"2024-10-11T01:10:57.000Z","dependencies_parsed_at":"2024-11-18T07:30:40.191Z","dependency_job_id":null,"html_url":"https://github.com/martinzamuner/overlastic","commit_stats":{"total_commits":61,"total_committers":1,"mean_commits":61.0,"dds":0.0,"last_synced_commit":"208c670707518e7d00410e25fb107dbc5d61eac3"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/martinzamuner/overlastic","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinzamuner%2Foverlastic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinzamuner%2Foverlastic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinzamuner%2Foverlastic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinzamuner%2Foverlastic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinzamuner","download_url":"https://codeload.github.com/martinzamuner/overlastic/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinzamuner%2Foverlastic/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260638586,"owners_count":23040345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["dialogs","hotwire","modals","overlays","panes","rails","ruby","turbo"],"created_at":"2024-11-15T20:31:53.204Z","updated_at":"2025-07-03T14:40:58.194Z","avatar_url":"https://github.com/martinzamuner.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cbr\u003e\n  \u003cimg src=\"assets/logo.svg\" alt=\"Overlastic\" width=\"150\"\u003e\n  \u003cbr\u003e\n  Overlastic\n  \u003cbr\u003e\n\u003c/h1\u003e\n\n\u003ch3 align=\"center\"\u003eFantastically easy overlays using \u003ca href=\"https://hotwired.dev/\" target=\"_blank\"\u003eHotwire\u003c/a\u003e.\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg alt=\"Build\" src=\"https://img.shields.io/github/actions/workflow/status/martinzamuner/overlastic/ci.yml?branch=main\"\u003e\n  \u003cimg alt=\"Gem\" src=\"https://img.shields.io/gem/v/overlastic\"\u003e\n  \u003cimg alt=\"rails version\" src=\"https://img.shields.io/badge/rails-%3E%3D%206.1.0-informational\"\u003e\n  \u003cimg alt=\"turbo-rails version\" src=\"https://img.shields.io/badge/turbo--rails-%3E%3D%201.3.0-informational\"\u003e\n  \u003cimg alt=\"License\" src=\"https://img.shields.io/github/license/martinzamuner/overlastic\"\u003e\n\u003c/p\u003e\n\nLoad any page inside an overlay (dialog modal, slide-out pane, or whatever else floats your boat). As easy as replacing `link_to` with `link_to_dialog`.\n\n### Benefits\n\n\u003cdetails\u003e\n  \u003csummary\u003eBuilt on top of your existing code\u003c/summary\u003e\u003cbr\u003e\n\n  No need to bend your codebase in weird ways or add lots of lines that feel out of place. Just change a link whenever you want something to open as an overlay. **The rest of your views, controllers and helpers stay the same**.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eReuse your existing overlay views\u003c/summary\u003e\u003cbr\u003e\n\n  Already have a partial for your gorgeous dialog modal? **Just tell Overlastic about it inside an initializer** and it will handle the rest.\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eProgressive enhancement\u003c/summary\u003e\u003cbr\u003e\n\n  Are you a compulsive tab opener? Overlay links render as normal pages if you open them in a new tab. On top of that, everything will **still work perfectly without Javascript**. Overlay links will just turn into _blank links.\n\u003c/details\u003e\n\n\n## Installation\n\nThis gem requires a modern Rails application running [turbo-rails](https://github.com/hotwired/turbo-rails). It supports both import map and node setups.\n\n1. `bundle add overlastic`\n2. `rails overlastic:install`\n\n\n## Usage\n\nMost of the time you'll just need to replace a `link_to` with one of the overlay helpers:\n\n```erb\n\u003c%= link_to_dialog \"Open dialog\", edit_article_path %\u003e\n\u003c%= link_to_pane \"Open slide-out pane\", edit_article_path %\u003e\n\u003c%= link_to_overlay \"Open default overlay type\", edit_article_path %\u003e\n\u003c%= link_to_overlay \"Open dialog\", edit_article_path, overlay_type: :dialog %\u003e\n```\n\nThey work just as `link_to` and accept the same options. You can also pass locals to the overlay view:\n\n```erb\n\u003c%= link_to_dialog \"Open dialog\", edit_article_path, overlay_args: { title: \"Dialog title\" } %\u003e\n```\n\nNested overlays will stack on top of each other. You can instead replace the last one or the whole stack:\n\n```erb\n\u003c%= link_to_dialog \"Open dialog\", edit_article_path, overlay: :last %\u003e\n\u003c%= link_to_dialog \"Open dialog\", edit_article_path, overlay: :first %\u003e\n```\n\nBy default, links and forms inside an overlay will drive the entire page (target _top). To keep navigation within the overlay you can set its target to _self:\n\n```erb\n\u003c%= link_to_dialog \"Open dialog\", edit_article_path, overlay_target: :_self %\u003e\n```\n\nTo break out of an overlay with target _self you can use:\n\n```erb\n\u003c%= link_to \"Open whole page\", edit_article_path, overlay: false %\u003e\n```\n\nA common use case is to render a form inside an overlay. When the form is submitted, you'll validate the data and redirect to a different page if it's successful or render the form again with errors. Overlastic will handle both cases gracefully without any modifications:\n\n```rb\nif @article.save\n  redirect_to article_url(@article), status: :see_other\nelse\n  render :new, status: :unprocessable_entity\nend\n```\n\nIn case the form overlay was nested inside another overlay, you could prefer to apply the redirection to the parent overlay:\n\n```rb\nredirect_to article_url(@article), overlay: :previous, status: :see_other\n```\n\n### Intermediate features\n\n\u003cdetails\u003e\n  \u003csummary\u003eAdapting a view using the overlay variant\u003c/summary\u003e\u003cbr\u003e\n\n  Sometimes, you may want to alter the content of a view depending on whether it's inside an overlay or not. Overlastic defines a new `:overlay` request variant that you can use to create custom views like `new.html+overlay.erb` or inside a controller like so:\n\n  ```rb\n  respond_to do |format|\n    format.turbo_stream.overlay { render :custom_view }\n    format.turbo_stream.any\n    format.html\n  end\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eClosing an overlay from the server\u003c/summary\u003e\u003cbr\u003e\n\n  If you don't need to render any more content you can also close an overlay from the server:\n\n  ```rb\n  if request.variant.overlay?\n    close_overlay\n    # close_overlay :last\n    # close_overlay :all\n    # close_overlay :overlay2\n  else\n    redirect_to articles_url, status: :see_other\n  end\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAttaching to lifecycle events\u003c/summary\u003e\u003cbr\u003e\n\n  If you want to add custom behavior every time an overlay is removed or attached to the DOM, you can listen to their lifecycle events:\n\n  - `overlastic:connected`\n  - `overlastic:disconnected`\n\n  They target the first element in your view to make it easy to add listeners using libraries like Stimulus. You could, for example, have something like this:\n\n  ```html\n  \u003c!-- app/views/overlay/_dialog.html.erb --\u003e\n\n  \u003cdiv data-controller=\"overlay\" data-action=\"overlastic:disconnect-\u003eoverlay#close\"\u003e\n    ...\n  \u003c/div\u003e\n  ```\n\n  The `overlastic:disconnect` event can be paused and resumed, which allows you to run lengthy functions, like animations, before being closed or replaced by another overlay:\n\n  ```js\n  close(event) {\n    event.preventDefault()\n\n    this.leave().then(() =\u003e {\n      event.detail.resume()\n    })\n  }\n  ```\n\n  If there are many overlays being closed at the same time, all of them will be dispatched an `overlastic:disconnect` event. This is great to have independent animations for each of them.\n\u003c/details\u003e\n\n### Advanced features\n\n\u003cdetails\u003e\n  \u003csummary\u003eAppending Turbo Streams to close_overlay\u003c/summary\u003e\u003cbr\u003e\n\n  Sometimes, you may want not only to close an overlay, but also to deliver some other page change using a Turbo Stream:\n\n  ```rb\n  close_overlay do\n    turbo_stream.prepend(\"flash-messages\", \"Deleted!\")\n  end\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eAppending Turbo Streams to every response\u003c/summary\u003e\u003cbr\u003e\n\n  Overlastic can be configured to append a Turbo Stream to every response that contains an overlay.\n  This can be very useful for automatically rendering new flash messages whenever they're available:\n\n  ```rb\n  Overlastic.configure do |config|\n    config.append_turbo_stream do\n      turbo_stream.replace(\"flash-messages\", partial: \"shared/flash_messages\")\n    end\n  end\n  ```\n\n  Then you'd only need to specify a flash message inside your action, when closing an overlay, or when redirecting to a different path:\n\n  ```rb\n  def show\n    flash.now[:notice] = \"You've been noticed!\"\n  end\n\n  # or\n\n  close_overlay notice: \"Deleted!\"\n\n  # or\n\n  redirect_to articles_path, notice: \"Deleted!\", status: :see_other\n  ```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRendering an overlay without an initiator\u003c/summary\u003e\u003cbr\u003e\n\n  Overlastic extends the `render` method inside a controller to add all the same options as `link_to_overlay`. This allows you to force an action to render an overlay, even if it wasn't requested:\n\n  ```rb\n  render :new, overlay: :first, overlay_target: :_self, overlay_args: { title: \"New article\" }\n  # render :edit, overlay: :last, overlay_type: :pane\n  ```\n\u003c/details\u003e\n\n\n## Configuration\n\n```rb\n# config/initializers/overlastic.rb\n\nOverlastic.configure do |config|\n  config.overlay_types = %i[dialog pane]\n  config.default_overlay = :dialog # Options: One of the defined overlay types\n  config.default_action = :stack # Options: :stack, :replace_last, :replace_all\n  config.default_target = :_top # Options: :_top, :_self\n\n  # You can define a custom partial for each overlay type\n  config.dialog_overlay_view_path = \"overlays/dialog\"\n  config.pane_overlay_view_path = \"overlays/pane\"\n\n  # You can append Turbo Streams to every response containing an overlay\n  config.append_turbo_stream do\n    turbo_stream.replace(\"flash-messages\", partial: \"shared/flash_messages\")\n  end\nend\n```\n\n\n## UI customization\n\nOverlastic comes with default views for both the dialog and pane overlays. They are intended to provide an easy way to try the gem. For real-world usage you're expected to implement your own UI elements, or use something like [Bootstrap](https://getbootstrap.com) or [TailwindCSS Stimulus Components](https://github.com/excid3/tailwindcss-stimulus-components).\n\n\u003cdetails\u003e\n  \u003csummary\u003eDefault overlays\u003c/summary\u003e\u003cbr\u003e\n\n  **Dialog**\n\n  \u003cimg src=\"assets/dialog.png?sanitize=true\" width=\"600\" alt=\"Dialog\"\u003e\n\n  \u003cbr\u003e\n\n  **Pane**\n\n  \u003cimg src=\"assets/pane.png?sanitize=true\" width=\"600\" alt=\"Dialog\"\u003e\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eGenerate customizable views\u003c/summary\u003e\u003cbr\u003e\n\n  Overlastic provides a generator to build your own views using the default overlays as a base. It's not advisable, though. You're better off using a UI library.\n\n  ```sh\n  # Available options: inline, tailwind\n  ./bin/rails generate overlastic:views --css tailwind\n  ```\n\u003c/details\u003e\n\n\n## Development\n\n\u003cdetails\u003e\n  \u003csummary\u003eRunning the demo application\u003c/summary\u003e\u003cbr\u003e\n\n  - First you need to install dependencies with `bundle \u0026\u0026 yarn \u0026\u0026 yarn build`\n  - Then you need to setup the DB with `rails db:setup`\n  - Lastly you can run the demo app with `rails server --port 3000`\n\u003c/details\u003e\n\n\u003cdetails\u003e\n  \u003csummary\u003eRunning the tests\u003c/summary\u003e\u003cbr\u003e\n\n  - You can run the whole suite with `./bin/test test/**/*_test.rb`\n\u003c/details\u003e\n\n\n## License\n\nOverlastic is released under the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinzamuner%2Foverlastic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinzamuner%2Foverlastic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinzamuner%2Foverlastic/lists"}