BartOtten

BartOtten

Proposal

  • Support DOM patching of the HTML link element for a favicon.
  • Add the special @page_favicon assign mimicking the @page_title assign so each page can have it’s own dynamic favicon; supporting multiple tabs for an application with different ‘statuses’.

Reason
Many modern web applications have dynamic favicons. These dynamic favicons are used to notify browser users of events or statuses. For example: unread messages or a CI build status. As those use cases are quite common, providing such functionality seems to fit the ‘no Javascript’-philosophy. Additionaly it seems to align with the automagic @page_title.

Because the root layout from the Plug pipeline is rendered outside of LiveView, the contents cannot be dynamically changed. The one exception is the <title> of the HTML document. Phoenix LiveView special cases the @page_title assign to allow dynamically updating the title of the page, which is useful when using live navigation, or annotating the browser tab with a notification. For example, to update the user’s notification count in the browser’s title bar, first set the page_title assign on mount
Live layouts — Phoenix LiveView v1.2.5

Current State

  • The HTML link element for favicons is placed in layout/root_live.html.heex. No native logic is in place to update it in the DOM and there is no @page_favicon.
  • The HTML title element is placed in `layout/root_live.html.heex. Native logic is in place to update the element in the DOM when the @page_title assignment is changed.

Todo

  • get approval for feature
  • research possibilities
  • draft design
  • get approval for design
  • implement

I am willing to work on this as contribution to the community.

Links
[LiveView Dynamic Favicon?]
[https://medium.com/@alperen.talaslioglu/building-dynamic-favicon-with-javascript-223ad7999661]

Showing Posts 1 to 10

AndyL

AndyL

Here is a working prototype for Dynamic Favicon. A streamlined solution that follows the style of live_title_tag would be great. I will help. :wink:

AndyL

AndyL

Here’s some rough design ideas:

Let there be a special assign @favicon_href

The live_favicon_tag would go into layout/root_live.html.heex

<%= live_favicon_tag assigns[:favicon_href] || "/images/favicon.ico" %>

The live_favicon_tag function would emit the following HTML

<link id="phx-favicon" rel="icon" type="image/x-icon" href="/images/favicon.ico"/>

Add an event listener to the client javascript

window.addEventListener("phx:change-favicon", (e) => {
  var href = e.detail.href 
  var fabtag = document.getElementById('phx-favicon') 
  fabtag.href = href
})

On the server, when the LiveView process detects that @favicon_href has changed, push an event to the client:

push_event(socket, "change-favicon", %{href: @favicon_href})}

With this approach, add-on packages (like live_dashboard) could add their own favicon images to priv/images, and then use their own favicons in their particular LiveViews.

10
Post #2
josevalim

josevalim

Creator of Elixir

Awesome job @AndyL! I am not sure if this is such a common use case to warrant inclusion on LiveView, but that’s all the pieces needed for anyone who wants to roll with it. :slight_smile:

PJextra

PJextra

It would be a great quick win!

BartOtten

BartOtten OP

Great example!

  • Should it support a size opt (or list of sizes and return multiple elements)?
  • SVG icons can be styled with CSS; removing the need for multiple images (in an ico container). Should it support that use case and if so, how? Blog post: Building an adaptive favicon

The other option is to keep is really simple and let a lib handle more advanced usecases :slight_smile:

AndyL

AndyL

Didn’t know about SVG icons - super nice! Pretty well supported on desktop browsers, less on mobile. Also learned that people sometimes use multiple favicon links, to give browsers an way to fall back to supported types.

I think there are two alternatives to attack this problem: manual coding like I did in the prototype, or editing LiveView itself. I don’t think this can be done with a Library, because there is no way for a Library to inject behavior into the LiveView JS. Is this right?

I looked in the LiveView code to understand live_title_tag - there seems to be three key areas in the code:

The code itself looks pretty straightforward - with a good amount of testing support.

Generating the appropriate favicon mime type could be done by checking the file extension of the href - this could be done in the javascript.

size opt

I’m not sure what the size opt does - I’ve always used ‘auto’ size.

The other option is to keep is really simple

If we could do something simple to streamline the 80% case, people could always fall back to a manual approach if needed.

BartOtten

BartOtten OP

Chose to keep the assign key generic; not sure of we can pass components to it (its too late).

If we can the favicon_tag function can use the (to be updated) DOM diffing too as no attribute is in the name. This allow for the simple approach by default using it as href when assigned a binary. Keeping the advanced usage of favicons to a lib which can simply pass a full icon link element. :slight_smile:

Too be continued….first let’s see if the draft PR survives the public exposure.

https://github.com/phoenixframework/phoenix_live_view/pull/2087

Won’t take long before you can play Doom in the browsers` tab bar…

