Transforming Notebook Names to Cards

I have Jupyter notebooks in `nbs/`. I want to turn them into cards from the filenames, without having to read the file contents.

I'm on a train without wifi, so I'll make simple cards for now and maybe later convert them to MonsterUI.

from fasthtml.common import *
from IPython.display import display, HTML
from pathlib import Path
import regex
nb_dir = Path('.')
nbs = L(sorted(nb_dir.glob('*.ipynb'), reverse=True)).map(str)
nbs
nbs[0]
x = nbs[0]
x
L(regex.findall(r"\d+", x))
def get_date_from_fname(fname):
    year, month, day = L(regex.findall(r"\d+", fname))[0:3]
    return f"{year}-{month}-{day}"
get_date_from_fname(x)
get_date_from_fname('2024-12-23-Exploring-execnb-and-nb2fasthtml.ipynb')
L(regex.finditer(r"\d+", x))
x[11:][:-6].replace('-', ' ')
def get_title_from_fname(fname): return fname[11:][:-6].replace('-', ' ').replace('_', ' ')
[get_title_from_fname(x) for x in nbs]
L(nbs).map(get_title_from_fname)
date = get_date_from_fname(x)
title = get_title_from_fname(x)
a = Div(Header(H2(title)),I(date),style="border:1px lightgray solid;padding:10px;")
a
HTML(to_xml(a))

I have wifi now! Monster UI cards use FrankenUI Card CSS, which is defined in https://github.com/franken-ui/ui/blob/master/src/lib/shadcn-ui/components/card.ts which apply Tailwind classes like pt-0. It's a bit involved to set up that whole build pipeline to extract and modify card styles, and I have to get off this train in 2 stops, so for now I'll continue with the simple CSS one-liner.

def Card(fname):
    date = get_date_from_fname(fname)
    title = get_title_from_fname(fname)
    c = Div(Header(H2(title)),I(date),style="border:1px lightgray solid;padding:10px;display:grid;grid-template-rows: max-content 30px 1fr;")
    return c
HTML(to_xml(Card(x)))
HTML(to_xml(Div(*L(nbs).map(Card), style="margin:1em auto;display:grid;grid-template-columns:repeat(auto-fill, minmax(180px,1fr));grid-gap:20px;")))

I asked AI: How to make the cards look better?

def Card(fname):
    date = get_date_from_fname(fname)
    title = get_title_from_fname(fname)
    style = """
        border: 1px solid #e2e8f0;
        padding: 1.25rem;
        border-radius: 0.5rem;
        background: white;
        box-shadow: 0 1px 3px rgba(0,0,0,0.12);
        transition: transform 0.2s ease;
        cursor: pointer;
    """
    header_style = "margin-bottom: 0.5rem; font-weight: 600;"
    date_style = "color: #666; font-size: 0.875rem;"
    
    c = Div(
        Header(H2(title, style=header_style)),
        I(date, style=date_style),
        style=style,
        onmouseover="this.style.transform='translateY(-2px)';this.style.boxShadow='0 4px 6px rgba(0,0,0,0.1)'",
        onmouseout="this.style.transform='none';this.style.boxShadow='0 1px 3px rgba(0,0,0,0.12)'"
    )
    return c
# Container style with some padding and max-width
container_style = """
    margin: 2em auto;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px,1fr));
    grid-gap: 1.5rem;
    padding: 1rem;
    max-width: 1200px;
"""

HTML(to_xml(Div(*L(nbs).map(Card), style=container_style)))

This adds: