Design System / Système de design
Update date : 2026-05-16 02:50
Index and general conventions for Streamlit in Snowflake apps built with pinky-streamlit.
Index et conventions générales pour les apps Streamlit in Snowflake construites avec pinky-streamlit.
Documentation
| File / Fichier | Content / Contenu |
|---|---|
| DESIGN_SYSTEM.md (this file / ce fichier) | Index, architecture, general conventions, page patterns |
| DESIGN_SYSTEM_PALETTE.md | Palette, tokens, dark mode, CSS variables, icons, spacing |
| DESIGN_SYSTEM_CORE.md | Session, page setup, cache strategies, CRUD operations, NaN→None convention |
| DESIGN_SYSTEM_UI.md | UI components (ui_components/ — planned L2) |
Package architecture / Architecture du package
src/pinky_streamlit/
├── __init__.py ← public API — flat re-exports from core/
├── core/ ← L1: stable — implemented
│ ├── constants.py ← PALETTES, PALETTE, ICONS, Icon, Palette, PaletteColors
│ ├── session.py ← get_session(), LocalSessionConfig
│ ├── db.py ← load_analytic, load_crud, load_static, load_nocache
│ │ update_data, insert_data, invalidate_crud, add_status_icons
│ ├── page.py ← setup_page(), Logo, AppFont, DEFAULT_FONT
│ └── assets/
│ ├── style.css ← Streamlit normalization, CSS variables, layout
│ └── fonts/DMSans.woff2 ← Default font (base64-embedded)
└── ui_components/ ← L2: planned
├── text/ ← header, badge, empty_state
├── widgets/ ← filters, FilterConfig, action_grid
├── data/ ← metric, detail, data_editor, drilldown
├── layouts/ ← card_grid, divider
└── status/ ← status_card, StatusStepConfig
CSS architecture — module-scoped / Architecture CSS — par module :
- style.css covers Streamlit normalization only (variables, layout, native component overrides). / style.css couvre uniquement la normalisation Streamlit (variables, layout, overrides des composants natifs).
- Each ui_components/ module owns its .css file, injected on demand by setup_page(). / Chaque module ui_components/ possède son .css, injecté à la demande par setup_page().
- Never add component styles to style.css. / Ne jamais ajouter de styles de composants dans style.css.
Page pattern / Pattern de page
Every SiS page follows this structure. / Chaque page SiS suit cette structure.
from functools import partial
from pinky_streamlit import setup_page, load_analytic, PALETTES
# Call once at the top — before any other st.* calls
# Appeler une seule fois en haut — avant tout autre appel st.*
messages_container, main_container, df = setup_page(
session=session,
loaders=[partial(load_analytic, _query_fn=my_query, key="data")],
palette=PALETTES.PYTHIA,
)
try:
with main_container:
st.title("My page")
st.dataframe(df)
except Exception as e:
messages_container.error(str(e), icon="‼️")
Rules / Règles :
- messages_container → always above main_container. Use .error() / .warning() from the except block only. / Toujours au-dessus de main_container. Utiliser .error() / .warning() uniquement depuis le bloc except.
- main_container → wrap all page content with with main_container:. / Envelopper tout le contenu de la page avec with main_container:.
- setup_page() returns (messages_container, main_container, *loader_results) — one result per loader in declaration order. / Retourne (messages_container, main_container, *loader_results) — un résultat par loader dans l'ordre de déclaration.
CRUD page pattern / Pattern page CRUD
from functools import partial
from pinky_streamlit import (
setup_page, load_crud, invalidate_crud, update_data, insert_data, PALETTES
)
KEY = "building"
TABLE = "USER_CONFIG_BUILDINGS"
@st.dialog(" ", width="large")
def add_building():
with st.form("form-add"):
code = st.text_input("Code")
submitted = st.form_submit_button("Save")
if submitted:
insert_data(
session=session, data=[{"CODE": code}], key="CODE", table=TABLE,
on_success=lambda: invalidate_crud(KEY),
)
st.rerun()
messages, main, df = setup_page(
session, loaders=[partial(load_crud, query_fn=my_query, key=KEY)]
)
with main:
if st.button("Add"):
add_building()
st.dataframe(df)
Filter form — avoid unnecessary reruns / Formulaire de filtres — éviter les reruns inutiles
Use st.form when you have 3+ combined filters in a CRUD app. / Utiliser st.form avec 3+ filtres combinés dans une app CRUD.
| Situation | Approach / Approche |
|---|---|
| 3+ combined filters, CRUD app | st.form — single rerun on submit / rerun unique au clic |
| 1–2 simple filters, analytic dashboard | Free widgets — immediate rerun OK / rerun immédiat OK |
| Filters with dependency (B depends on A) | Free widgets — rerun updates options |
| Sidebar pills / navigation | Free widgets — immediate feedback expected |
Multi-page navigation / Navigation multi-pages
# constants.py — centralize page config / centraliser la config des pages
PAGES_CONFIG: dict[str, dict] = {
"home": {"icon": str(ICONS.HOME), "title": "Home", "path": "pages/home.py"},
"settings": {"icon": str(ICONS.SETTINGS), "title": "Settings", "path": "pages/settings.py"},
"buildings":{"icon": str(ICONS.BUILDING), "title": "Buildings", "path": "pages/buildings.py",
"table": "USER_CONFIG_BUILDINGS"},
}
# streamlit_app.py
home = st.Page(PAGES_CONFIG["home"]["path"], title="Home", icon=PAGES_CONFIG["home"]["icon"], default=True)
pg = st.navigation({"": [home]})
pg.run()
Do not name the folder
/pages/— conflicts with Streamlit automatic page discovery. Ne pas nommer le dossier/pages/— conflit avec la découverte automatique de pages Streamlit.
Streamlit version / Version Streamlit
Pin to the version validated against the SiS CSS design system. / Épingler à la version validée contre le système de design CSS SiS.
# pyproject.toml
[project]
dependencies = ["streamlit==1.52.2"]
Streamlit breaks CSS and widget APIs regularly. Never use >= or leave unpinned. / Streamlit casse régulièrement les CSS et les APIs de widgets. Ne jamais utiliser >= ni laisser sans version.
Integration checklist / Checklist d'intégration
For a new SiS app / Pour une nouvelle app SiS :
- Call
setup_page()at the top of every page / Appelersetup_page()en haut de chaque page - Choose a palette →
palette=PALETTES.PYTHIAor custom / Choisir une palette →palette=PALETTES.PYTHIAou custom - Select the correct cache strategy for each dataset (see DESIGN_SYSTEM_CORE.md) / Sélectionner la bonne stratégie de cache par dataset
- Use
ICONS.<NAME>.materialfor buttons/badges,.emojifor dataframe columns / UtiliserICONS.<NAME>.materialpour boutons/badges,.emojipour colonnes dataframe - Apply
where(lambda d: d.notna(), None)after everyto_pandas()/ Appliquerwhere(lambda d: d.notna(), None)après chaqueto_pandas() - Follow key naming conventions:
btn-{type}-{accent}-{name},container-{accent}-{shade}-{name},table-{accent}-{name}/ Suivre les conventions de nommage des keys