Skip to content

Commit

Permalink
Merge pull request #587 from AnswerDotAI/toast-duration
Browse files Browse the repository at this point in the history
configurable toast duration
  • Loading branch information
jph00 authored Nov 21, 2024
2 parents 61ecb09 + 02e95a7 commit 55fc762
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
38 changes: 24 additions & 14 deletions fasthtml/toaster.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,17 @@
}
.fh-toast {
background-color: #333; color: white;
padding: 12px 20px; border-radius: 4px; margin-bottom: 10px;
padding: 12px 28px 12px 20px; border-radius: 4px; margin-bottom: 10px;
max-width: 80%; width: auto; text-align: center;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
position: relative;
}
.fh-toast-dismiss {
position:absolute; top:0.2em; right:0.4em;
line-height:1em; padding: 0 0.2em 0.2em 0.2em; border-radius:inherit;
transform:scaleY(0.8); transform:scaleX(1.);
pointer-events:auto; cursor:pointer;
background-color:inherit; color:inherit; filter:brightness(0.85);
}
.fh-toast-info { background-color: #2196F3; }
.fh-toast-success { background-color: #4CAF50; }
Expand All @@ -24,36 +32,38 @@
"""

toast_js = """
export function proc_htmx(sel, func) {
htmx.onLoad(elt => {
export function proc_htmx(sel, func) {{
htmx.onLoad(elt => {{
const elements = any(sel, elt, false);
if (elt.matches && elt.matches(sel)) elements.unshift(elt);
elements.forEach(func);
});
}
proc_htmx('.fh-toast-container', async function(toast) {
}});
}}
proc_htmx('.fh-toast-container', async function(toast) {{
await sleep(100);
toast.style.opacity = '0.8';
await sleep(3000);
await sleep({duration});
toast.style.opacity = '0';
await sleep(300);
toast.remove();
});
}});
proc_htmx('.fh-toast-dismiss', function(elem) {{
elem.addEventListener('click', (e) => {{ e.target.parentElement.remove() }});
}});
"""

def add_toast(sess, message, typ="info"):
assert typ in ("info", "success", "warning", "error"), '`typ` not in ("info", "success", "warning", "error")'
sess.setdefault(sk, []).append((message, typ))

def render_toasts(sess):
toasts = [Div(msg, cls=f"fh-toast fh-toast-{typ}") for msg,typ in sess.pop(sk, [])]
return Div(Div(*toasts, cls="fh-toast-container"),
hx_swap_oob="afterbegin:body")
toasts = [Div(msg, Span('x', cls='fh-toast-dismiss'), cls=f"fh-toast fh-toast-{typ}") for msg,typ in sess.pop(sk, [])]
return Div(Div(*toasts, cls="fh-toast-container"), hx_swap_oob="afterbegin:body")

def toast_after(resp, req, sess):
if sk in sess and (not resp or isinstance(resp, (tuple,FT,FtResponse))): req.injects.append(render_toasts(sess))

def setup_toasts(app):
app.hdrs += (Style(toast_css), Script(toast_js, type="module"))
def setup_toasts(app, duration:float=10.):
app.hdrs += (Style(toast_css), Script(toast_js.format(duration=1000*duration), type="module"))
app.after.append(toast_after)

4 changes: 3 additions & 1 deletion nbs/tutorials/quickstart_for_web_devs.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,9 @@
"\n",
"1. `setup_toasts` is a helper function that adds toast dependencies. Usually this would be declared right after `fast_app()`\n",
"2. Toasts require sessions\n",
"3. Views with Toasts must return FT or FtResponse components."
"3. Views with Toasts must return FT or FtResponse components.\n",
"\n",
"💡 `setup_toasts` takes a `duration` input that allows you to specify how long a toast will be visible before disappearing. For example `setup_toasts(duration=5)` sets the toasts duration to 5 seconds. By default toasts disappear after 10 seconds."
]
},
{
Expand Down

0 comments on commit 55fc762

Please sign in to comment.