A Streamlit wrapper for styled content rendering
Project description
StreamTeX Complete Cheatsheet
Essential Imports
# Block files (mandatory)
import streamlit as st
from streamtex import *
import streamtex as stx
from streamtex.styles import Style as ns, StyleGrid as sg
from streamtex.enums import Tags as t, ListTypes as lt
from custom.styles import Styles as s
# Book entry point (book.py)
import streamlit as st
import setup
import streamtex as stx
from streamtex import st_book, TOCConfig, MarkerConfig
from pathlib import Path
from custom.styles import Styles as s
from custom.themes import dark
import streamtex.styles as sts
import blocks
Style Organization
Custom Style Class
class BlockStyles:
"""Custom styles defined locally and used only for this block"""
# Composed styles
content = s.Large + s.center_txt
lime_bold = s.text.colors.lime + s.bold
bold_green = s.project.colors.green_01 + s.bold
# Styles with alignment
green_title = bold_green + s.huge + s.center_txt
# Styles with borders
border = s.container.borders.color(s.text.colors.black) + \
s.container.borders.solid_border + \
s.container.borders.size("2px")
# Styles with padding
side_padding = ns("padding: 10pt 36pt;")
bs = BlockStyles
Style Composition
# Create from CSS string
my_style = Style("color: red; font-weight: bold;", "my_style")
# Copy existing style with new ID
my_title = Style.create(s.bold + s.Large + s.center_txt, "my_title")
# Compose with + operator
heading = s.huge + s.bold + s.project.colors.primary
# Remove properties with - operator
no_bold = heading - s.bold
Basic Elements
Blocks and Text
# Simple block with style
with st_block(s.center_txt):
st_write(bs.green_title, "My Title")
st_space(size=3)
# Block with list
with st_block(s.center_txt):
with st_list(
list_type=lt.ordered,
li_style=bs.content) as l:
with l.item(): st_write("First item")
with l.item(): st_write("Second item")
st_write — Full Signature
st_write(
*args, # Style objects, text, or (Style, text) tuples
tag=t.span, # HTML tag: t.div, t.span, t.h1, t.p, t.section...
link="", # Optional hyperlink URL
no_link_decor=False, # Remove underline from links
toc_lvl=None, # TOC level: "1", "+1", "-1"
label="", # Custom TOC entry label
marker=None, # Per-heading marker control (True/False/None=auto)
)
# Inline mixed styles — ONE st_write with tuples (multiple calls stack vertically!)
st_write(s.Large, (s.text.colors.red, "Red "), (s.text.colors.blue, "Blue"))
# Register in TOC
st_write(bs.title, "Section Title", tag=t.div, toc_lvl="1")
st_write(bs.subtitle, "Subsection", toc_lvl="+1")
# Exclude a heading from marker navigation
st_write(s.huge, "Appendix", toc_lvl="1", marker=False)
# Force include in markers
st_write(s.huge, "Important", toc_lvl="2", marker=True)
Images and Media
# Simple image
st_image(uri="image.png")
# Image with dimensions
st_image(uri="image.png", width="1150px", height="735.34px")
# Image with link
st_image(uri="image.png", link="https://example.com")
# Image with auto-height style
st_image(s.container.sizes.height_auto, uri="image.png")
Grids and Tables (Responsive-First)
Multi-column grids MUST use responsive patterns so columns stack on narrow screens.
# GOOD — responsive 2-column (stacks below 350px per column)
with st_grid(
cols=s.project.containers.responsive_2col,
grid_style=s.project.containers.gap_24,
) as g:
with g.cell(): st_write("Panel A")
with g.cell(): st_write("Panel B")
# GOOD — responsive 3-column
with st_grid(cols=s.project.containers.responsive_3col) as g:
with g.cell(): st_write("Card 1")
with g.cell(): st_write("Card 2")
with g.cell(): st_write("Card 3")
# GOOD — responsive card grid
with st_grid(cols=s.project.containers.responsive_cards) as g:
with g.cell(): st_image(uri="image1.png")
with g.cell(): st_image(uri="image2.png")
with g.cell(): st_image(uri="image3.png")
# Responsive presets (defined in custom/styles.py):
# responsive_2col = "repeat(auto-fit, minmax(350px, 1fr))"
# responsive_3col = "repeat(auto-fit, minmax(280px, 1fr))"
# responsive_cards = "repeat(auto-fit, minmax(200px, 1fr))"
# BAD — fixed columns, never wraps on narrow screens
# st_grid(cols=2)
# st_grid(cols="2fr 3fr")
# OK — fixed columns ONLY for data tables with known column count
with st_grid(cols=2, cell_styles=bs.border) as g:
with g.cell(): st_write("Header 1")
with g.cell(): st_write("Header 2")
# Grid (table) with per-cell styles
with st_grid(
cols=2,
cell_styles=sg.create("A1,A3", s.project.colors.orange_02) +
sg.create("A2", s.project.colors.red_01) +
sg.create("A1:B3", s.bold + s.LARGE)
) as g:
with g.cell(): st_write("Title")
with g.cell(): st_write("Link")
with g.cell(): st_write("Item 1")
with g.cell(): st_write("link1")
with g.cell(): st_write("Item 2")
with g.cell(): st_write("link2")
Overlays (Absolute Positioning)
with st_overlay() as ov:
with ov.layer(top=10, left=20):
st_write(s.large, "Positioned at top:10px left:20px")
with ov.layer(top=50, right=20):
st_image(uri="badge.png", width="80px")
Links and Navigation
Links
# Simple link
st_write("Click here", link="https://example.com")
# Styled link
link_style = s.text.colors.blue + s.text.decors.underline_text
st_write(link_style, "Styled link", link="https://example.com", no_link_decor=True)
Table of Contents
# Register headings
st_write(style, "Section", toc_lvl="1")
st_write(style, "Subsection", toc_lvl="+1")
# TOCConfig — full options
toc = TOCConfig(
numerate_titles=False, # Auto-numbering of headings
toc_position=0, # 0=start, -1=end, None=no TOC
title_style=s.project.titles.section_title + s.center_txt,
content_style=s.large + s.text.colors.reset,
sidebar_max_level=None, # None = auto (paginated: 1, continuous: 2)
search=True, # Full-text search in sidebar
)
Marker Navigation
from streamtex import st_marker, MarkerConfig, st_book
# Place markers manually
st_marker("Section Start", visible=True) # Visible marker (dashed border + label)
st_marker("Hidden Waypoint") # Invisible marker (default)
# Auto-markers from TOC headings (in book.py)
marker_config = MarkerConfig(
auto_marker_on_toc=1, # Level-1 TOC headings become markers
next_keys=["PageDown"], # Navigate forward
prev_keys=["PageUp"], # Navigate backward
)
st_book([...], marker_config=marker_config)
Predefined Styles
Text Colors
s.text.colors.red # 140+ CSS named colors available
s.text.colors.lime
s.text.colors.alice_blue
s.text.colors.reset # color: initial
Text Sizes
# Title sizes
s.GIANT # 196pt s.Giant # 128pt s.giant # 112pt
s.Huge # 96pt s.huge # 80pt
# Header sizes
s.LARGE # 64pt s.Large # 48pt s.large # 32pt
# Body sizes
s.big # 24pt s.medium # 16pt s.little # 12pt
s.small # 8pt s.tiny # 4pt
# Dynamic sizes
s.text.sizes.size(20, "custom_20pt") # Factory method
Alignment and Layout
s.center_txt # text-align: center
s.text.alignments.right_align # text-align: right
s.text.alignments.justify_align # text-align: justify
s.container.flex.center_align_items # align-items: center
s.container.layouts.vertical_center_layout # Flex centered both axes
s.container.layouts.center # width: fit-content + auto margin
Decorations
s.bold # font-weight: bold
s.italic # font-style: italic
s.text.decors.underline_text # text-decoration: underline
s.text.decors.strike_text # text-decoration: line-through
Container Styles
# Padding
s.container.paddings.little_padding # 9pt
s.container.paddings.small_padding # 6pt
s.container.paddings.medium_padding # 12pt
s.container.paddings.size("10px", "20px", style_id="custom_pad") # Factory
# Borders
s.container.borders.solid_border
s.container.borders.dashed_border
s.container.borders.size("2px") # Factory
s.container.borders.color(s.text.colors.blue) # Factory
# Background colors
s.container.bg_colors.red_bg # 140+ named background colors
s.container.bg_colors.reset_bg # background-color: initial
# Flex
s.container.flex.flex # display: flex
s.container.flex.center_flex # flex + center both axes
s.container.flex.space_between_justify # justify-content: space-between
# Sizes
s.container.sizes.width_full # width: 100%
s.container.sizes.height_auto # height: auto
# Lists
s.container.lists.g_docs # Google Docs symbols
s.container.lists.ordered_lowercase # lower-alpha list
Book Orchestration
book.py Pattern
import streamlit as st
import setup
import streamtex as stx
from streamtex import st_book, TOCConfig, MarkerConfig
from pathlib import Path
from custom.styles import Styles as s
from custom.themes import dark
import streamtex.styles as sts
import blocks
# Configure static sources
stx.set_static_sources([str(Path(__file__).parent / "static")])
# Page configuration
st.set_page_config(
page_title="My Project",
layout="wide",
initial_sidebar_state="collapsed",
)
# Inject dark theme
sts.theme = dark
# TOC + Markers
toc = TOCConfig(numerate_titles=False, toc_position=0, search=True)
marker_config = MarkerConfig(auto_marker_on_toc=1, next_keys=["PageDown"], prev_keys=["PageUp"])
# Orchestrate blocks
st_book(
[
blocks.bck_01_welcome,
blocks.bck_02_content,
],
toc_config=toc,
marker_config=marker_config,
paginate=True,
inspector=stx.InspectorConfig(enabled=True),
)
st_book — Full Signature
st_book(
module_list, # List of block modules
toc_config=None, # TOCConfig object
marker_config=None, # MarkerConfig object
separator=None, # Module rendered between blocks (optional)
export=True, # Enable HTML export
export_title="StreamTeX Export",
paginate=False, # One block per page
bib_sources=None, # List of .bib/.json/.ris paths
bib_config=None, # BibConfig for bibliography
inspector=None, # InspectorConfig for block inspector
page_width=90, # Page width as % of browser width (default 90)
)
InspectorConfig
import streamtex as stx
# Enable the block inspector panel
st_book([...], inspector=stx.InspectorConfig(enabled=True))
# Full options
stx.InspectorConfig(
enabled=True,
password=None, # Optional password protection
panel_width="35vw", # Right panel width
backup=True, # Create .bak files before saving
)
Block Infrastructure
Block Registry — blocks/init.py
"""Blocks package — lazy-loaded via streamtex.ProjectBlockRegistry."""
from pathlib import Path
from streamtex import ProjectBlockRegistry, BlockNotFoundError, BlockImportError
registry = ProjectBlockRegistry(Path(__file__).parent)
__all__ = ["registry", "BlockNotFoundError", "BlockImportError"]
def __getattr__(name: str):
try:
return registry.get(name)
except (BlockNotFoundError, BlockImportError) as e:
raise AttributeError(str(e)) from e
def __dir__():
return sorted(registry.list_blocks() + __all__)
LazyBlockRegistry — Shared Blocks
# In book.py — load blocks from external directories
shared_path = str(Path(__file__).parent.parent / "shared-blocks" / "blocks")
shared_blocks = stx.LazyBlockRegistry([shared_path])
st_book([
shared_blocks.bck_header, # From shared library
blocks.bck_content, # From local blocks/
shared_blocks.bck_footer, # From shared library
])
# Multi-source with priority (first source wins)
shared = stx.LazyBlockRegistry([
"blocks/overrides", # Checked first (project overrides)
"../../shared-blocks/blocks", # Checked second (originals)
])
Composite Blocks (Atomic Sub-blocks)
# Composite block: loads atomic sub-blocks from _atomic/ subfolder
import streamtex as stx
from streamtex import st_include
bck_text_basics = stx.load_atomic_block("bck_text_basics", __file__)
bck_text_styles = stx.load_atomic_block("bck_text_styles", __file__)
class BlockStyles:
pass
def build():
st_include(bck_text_basics)
st_include(bck_text_styles)
load_atomic_block(name, __file__)loads_atomic/{name}.pyrelative to caller- Raises
BlockNotFoundError/BlockImportErroron failure
Static Asset Resolution
import streamtex as stx
from pathlib import Path
# Single source
stx.set_static_sources([str(Path(__file__).parent / "static")])
# Multi-source with priority (first directory containing the file wins)
stx.set_static_sources([
str(Path(__file__).parent / "static"), # Local (highest priority)
str(Path(__file__).parent.parent / "shared-blocks" / "static"), # Shared fallback
])
# Manual resolution
path = stx.resolve_static("logo.png") # Searches each source in order
# st_image() calls resolve_static() internally
Block Helpers
Config Injection Pattern (Recommended)
# blocks/helpers.py — inject project styles globally
from streamtex import (
BlockHelperConfig, set_block_helper_config,
show_code as _show_code,
show_explanation as _show_explanation,
show_details as _show_details,
)
from custom.styles import Styles as s
class ProjectBlockHelperConfig(BlockHelperConfig):
def get_code_style(self):
return s.project.containers.code_box
def get_explanation_style(self):
return s.project.containers.explanation_box
def get_details_style(self):
return s.project.containers.details_box
set_block_helper_config(ProjectBlockHelperConfig())
# Convenience wrappers
def show_code(code_string: str, language: str = "python", line_numbers: bool = True):
return _show_code(code_string, language, line_numbers)
def show_explanation(text: str):
return _show_explanation(text)
def show_details(text: str):
return _show_details(text)
Standalone Functions
from streamtex import show_code, show_explanation, show_details
show_code("print('hello')") # Uses injected config style
show_code("print('hello')", style=s.custom.style) # Override with explicit style
show_explanation("This explains the concept...")
show_details("Additional details here...")
OOP Inheritance (Advanced)
from streamtex import BlockHelper
class ProjectBlockHelper(BlockHelper):
def show_comparison(self, before: str, after: str):
self.show_code(before)
self.show_code(after)
helper = ProjectBlockHelper()
helper.show_comparison(old_code, new_code)
Raw HTML (st_html)
Use stx.st_html() when you need to render raw HTML content (bar charts, decorative rules, embedded iframes). It routes through the dual-rendering pipeline (live + export buffer) and auto-injects font-family: Source Sans Pro in iframes.
# Inline HTML (height=0, default) — renders via st.html()
stx.st_html('<hr style="border:none;height:3px;">')
# Iframe HTML (height>0) — renders via components.html() with auto font injection
stx.st_html('<div>chart content</div>', height=400)
# Iframe with scrolling
stx.st_html('<div>long content</div>', height=600, scrolling=True)
# Light background (force white bg in dark mode)
stx.st_html('<svg>...</svg>', height=300, light_bg=True)
Parameters:
html— HTML string to renderheight— When > 0, render in an iframe with explicit pixel height (default: 0 = inline)light_bg— Force light color-scheme in the iframe (default: False)scrolling— Enable scrolling in the iframe (default: False)
Export-Aware Widgets
Use stx.st_* wrappers instead of raw st.* calls for data visualization — they appear in both the live app AND the HTML export.
Charts
stx.st_line_chart(data, x="col_x", y="col_y")
stx.st_bar_chart(data, x="Category", y="Value")
stx.st_area_chart(data)
stx.st_scatter_chart(data, x="x", y="y")
Tables & Data
stx.st_dataframe(df, use_container_width=True) # Interactive table
stx.st_table(data) # Static table
stx.st_json({"key": "value"}) # JSON viewer
stx.st_metric("Revenue", "$1M", delta="+5%") # KPI metric
Diagrams
# Graphviz (DOT language)
stx.st_graphviz('digraph { A -> B -> C }')
# Mermaid (interactive zoom/pan support)
stx.st_mermaid("""
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[OK]
B -->|No| D[End]
""")
# Mermaid with options
stx.st_mermaid(code, style=my_style, light_bg=True, height=500)
# Mermaid fit modes (initial zoom on first render)
stx.st_mermaid(code, fit="contain") # default: fit entire diagram in viewport
stx.st_mermaid(code, fit="width") # fill viewport width
stx.st_mermaid(code, fit="none") # natural size (scale 1)
# TikZ (requires LaTeX + Ghostscript)
stx.st_tikz(r"""
\begin{tikzpicture}
\draw (0,0) -- (1,1) -- (2,0) -- cycle;
\end{tikzpicture}
""", preamble=r"\usepackage{tikz}")
# PlantUML (server-rendered, configurable)
stx.st_plantuml("""
@startuml
Alice -> Bob: Authentication Request
Bob --> Alice: Authentication Response
@enduml
""")
# PlantUML with options
stx.st_plantuml(code, style=my_style, light_bg=True, height=500,
server="https://www.plantuml.com/plantuml")
Audio & Video
stx.st_audio("path/to/audio.wav", format="audio/wav")
stx.st_video("path/to/video.mp4")
stx.st_video("https://www.youtube.com/watch?v=...")
Generic Fallback
# For any widget not covered above
with stx.st_export('<p>Fallback HTML for export</p>'):
st.plotly_chart(fig)
Note: Interactive widgets (
st.button,st.slider,st.selectbox) have no static representation and are absent from the export.
Zoom Control
import streamtex as stx
# Zoom is managed automatically by st_book().
# Two independent sidebar controls: Width % and Zoom % (pure CSS, no JavaScript).
# If calling manually:
stx.add_zoom_options() # Defaults: width=100%, zoom=100%
stx.add_zoom_options(default_page_width=80) # Start at 80% width
stx.add_zoom_options(default_page_width=80, default_zoom=125) # 80% width, 125% zoom
# Low-level injection (rarely needed):
stx.inject_zoom_logic(100, 100) # Width 100%, Zoom 100%
stx.inject_zoom_logic(80, 150) # Width 80%, Zoom 150%
stx.inject_zoom_logic(120, 50) # Width 120%, Zoom 50%
Bibliography
from streamtex.bib import BibConfig, BibFormat, CitationStyle
# Configure bibliography
bib_config = BibConfig(
format=BibFormat.APA,
citation_style=CitationStyle.AUTHOR_YEAR,
hover_enabled=True, # Hover preview of citations
hover_show_abstract=True,
)
# Load sources (supports .bib, .json, .ris, .csl-json)
bib_sources = ["references.bib"]
# Pass to st_book
st_book([...], bib_sources=bib_sources, bib_config=bib_config)
# In-text citations (inside blocks)
from streamtex.bib import st_cite, st_bibliography
st_cite("author2024key") # Inline citation widget
st_bibliography() # Render full bibliography
Collection System (Multi-Project Hub)
collection.toml
[collection]
title = "My Course Library"
description = "A collection of StreamTeX courses"
cards_per_row = 2
[projects.intro]
title = "Introduction Course"
description = "Learn the basics"
cover = "static/images/covers/intro.png"
project_url = "http://localhost:8502"
order = 1
[projects.advanced]
title = "Advanced Course"
description = "Master advanced concepts"
cover = "static/images/covers/advanced.png"
project_url = "http://localhost:8503"
order = 2
Automatic Collection UI
from streamtex import st_collection, CollectionConfig
config = CollectionConfig.from_toml("collection.toml")
st_collection(config=config, home_styles=s)
Custom Collection with st_book
# For full control over the collection UI
st_book([
blocks.bck_home, # Custom home page with cards
blocks.bck_management, # Documentation
], toc_config=toc, paginate=False)
Google Sheets Import
from streamtex import GSheetConfig, set_gsheet_config, load_gsheet, load_gsheet_df
# Configure
config = GSheetConfig(...)
set_gsheet_config(config)
# Load as module or DataFrame
block_module = load_gsheet("path/to/source")
df = load_gsheet_df("path/to/source")
Utilities
Spacing
st_space(size=3) # 3em vertical space
st_space("v", size=2) # 2em vertical space
st_space("h", size=1) # 1em horizontal space
st_space("h", size="40px") # 40px horizontal space
st_br() # Line break
st_br(count=3) # 3 line breaks
Containers
# Styled block container (vertical)
with st_block(s.center_txt):
st_write("Centered content")
# Inline styled container
with st_span(s.bold + s.text.colors.red):
st_write("Inline bold red")
Project Structure
project_name/
book.py # Entry point
setup.py # PATH setup
blocks/
__init__.py # ProjectBlockRegistry
bck_*.py # Each block: BlockStyles + build()
helpers.py # Block helper configuration
_atomic/ # Atomic sub-blocks (optional)
custom/
styles.py # Project styles (extends StxStyles)
themes.py # Dark theme overrides (dict)
static/images/ # Image assets
.streamlit/config.toml # enableStaticServing = true
Custom Styles Pattern (custom/styles.py)
from streamtex.styles import Style, Text, Container, StxStyles
class ColorsCustom:
primary = Style("color: #4A90D9;", "primary")
accent = Style("color: #2EC4B6;", "accent")
class BackgroundsCustom:
callout_bg = Style("background-color: rgba(74, 144, 217, 0.12);", "callout_bg")
class TextStylesCustom:
course_title = Style.create(
ColorsCustom.primary + Text.weights.bold_weight + Text.sizes.Giant_size,
"course_title"
)
class ContainerStylesCustom:
callout = Style.create(
BackgroundsCustom.callout_bg
+ Container.borders.solid_border
+ Style("border-color: #4A90D9; border-width: 0 0 0 4px;", "callout_border")
+ Container.paddings.medium_padding,
"callout"
)
class Custom:
colors = ColorsCustom
backgrounds = BackgroundsCustom
titles = TextStylesCustom
containers = ContainerStylesCustom
class Styles(StxStyles):
project = Custom
Theme Overrides (custom/themes.py)
# Keys are style_ids, values are replacement CSS strings
dark = {
"primary": "color: #7AB8F5;",
"course_title": "color: #7AB8F5; font-weight: bold; font-size: 128pt;",
"callout_bg": "background-color: rgba(74, 144, 217, 0.20);",
}
Tips and Best Practices
- Group common styles in a
BlockStylesclass — one per block - ONE
st_write()with tuples for inline mixed-style text (multiple calls stack vertically) - Never hardcode black/white — let Streamlit handle Light/Dark mode
- No raw HTML/CSS — use Style composition
- Use
stx.*for content,st.*only for interactivity (buttons, sliders, inputs) - One generic style, reused everywhere — no duplicates
- Use
tag=t.divfor block-level elements, defaultt.spanfor inline
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file streamtex-0.2.0.tar.gz.
File metadata
- Download URL: streamtex-0.2.0.tar.gz
- Upload date:
- Size: 181.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c075b0cfa8dc762af0e2f73b90ef5b962959030be5807762508551104dd8bea3
|
|
| MD5 |
17070ad40278b254204814bc35255a08
|
|
| BLAKE2b-256 |
26225af95cb0afd2330984bcdeaf06ccc92eb50a049715489613b3d45e1bb8cd
|
File details
Details for the file streamtex-0.2.0-py3-none-any.whl.
File metadata
- Download URL: streamtex-0.2.0-py3-none-any.whl
- Upload date:
- Size: 122.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.8.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c765c82f010131f4335202c2dc5d7332e263223f6589a2445d327ac3901b2b7a
|
|
| MD5 |
817d30e3a333c8cc6b5e367a27628f08
|
|
| BLAKE2b-256 |
55549e566be8cf54db38ec12e8f936e0ce295f1ed5e2c1107174177e4dee880f
|