Tutorial: Build a To-Do app in Python with Dash!

Hello!

I wanted to share a new tutorial I created, that will teach you how to use Dash and mantine components to create a beautiful, To-Do App:

To-Do app are great exercices to understand how to handle CRUD operations (create, read, update, delete) within an app. And for Dash plotly, it means using pattern matching callbacks.

In this tutorial you’ll find:

  • An introduction to DMC (Dash Mantine Components) and its components
  • How to use pattern matching callbacks for dynamic interactions
  • How to use CSS styling in a Dash context
  • How to use dcc.Store with localStorage (part 2)

The tutorial is in two parts, and I plan on writing a third part that uses Patch() :slight_smile:

Let me know what you think …
and if it was useful to you!

Fran

2 Likes

Hi @spriteware

Nice tutorial!

You ask in one section:

You might wonder why we use a dcc.Input wrapped in a dmc.Text component.

Yes, I actually did wonder that :thinking:

Using a dmc.TextInput works pretty well. Plus using dmc.Group is a little simpler than using grid and columns for each task:


content = dmc.Group([
    dmc.Checkbox(size="md"),
    dmc.TextInput(
        debounce=True,
        classNames={"input": "shadow-input"}
    ),
    dmc.ActionIcon(
        DashIconify(icon="tabler:x", width=20),
        variant="transparent",
        color="gray",
        className="task-del-button"
    )
], className="task-container", m="lg")

Then tweek the .css file


.shadow-input {
   border-color: transparent;
    &:focus-within {
      outline: 1px solid black;;
      border-color: transparent;
  }
}

.task-container:has(.mantine-Checkbox-root[data-checked]) .mantine-TextInput-input {
    text-decoration: line-through;
    color: gray;
}

.task-del-button:hover {
    color: red;
}

I like the way you did the strike-through of the completed items with CSS instead of a callback :tada:

1 Like

Hello @AnnMarieW

Thanks for your ideas!

Yes I could have used dmc.TextInput. It makes more sense. But I found a little more complicated to style it (CSS overrides needed for height/padding/text size) while the dcc.Input do not modifies the styles from the parent, it just adds a border. It’s visible when embedding a dmc.TextInput inside a dmc.Title. I admit it’s maybe a bit intricate :sweat_smile:, but I wanted to show how to “make any element modifable” rather than “adding text inputs everywhere”.

At the end I think you’re right, it makes more sense (thus better for a tutorial).

Unfortunately, dmc.Group do not allow making the middle element (the input) growing. The default size for the input almost fills the container, though.
→ edit: or it requires grow=True on the group and style={"flex-grow": 1} on the input.

I didn’t know about CSS nesting, thanks for this! :smiley: