fceruti

fceruti

Surface Boxicon - a component library that wraps the boxicons library (My first library :))

Hey everyone!

For a personal project I’m working, I need to use boxicons in surface templates. Since the package didn’t exist, I decided to take the matter into my own hands. The results are here:

https://github.com/fceruti/surface-boxicon

I feel like a leveled up or something.

PS: The library is very small, so I’d very happy if you could check it out and point out things you would have don’t better. Anything. Even style pointers are most welcomed.

Most Liked

msaraiva

msaraiva

Broadway Core Team

Hi @fceruti. Nice work!

One thing to keep in mind is that defining modules is more expensive than defining multiple function clauses so since all components have the same props, I believe you would have a more consistent API, along with faster compilation, if you define a single component with name and maybe also a type prop to differentiate each icon. Something like:

def render(%{name: "video-plus", type="solid"} = assigns) do
  ~F[<svg ... width={@size} height={@size} class={@class} .../></svg>]
end

def render(%{name: "video-plus", type="regular"} = assigns) do
  ~F[<svg ... width={@size} height={@size} class={@class} .../></svg>]
end

def render(%{name: "bell", type="solid"} = assigns) do
  ~F[<svg ... width={@size} height={@size} class={@class} .../></svg>]
end

def render(%{name: "bell", type="regular"} = assigns) do
  ~F[<svg ... width={@size} height={@size} class={@class} .../></svg>]
end
...

Then you could use it like:

<BoxIcon name="bell" type="solid"/>
fceruti

fceruti

OK, so I managed to both finished the book and the library :partying_face:

I added a way to load less functions using configuration

config :surface_boxicon,
  icons: [
    regular: ["calendar", "chvron-down"],
    solid: ["hand", "file-md"],
    logos: ["docker"]
  ]

But it turned out to be completely unnecessary, the Module is compiling super fast with all the icons. The current Boxicon module looks like this:

defmodule Boxicon
  ...

  def render(assigns) do
    ~F[<svg xmlns="http://www.w3.org/2000/svg" width={"#{@size}"} height={"#{@size}"} class={"#{@class}"} viewBox="0 0 24 24">{render_content(@type, @name)}</svg>]
  end

  for %Boxicon.Source{type: type, name: name, content: content} <- @icons do
    defp render_content(unquote(Atom.to_string(type)), unquote(name)),
      do: unquote(Phoenix.HTML.raw(content))
  end

  defp render_content(_, _), do: ""

end

I’m not sure why this is the case, but maybe the compiler is having an easier time dealing with string signatures instead of maps. If I create one render function per icon, pattern matching on the assigns map, I go back to lousy compile times.

fceruti

fceruti

Since this thread was first published, I migrated my code from Surface to vanilla LiveView.

Here is a new package for everyone using heex files: Boxicons Heex

I think the API to use it, it’s pretty clever:

      <Box.icons
        type="regular"
        name="calendar"  
        size="64" 
        class="icon green"
      />

Have a nice day!

PS: It’s updated to use boxicons 2.1.1

kip

kip

ex_cldr Core Team

You wouldn’t necessarily need to implement any macros, but meta programming would still be useful. Something like:

defmodule Boxicon do
  
  @doc "Type of the icon"
  prop type, :string, values!: ["solid", "regular", "logos"]

  @doc "Name of the icon"
  prop name, :string, required: true

  @doc "Width & height of the icon"
  prop size, :integer, default: 24

  @doc "CSS classes for the wrapping svg element"
  prop class, :string, default: "icon"

  @icons "populate icons from static data at compile time"

  for {type, name, path} <- @icons do
    def render(%{name: unquote(name), type: unquote(type)} = assigns) do
      ~F[<svg xmlns="http://www.w3.org/2000/svg" width={"#{@size}"} height={"#{@size}"} class={"#{@class}"} viewBox="0 0 24 24"><path d=unquote(path)/></svg>]
    end
  end
end

Happy to help with how to structure the data to populate @icons at compile time if you need.

Malian

Malian

@edisonywh Yes and no :slight_smile:

What you propose is perfectly fine and it will work! You will lose some Surface features, like compilation checks, and properties documentations.

@fceruti you can follow what @miguels did with ExHeroicons by creating a Phoenix helper, boxicon("video-plus", type: "solid") for example, and Surface will “just” uses that helper. In that case, you will be able to use the icons both with Phoenix with and without Surface.

Where Next?

Popular in Libraries Top

hpopp
After just over two years in development, this latest version of Pigeon is what I finally consider done in regards to my original vision ...
New
pkrawat1
Hey guyz We at @aviabird are working on a payment library in elixir/phoenix. We are targeting March 2018 to add 56 Gateways to it. Have...
New
oltarasenko
Dear Elixir community, After a year of development, bug fixes, and improvements, we are proudly ready to share the release of Crawly 0.1...
New
achempion
Hi, I would like to tell about my initiative to further maintain and develop Waffle project which is the fork of Arc library. The progre...
New
riverrun
I’ve just released version 3 of Comeonin, a password hashing library. The following small changes have been made: changes to the NIF c...
New
tmbb
I’ve decided to create this topic to discuss optimization possibilities for something like Phoenix LiveView. I’ve created this topic unde...
New
vic
Expat is a tiny experiment I did for extracting patterns and being able to reuse them (compose and share patterns between elixir librarie...
New
mattludwigs
Grizzly is a library for working with Z-Wave devices. Z-Wave is a low-frequency radio protocol for controlling smart home devices on a me...
New
mischov
import Meeseeks.CSS html = HTTPoison.get!("https://news.ycombinator.com/").body for story &lt;- Meeseeks.all(html, css("tr.athing")) do...
New
mplatts
With HEEX released we decided to start a components library using Tailwind CSS - check it out here: Petal Components. We also have a boi...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3268 119930 1237
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New

Sub Categories:

We're in Beta

About us Mission Statement