{"id":13544199,"url":"https://github.com/tobymao/snabberb","last_synced_at":"2026-03-02T16:36:39.568Z","repository":{"id":36547128,"uuid":"226210175","full_name":"tobymao/snabberb","owner":"tobymao","description":"A simple component view framework for Ruby Opal based on Snabbdom","archived":false,"fork":false,"pushed_at":"2023-03-15T21:43:21.000Z","size":236,"stargazers_count":44,"open_issues_count":2,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-12-25T19:02:26.429Z","etag":null,"topics":["components","opal","ruby","snabbdom","views"],"latest_commit_sha":null,"homepage":null,"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/tobymao.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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":"2019-12-05T23:57:13.000Z","updated_at":"2025-11-28T21:06:48.000Z","dependencies_parsed_at":"2024-10-28T12:19:33.610Z","dependency_job_id":"628a9650-0d31-4a81-a7a7-6e73954cdfaf","html_url":"https://github.com/tobymao/snabberb","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/tobymao/snabberb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobymao%2Fsnabberb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobymao%2Fsnabberb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobymao%2Fsnabberb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobymao%2Fsnabberb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tobymao","download_url":"https://codeload.github.com/tobymao/snabberb/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tobymao%2Fsnabberb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30009705,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-02T15:15:59.058Z","status":"ssl_error","status_checked_at":"2026-03-02T15:15:58.758Z","response_time":60,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6: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":["components","opal","ruby","snabbdom","views"],"created_at":"2024-08-01T11:00:43.608Z","updated_at":"2026-03-02T16:36:39.526Z","avatar_url":"https://github.com/tobymao.png","language":"Ruby","funding_links":[],"categories":["Uncategorized","Ruby"],"sub_categories":["Uncategorized"],"readme":"# Snabberb\n\nSnabberb is a simple Ruby view framework built on [Opal](https://github.com/opal/opal) and [Snabbdom](https://github.com/snabbdom/snabbdom).\n\nYou can write reactive views in plain Ruby that compile to efficient Javascript.\n\n## Inline Example\n\n```ruby\nrequire 'opal'\nrequire 'snabberb'\n\nclass TextBox \u003c Snabberb::Component\n  needs :text\n  needs :selected, default: false, store: true\n\n  def render\n    onclick = lambda do\n      store(:selected, !@selected)\n    end\n\n    style = {\n      cursor: 'pointer',\n      border: 'solid 1px rgba(0,0,0,0.2)',\n    }\n\n    style['background-color'] = 'lightblue' if @selected\n\n    h(:div, { style: style, on: { click: onclick } }, [\n      h(:div, @text)\n    ])\n  end\nend\n\n\n# Assuming you have a DOM element with ID=app\nTextBox.attach('app', text: 'hello world')\n\n# Or you can get the HTML string for isomorphic applications\nTextBox.html(text: 'hello world')\n```\n\n## Examples\n[Rack App](examples/rack)\n\n[Roda App with HTML Prerendering](examples/roda)\n\n[18xx Board Game Engine](https://github.com/tobymao/18xx)\n\n## Usage\n\n### Creating DOM Elements With h\n\nSubclass Snabberb::Component and override #render to build divs using \\#h.\n\nRender should only return one root element.\n\n\\#h takes either a DOM symbol (:div, :span, :a, ...) or another Snabberb::Component class.\n\n```ruby\n...\nclass DomExample \u003c Snabberb::Component\n  def render\n    h(:div)\n  end\nend\n\nclass ComponentExample \u003c Snabberb::Component\n  def render\n    h(OtherComponent)\n  end\nend\n```\n\nLike Snabbdom, \\#h with DOM elements can take props which take the form of a dict.\n\n```ruby\n...\nclass PropsExample \u003c Snabberb::Component\n  def render\n    h(:div, { style: { display: 'inline-block' }, class: { selected: true } })\n  end\nend\n```\n\nComponents do not take props, instead they take [needs](#Needs) which are dependent arguments.\n\n```ruby\n...\nclass PassingNeedsExample \u003c Snabberb::Component\n  def render\n    h(ChildComponent, need1: 1, need2: 2)\n  end\nend\n```\n\n\\#h can also be nested with a child or multiple children.\n\n```ruby\n...\nclass NestedExample \u003c Snabberb::Component\n  def render\n    h(:div, [\n      h(ChildComponent, need1: 1, need2: 2),\n      h(:div, { style: { width: '100px' } }, [\n        h(:div, 'hello'),\n      ])\n    ])\n  end\nend\n```\n\n### Needs\n\nComponents can define needs which allow parent components to pass down arguments. They can also be stateful which allows changes to propogate easily throughout the application.\n\nNeeds are by default required. They can be set with default values. Needs are accesible with instance variables that are automatically set.\n\n```ruby\n...\nclass NeedsExample \u003c Snabberb::Component\n  needs :name\n  needs :value, default: 0, store: true\n\n  def render\n    onclick = lambda do\n      store(:value, @value + 1)\n    end\n\n    h(:div, [\n      h(:div, @name),\n      h(:div, { on: { click: onclick} }, @value),\n    ])\n  end\nend\n```\n\nWhen simple state changes must be tracked, a need can define store: true. This will use the stored value of this key which is set on the root node.\nThe precedence of need values is stored \u003e passed needs \u003e default value.\n\nNeeds can be set with #store which will trigger a view update. Snabberb uses Snabbdom to update the DOM, so only the differences in the DOM are changed.\n\n### Prerendering\n\nYou can prerender your HTML by calling\n\n```ruby\nSnabberb.prerender_script('LayoutClass', 'ApplicationClass', 'application_id', javascript_include_tags: '', **needs)\n```\n\nA detailed example can be found [in the Roda example](examples/roda).\n\n### Generating HTML from a File\n\nYou can generate HTML from a component with a file.\n\nSnabberb.html\\_script('path/to/my\\_component.rb', **needs)\n\nThis reads in the ruby file at the path and generates javascript that calls html on the CamelCased version of the file name.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'snabberb'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install snabberb\n\n## Development\n\n```\nbundle install\nbundle exec rake\n```\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/tobymao/snabberb.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftobymao%2Fsnabberb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftobymao%2Fsnabberb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftobymao%2Fsnabberb/lists"}