Table rendering helper
The answer, which may not be what you were hoping to hear, is that for generating more than a couple lines of HTML, partials are a much better fit than content_tag et al. Put your table code in a partial in e.g. views/shared/_semantic_table.slim.html:

table class="ui basic striped table"
  thead
    tr
      - headers.each do |header|
        th = header
  tbody
    = yield


...and then make your helper render it with the given arguments:

def semantic_table(headers, &amp;block)
  render partial: "shared/semantic_table",
    locals: { headers: headers }, &amp;block
end


Helpers are great for encapsulating logic that doesn't belong in a view/partial or in the controller, or adds a lot of noise: formatting data, choosing/combining several attributes, that sort of thing. But when you just want to spit out a bunch of boring HTML, you can't really beat a simple partial.

Edit

Re: your comment, that's interesting. I'm guessing Rails is using instance_eval somewhere, so your block with render @users is being evaluated in some different context where @users is nil. This is surprising, but I don't have a computer in front of me to dig further.

There may be a workaround that I'm not thinking of, but barring that, the simplest solution is to drop the helper entirely and just use the partial directly in your view:

= render partial: "shared/semantic_table", locals: { headers: headers } do
  = render @users


I'm not 100% sure that'll work, since didn't anticipate the other issue, but I think it will.

Another solution is to get rid of the block and pass in the objects directly:

def semantic_table(headers, objects)
  render partial: "shared/semantic_table",
    locals: { headers: headers, objects: objects }
end


...and then in the partial call render objects instead of yield.

Of course, this is more constraining than a block, but it may suffice for your use case.