AndyL

AndyL

PR looks great - beautiful screen shot!

I’m curious - did you intend that it should be possible to update multiple favicon links, or just one? If multiple: would you assign an array of hrefs to @favicon, or use some other convention?

BartOtten

BartOtten OP

Last night I looked at support for multiple icons

Phoenix LiveView is awesome at diffing and sending the least amount of data over the wire. I am trying to keep that in honor. As a result I have chosen to use a simple string replace.

The free schema also makes it easier to use online favicon generators that generate a bunch of PNG files for you. Just unzip and place in a subfolder of a variant. SVG scale so don’t need a subfolder. See pseudo code:

# pseudo code supports multiple schema’s
<.live_favicon href="/images/svg/@dynamic.svg" />
<.live_favicon href="/images/status/@dynamic/favicon-32x32.png" />
<.live_favicon href="/images/status/@dynamic/favicon-16x16.png" />

When a new @dynamic value is assigned, the href is split in 3 parts: prefix, @dynamic and suffix. The dynamic value is replaced with the value assigned.

static: /images/status/
dynamic: “new_message”
static: /favicon-32x32.png

Only the dynamic part is sent over the wire on socket assign updates. Just like…LiveView does already :slight_smile:

{"f": {   "dynamic": "new_message"}}

When href is defined without a dynamic, the helper assumes the user needs full control over the href and just passes it through. Thus supporting base64 encoded data and one-off use cases.

This also allow me to add ‘class’ to support those fancy dynamic SVG’s.

As you like screenshots:

BartOtten

BartOtten OP

Update: the draft PR is rejected

Not sure if the presented solution really covers the use cases as mentioned above. It does cover the simple first case in the draft though, so it’s not a surprise. Will check later.

Where Next? Top

Trending in Questions Top

stjefim
Hello! Suppose you are building workflow (order / task / payment) processing system with the following requirements: Each workflow con...
New
water
I’m aware of 2 such projects, are there others? git: GitHub - team-alembic/realworld: A fullstack Phoenix LiveView application with back...
New
itzmidinesh
Hi all, I’m working on a Phoenix project where I need to make external HTTP requests and I’m trying to choose between Req and HTTPoison....
New
peck
Hi everyone. My team and I have been working on a fairly modest app based around video streaming and chat, but we’ve landed a customer t...
New
leoschweizer
Hi, we run different LLM models across a cluster, with each node loading a configurable subset. Model-specific queues let nodes consume ...
New
csmr
Hi all, I’m new here and would like to hear peoples views on my Elixir/Phoenix based game-engine! :smiley: Mutonex gamedesign was finish...
New
Stef-Verniers
Hello I’ve been coding in Elixir for almost two years now because of my current job where we implemented Elixir in our application. But ...
New

Other Trending Topics Top

dominicletz
Hey there, I haven’t seen a list of useful Elixir specific skills for the popular AI tools yet so I’m starting one here with my first. ...
New
mudasobwa
I fully migrated to my own harness from Anthropic/Gemini and I think it’s time to share it. Welcome DSH, the DeepSeek Harness, fully writ...
New
KristerV
Hey. Is there anyone here who creates agents in their apps? Not talking about using agents, but creating them. I’m finding it pretty diff...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New
OndrejValenta
(I just needed to vent somewhere and LinkedIn is full of hope, or hype, I’m not sure which exactly) AI dream has many faces, but general...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews