# Streamlit JSON Tip
[](https://pypi.org/project/streamlit-json-tip/)
[](https://pypi.org/project/streamlit-json-tip/)
[](https://github.com/kazuar/streamlit-json-tip/blob/main/LICENSE)
[](https://github.com/kazuar/streamlit-json-tip/actions/workflows/test.yml)
[](https://pepy.tech/project/streamlit-json-tip)
A Streamlit custom component for viewing JSON data with interactive tooltips and tags for individual fields.

## Features
- đ **Interactive JSON Viewer**: Expand/collapse objects and arrays
- đ **Interactive Tooltips**: Add contextual help for any field with professional Tippy.js tooltips
- đˇī¸ **Field Tags**: Categorize fields with colored tags (PII, CONFIG, etc.)
- đ¯ **Field Selection**: Click on fields to get detailed information
- đ¨ **Syntax Highlighting**: Color-coded JSON with proper formatting
- đą **Responsive Design**: Works well in different screen sizes
## Installation
### With uv (Recommended)
```bash
uv add streamlit-json-tip
```
Or for a one-off script:
```bash
uv run --with streamlit-json-tip streamlit run your_app.py
```
### With pip
```bash
pip install streamlit-json-tip
```
### From TestPyPI (Latest Development Version)
With uv:
```bash
uv add --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ streamlit-json-tip
```
With pip:
```bash
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ streamlit-json-tip
```
### Development Setup
#### Prerequisites
* Install task
```bash
brew install go-task/tap/go-task
```
* Install uv
```bash
curl -LsSf https://astral.sh/uv/install.sh | sh
```
#### Build repo
1. Clone this repository:
```bash
git clone https://github.com/isaac/streamlit-json-tip.git
cd streamlit-json-tip
```
2. Set up development environment with uv:
```bash
# Create virtual environment and install all dependencies (including dev dependencies)
uv sync
```
3. Run the example app:
```bash
uv run streamlit run example_app.py
```
## Usage
```python
import streamlit as st
from streamlit_json_tip import json_viewer
# Your JSON data
data = {
"user": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
}
}
# Help text for specific fields
help_text = {
"user.id": "Unique user identifier",
"user.name": "Full display name",
"user.email": "Primary contact email"
}
# Tags for categorizing fields
tags = {
"user.id": "ID",
"user.name": "PII",
"user.email": "PII"
}
# Display the JSON viewer
selected = json_viewer(
data=data,
help_text=help_text,
tags=tags,
height=400
)
# Handle field selection
if selected:
st.write(f"Selected field: {selected['path']}")
st.write(f"Value: {selected['value']}")
if selected.get('help_text'):
st.write(f"Help: {selected['help_text']}")
```
## Advanced Examples
### Dynamic Tooltips
Dynamic tooltips allow you to generate contextual help text programmatically based on field paths, values, and the complete data structure:
```python
import streamlit as st
from streamlit_json_tip import json_viewer
# Sample data with various types
data = {
"user": {
"name": "Alice Johnson",
"score": 95,
"email": "alice@company.com",
"role": "admin"
},
"metrics": {
"cpu_usage": 0.78,
"memory_usage": 0.65,
"disk_usage": 0.92
},
"items": [
{"id": 1, "status": "active"},
{"id": 2, "status": "pending"}
]
}
def dynamic_tooltip(path, value, data):
"""Generate contextual tooltips based on field path and value."""
# Name fields
if path.endswith(".name"):
return f"đ¤ Full name: {len(value)} characters"
# Score fields with conditional icons
elif path.endswith(".score"):
icon = "đĸ" if value >= 90 else "đĄ" if value >= 70 else "đ´"
return {
"text": f"Performance score: {value}/100",
"icon": icon
}
# Email fields
elif path.endswith(".email"):
domain = value.split("@")[1] if "@" in value else "unknown"
return {
"text": f"đ§ Email domain: {domain}",
"icon": "đ§"
}
# Usage metrics with warnings
elif "usage" in path:
percentage = f"{value * 100:.1f}%"
if value > 0.9:
return {
"text": f"â ī¸ High usage: {percentage}",
"icon": "â ī¸"
}
elif value > 0.7:
return f"đĄ Moderate usage: {percentage}"
else:
return f"đĸ Normal usage: {percentage}"
# Status fields
elif path.endswith(".status"):
status_info = {
"active": {"icon": "â
", "desc": "Currently active"},
"pending": {"icon": "âŗ", "desc": "Awaiting approval"},
"inactive": {"icon": "â", "desc": "Not active"}
}
info = status_info.get(value, {"icon": "â", "desc": "Unknown status"})
return {
"text": f"{info['desc']}: {value}",
"icon": info["icon"]
}
# Role-based tooltips
elif path.endswith(".role"):
role_descriptions = {
"admin": "đ Full system access",
"user": "đ¤ Standard user access",
"guest": "đī¸ Read-only access"
}
return role_descriptions.get(value, f"Role: {value}")
return None
# Display with dynamic tooltips
json_viewer(
data=data,
dynamic_tooltips=dynamic_tooltip,
height=500
)
```
### Custom Tooltip Configuration
Configure Tippy.js tooltip behavior and appearance:
```python
import streamlit as st
from streamlit_json_tip import json_viewer
data = {
"api": {
"endpoint": "https://api.example.com",
"version": "v2.1",
"rate_limit": 1000
},
"database": {
"host": "db.example.com",
"port": 5432,
"ssl": True
}
}
help_text = {
"api.endpoint": "The base URL for API requests",
"api.version": "Current API version - breaking changes in major versions",
"api.rate_limit": "Maximum requests per hour",
"database.host": "Database server hostname",
"database.port": "Database connection port",
"database.ssl": "SSL encryption enabled for secure connections"
}
# Custom tooltip configuration
tooltip_config = {
"placement": "right", # Position: top, bottom, left, right, auto
"animation": "scale", # Animation: fade, shift-away, shift-toward, scale, perspective
"delay": [500, 100], # [show_delay, hide_delay] in milliseconds
"duration": [200, 150], # [show_duration, hide_duration] in milliseconds
"interactive": True, # Allow hovering over tooltip content
"maxWidth": 300, # Maximum width in pixels
"trigger": "mouseenter focus", # Events: mouseenter, focus, click, etc.
"hideOnClick": False, # Keep tooltip open when clicking
"sticky": True, # Tooltip follows cursor movement
"arrow": True, # Show pointing arrow
"theme": "light" # Theme: light, dark, or custom
}
json_viewer(
data=data,
help_text=help_text,
tooltip_config=tooltip_config,
tooltip_icon="đĄ", # Custom global icon
height=400
)
```
### Complex Data with Tags and Icons
Handle complex nested structures with comprehensive tooltips:
```python
import streamlit as st
from streamlit_json_tip import json_viewer
# Complex nested data structure
data = {
"users": [
{
"id": 1,
"profile": {
"name": "John Doe",
"email": "john@company.com",
"ssn": "***-**-1234",
"department": "Engineering"
},
"permissions": ["read", "write", "admin"],
"last_login": "2024-01-15T10:30:00Z",
"settings": {
"theme": "dark",
"notifications": True,
"api_key": "sk-abc123...xyz789"
}
}
],
"system": {
"version": "2.1.0",
"environment": "production",
"uptime": 99.9,
"memory_usage": 0.78
}
}
# Static help text for specific fields
help_text = {
"users[0].id": "Unique user identifier in the system",
"system.version": "Current application version following semantic versioning",
"system.environment": "Deployment environment (dev/staging/production)"
}
# Field categorization with tags
tags = {
"users[0].profile.email": "PII",
"users[0].profile.ssn": "SENSITIVE",
"users[0].profile.name": "PII",
"users[0].settings.api_key": "SECRET",
"system.environment": "CONFIG",
"system.version": "INFO"
}
# Advanced dynamic tooltips with context awareness
def advanced_tooltips(path, value, data):
# Get user context for personalized tips
if "users[0]" in path:
user_name = data["users"][0]["profile"]["name"]
if path.endswith(".permissions"):
perm_count = len(value)
return {
"text": f"đ {user_name} has {perm_count} permission(s): {', '.join(value)}",
"icon": "đ"
}
elif path.endswith(".last_login"):
return {
"text": f"đ {user_name}'s last activity: {value}",
"icon": "đ"
}
elif path.endswith(".department"):
dept_info = {
"Engineering": "đ¨âđģ Technical development team",
"Sales": "đŧ Revenue generation team",
"Marketing": "đĸ Brand and promotion team"
}
return dept_info.get(value, f"Department: {value}")
# System metrics with thresholds
elif path.startswith("system."):
if path.endswith(".uptime"):
if value >= 99.9:
return {"text": f"đĸ Excellent uptime: {value}%", "icon": "đĸ"}
elif value >= 99.0:
return {"text": f"đĄ Good uptime: {value}%", "icon": "đĄ"}
else:
return {"text": f"đ´ Poor uptime: {value}%", "icon": "đ´"}
elif path.endswith(".memory_usage"):
percentage = f"{value * 100:.1f}%"
if value > 0.9:
return {"text": f"â ī¸ Critical memory usage: {percentage}", "icon": "â ī¸"}
elif value > 0.7:
return {"text": f"đĄ High memory usage: {percentage}", "icon": "đĄ"}
else:
return {"text": f"đĸ Normal memory usage: {percentage}", "icon": "đĸ"}
# Sensitive data warnings
if any(keyword in path for keyword in ["ssn", "api_key", "password"]):
return {
"text": "đ¨ Sensitive data - handle with care",
"icon": "đ¨"
}
return None
# Advanced tooltip configuration for better UX
advanced_config = {
"placement": "auto", # Auto-position based on available space
"animation": "fade", # Smooth fade animation
"delay": [300, 100], # Quick show, delayed hide
"interactive": True, # Allow interaction with tooltip content
"maxWidth": 400, # Wider tooltips for more content
"hideOnClick": False, # Keep tooltips persistent
"appendTo": "parent" # Better positioning within container
}
selected = json_viewer(
data=data,
help_text=help_text,
tags=tags,
dynamic_tooltips=advanced_tooltips,
tooltip_config=advanced_config,
tooltip_icon="âšī¸",
height=600
)
# Handle field selection with detailed information
if selected:
st.sidebar.header("Field Details")
st.sidebar.json({
"Path": selected['path'],
"Value": selected['value'],
"Type": type(selected['value']).__name__,
"Help": selected.get('help_text', 'No help available')
})
```
## Parameters
- **data** (dict): The JSON data to display
- **help_text** (dict, optional): Dictionary mapping field paths to help text
- **tags** (dict, optional): Dictionary mapping field paths to tags/labels
- **dynamic_tooltips** (function, optional): Function that takes (field_path, field_value, full_data) and returns tooltip text or dict with text and icon
- **tooltip_config** (dict, optional): Tippy.js configuration options (see Tooltip Configuration below)
- **tooltip_icon** (str, optional): Default icon for tooltips (default: "âšī¸")
- **height** (int, optional): Height of the component in pixels (default: 400)
- **key** (str, optional): Unique key for the component
### Tooltip Configuration Options
The `tooltip_config` parameter accepts any valid [Tippy.js options](https://atomiks.github.io/tippyjs/v6/all-props/):
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| `placement` | str | "top" | Tooltip position: "top", "bottom", "left", "right", "auto" |
| `animation` | str | "fade" | Animation type: "fade", "shift-away", "shift-toward", "scale", "perspective" |
| `delay` | int/list | 0 | Show delay in ms, or [show_delay, hide_delay] |
| `duration` | int/list | [300, 250] | Animation duration in ms, or [show_duration, hide_duration] |
| `interactive` | bool | False | Allow hovering over tooltip content |
| `maxWidth` | int | 350 | Maximum width in pixels |
| `trigger` | str | "mouseenter focus" | Events that trigger tooltip |
| `hideOnClick` | bool | True | Hide tooltip when clicking |
| `sticky` | bool | False | Tooltip follows cursor movement |
| `arrow` | bool | True | Show pointing arrow |
| `theme` | str | "light" | Tooltip theme |
## Field Path Format
Field paths use dot notation for objects and bracket notation for arrays:
- `"user.name"` - Object field
- `"items[0].title"` - Array item field
- `"settings.preferences.theme"` - Nested object field
## Development
### Frontend Development
1. Set up the development environment (see Development Setup above)
2. Navigate to the frontend directory:
```bash
cd streamlit_json_tip/frontend
```
3. Install frontend dependencies:
```bash
npm install
```
4. Start development server:
```bash
npm start
```
5. In your Python code, set `_RELEASE = False` in `__init__.py`
6. Run the example app in another terminal:
```bash
uv run streamlit run example_app.py
```
### Running Tests
#### Python Tests
```bash
# Run all Python unit tests with coverage
uv run pytest
# Run tests with verbose output
uv run pytest -v
# Generate HTML coverage report
uv run pytest --cov-report=html
```
#### Frontend Tests
```bash
cd streamlit_json_tip/frontend
# Run Jest tests once
npm test -- --ci --watchAll=false
# Run tests with coverage
npm test -- --coverage --ci --watchAll=false
# Run tests in watch mode (for development)
npm test
```
#### Run All Tests
Both Python and frontend tests run automatically in GitHub Actions on every push and pull request.
### Building for Production
1. Build the frontend:
```bash
cd streamlit_json_tip/frontend
npm run build
```
2. Set `_RELEASE = True` in `__init__.py`
3. Build the Python package:
```bash
uv run python -m build
```
4. Upload to PyPI:
```bash
uv run python -m twine upload dist/*
```
### Build Scripts
The project includes convenient uv scripts for common development tasks:
#### Frontend Development
```bash
task build-frontend
```
#### Package Building
```bash
uv run clean # Clean build artifacts
uv run build # Clean + build Python package
uv run build-check # Build + validate package with twine
```
#### Publishing
```bash
task release-test # Build + upload to TestPyPI
task release # Build + upload to PyPI
```
This will build the frontend, package the Python distribution, validate it, and upload to PyPI.
## Releasing a New Version
This project uses automated GitHub Actions for releases. Follow these steps to release a new version:
### 1. Update Version and Changelog
1. **Update the version** in `pyproject.toml`:
```toml
version = "0.2.5" # Increment according to semver
```
2. **Add changelog entry** in `CHANGELOG.md`:
```markdown
## [0.2.5] - 2025-01-26
### ⨠Added
- New feature description
### đ§ Fixed
- Bug fix description
```
3. **Commit your changes**:
```bash
git add pyproject.toml CHANGELOG.md
git commit -m "Bump version to 0.2.5"
git push origin main
```
### 2. Create and Push Release Tag
```bash
git tag v0.2.5
git push origin v0.2.5
```
### 3. Automated Release Process
Once you push the tag, GitHub Actions will automatically:
- â
Build the frontend (React components)
- â
Build the Python package (wheel + source distribution)
- â
Extract changelog section for this version
- â
Create GitHub Release with changelog as release notes
- â
Upload distribution files as release assets
- â
Publish to PyPI
### 4. Monitor the Release
1. **Check GitHub Actions**: Go to the Actions tab to monitor the release workflow
2. **Verify GitHub Release**: Check that the release was created with proper changelog
3. **Verify PyPI**: Confirm the new version appears on PyPI
### Setup Requirements (One-time)
To use automated releases, you need:
1. **PyPI API Token**: Add `PYPI_API_TOKEN` to your repository secrets
- Go to: Repository â Settings â Secrets and variables â Actions
- Add your PyPI token as `PYPI_API_TOKEN`
### Manual Release (Alternative)
If you prefer manual releases or need to troubleshoot:
```bash
# Build everything
task build
# Upload to PyPI manually
export TWINE_PASSWORD=your_pypi_token_here
python -m twine upload --username __token__ dist/*
```
## License
MIT License
Raw data
{
"_id": null,
"home_page": "https://github.com/yourusername/streamlit-json-tip",
"name": "streamlit-json-tip",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "streamlit, json, viewer, tooltip, component, interactive",
"author": "Your Name",
"author_email": "Isaac <isaac@example.com>",
"download_url": "https://files.pythonhosted.org/packages/9b/40/e41de1c10de9e64e40c5f38f3d06a41720ad82a4c02b55215195c114e995/streamlit_json_tip-0.2.8.tar.gz",
"platform": null,
"description": "# Streamlit JSON Tip\n\n[](https://pypi.org/project/streamlit-json-tip/)\n[](https://pypi.org/project/streamlit-json-tip/)\n[](https://github.com/kazuar/streamlit-json-tip/blob/main/LICENSE)\n[](https://github.com/kazuar/streamlit-json-tip/actions/workflows/test.yml)\n[](https://pepy.tech/project/streamlit-json-tip)\n\nA Streamlit custom component for viewing JSON data with interactive tooltips and tags for individual fields.\n\n\n\n## Features\n\n- \ud83d\udd0d **Interactive JSON Viewer**: Expand/collapse objects and arrays\n- \ud83d\udcdd **Interactive Tooltips**: Add contextual help for any field with professional Tippy.js tooltips\n- \ud83c\udff7\ufe0f **Field Tags**: Categorize fields with colored tags (PII, CONFIG, etc.)\n- \ud83c\udfaf **Field Selection**: Click on fields to get detailed information\n- \ud83c\udfa8 **Syntax Highlighting**: Color-coded JSON with proper formatting\n- \ud83d\udcf1 **Responsive Design**: Works well in different screen sizes\n\n## Installation\n\n### With uv (Recommended)\n\n```bash\nuv add streamlit-json-tip\n```\n\nOr for a one-off script:\n```bash\nuv run --with streamlit-json-tip streamlit run your_app.py\n```\n\n### With pip\n\n```bash\npip install streamlit-json-tip\n```\n\n### From TestPyPI (Latest Development Version)\n\nWith uv:\n```bash\nuv add --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ streamlit-json-tip\n```\n\nWith pip:\n```bash\npip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ streamlit-json-tip\n```\n\n### Development Setup\n\n#### Prerequisites\n\n* Install task\n\n```bash\nbrew install go-task/tap/go-task\n```\n\n* Install uv\n\n```bash\n curl -LsSf https://astral.sh/uv/install.sh | sh\n```\n\n#### Build repo\n\n1. Clone this repository:\n ```bash\n git clone https://github.com/isaac/streamlit-json-tip.git\n cd streamlit-json-tip\n ```\n\n2. Set up development environment with uv:\n ```bash\n # Create virtual environment and install all dependencies (including dev dependencies)\n uv sync\n ```\n\n3. Run the example app:\n ```bash\n uv run streamlit run example_app.py\n ```\n\n## Usage\n\n```python\nimport streamlit as st\nfrom streamlit_json_tip import json_viewer\n\n# Your JSON data\ndata = {\n \"user\": {\n \"id\": 123,\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}\n\n# Help text for specific fields\nhelp_text = {\n \"user.id\": \"Unique user identifier\",\n \"user.name\": \"Full display name\",\n \"user.email\": \"Primary contact email\"\n}\n\n# Tags for categorizing fields\ntags = {\n \"user.id\": \"ID\",\n \"user.name\": \"PII\",\n \"user.email\": \"PII\"\n}\n\n# Display the JSON viewer\nselected = json_viewer(\n data=data,\n help_text=help_text,\n tags=tags,\n height=400\n)\n\n# Handle field selection\nif selected:\n st.write(f\"Selected field: {selected['path']}\")\n st.write(f\"Value: {selected['value']}\")\n if selected.get('help_text'):\n st.write(f\"Help: {selected['help_text']}\")\n```\n\n## Advanced Examples\n\n### Dynamic Tooltips\n\nDynamic tooltips allow you to generate contextual help text programmatically based on field paths, values, and the complete data structure:\n\n```python\nimport streamlit as st\nfrom streamlit_json_tip import json_viewer\n\n# Sample data with various types\ndata = {\n \"user\": {\n \"name\": \"Alice Johnson\", \n \"score\": 95,\n \"email\": \"alice@company.com\",\n \"role\": \"admin\"\n },\n \"metrics\": {\n \"cpu_usage\": 0.78,\n \"memory_usage\": 0.65,\n \"disk_usage\": 0.92\n },\n \"items\": [\n {\"id\": 1, \"status\": \"active\"},\n {\"id\": 2, \"status\": \"pending\"}\n ]\n}\n\ndef dynamic_tooltip(path, value, data):\n \"\"\"Generate contextual tooltips based on field path and value.\"\"\"\n \n # Name fields\n if path.endswith(\".name\"):\n return f\"\ud83d\udc64 Full name: {len(value)} characters\"\n \n # Score fields with conditional icons\n elif path.endswith(\".score\"):\n icon = \"\ud83d\udfe2\" if value >= 90 else \"\ud83d\udfe1\" if value >= 70 else \"\ud83d\udd34\"\n return {\n \"text\": f\"Performance score: {value}/100\",\n \"icon\": icon\n }\n \n # Email fields\n elif path.endswith(\".email\"):\n domain = value.split(\"@\")[1] if \"@\" in value else \"unknown\"\n return {\n \"text\": f\"\ud83d\udce7 Email domain: {domain}\",\n \"icon\": \"\ud83d\udce7\"\n }\n \n # Usage metrics with warnings\n elif \"usage\" in path:\n percentage = f\"{value * 100:.1f}%\"\n if value > 0.9:\n return {\n \"text\": f\"\u26a0\ufe0f High usage: {percentage}\",\n \"icon\": \"\u26a0\ufe0f\"\n }\n elif value > 0.7:\n return f\"\ud83d\udfe1 Moderate usage: {percentage}\"\n else:\n return f\"\ud83d\udfe2 Normal usage: {percentage}\"\n \n # Status fields\n elif path.endswith(\".status\"):\n status_info = {\n \"active\": {\"icon\": \"\u2705\", \"desc\": \"Currently active\"},\n \"pending\": {\"icon\": \"\u23f3\", \"desc\": \"Awaiting approval\"},\n \"inactive\": {\"icon\": \"\u274c\", \"desc\": \"Not active\"}\n }\n info = status_info.get(value, {\"icon\": \"\u2753\", \"desc\": \"Unknown status\"})\n return {\n \"text\": f\"{info['desc']}: {value}\",\n \"icon\": info[\"icon\"]\n }\n \n # Role-based tooltips\n elif path.endswith(\".role\"):\n role_descriptions = {\n \"admin\": \"\ud83d\udc51 Full system access\",\n \"user\": \"\ud83d\udc64 Standard user access\", \n \"guest\": \"\ud83d\udc41\ufe0f Read-only access\"\n }\n return role_descriptions.get(value, f\"Role: {value}\")\n \n return None\n\n# Display with dynamic tooltips\njson_viewer(\n data=data,\n dynamic_tooltips=dynamic_tooltip,\n height=500\n)\n```\n\n### Custom Tooltip Configuration\n\nConfigure Tippy.js tooltip behavior and appearance:\n\n```python\nimport streamlit as st\nfrom streamlit_json_tip import json_viewer\n\ndata = {\n \"api\": {\n \"endpoint\": \"https://api.example.com\",\n \"version\": \"v2.1\",\n \"rate_limit\": 1000\n },\n \"database\": {\n \"host\": \"db.example.com\",\n \"port\": 5432,\n \"ssl\": True\n }\n}\n\nhelp_text = {\n \"api.endpoint\": \"The base URL for API requests\",\n \"api.version\": \"Current API version - breaking changes in major versions\",\n \"api.rate_limit\": \"Maximum requests per hour\",\n \"database.host\": \"Database server hostname\",\n \"database.port\": \"Database connection port\",\n \"database.ssl\": \"SSL encryption enabled for secure connections\"\n}\n\n# Custom tooltip configuration\ntooltip_config = {\n \"placement\": \"right\", # Position: top, bottom, left, right, auto\n \"animation\": \"scale\", # Animation: fade, shift-away, shift-toward, scale, perspective\n \"delay\": [500, 100], # [show_delay, hide_delay] in milliseconds\n \"duration\": [200, 150], # [show_duration, hide_duration] in milliseconds\n \"interactive\": True, # Allow hovering over tooltip content\n \"maxWidth\": 300, # Maximum width in pixels\n \"trigger\": \"mouseenter focus\", # Events: mouseenter, focus, click, etc.\n \"hideOnClick\": False, # Keep tooltip open when clicking\n \"sticky\": True, # Tooltip follows cursor movement\n \"arrow\": True, # Show pointing arrow\n \"theme\": \"light\" # Theme: light, dark, or custom\n}\n\njson_viewer(\n data=data,\n help_text=help_text,\n tooltip_config=tooltip_config,\n tooltip_icon=\"\ud83d\udca1\", # Custom global icon\n height=400\n)\n```\n\n### Complex Data with Tags and Icons\n\nHandle complex nested structures with comprehensive tooltips:\n\n```python\nimport streamlit as st\nfrom streamlit_json_tip import json_viewer\n\n# Complex nested data structure\ndata = {\n \"users\": [\n {\n \"id\": 1,\n \"profile\": {\n \"name\": \"John Doe\",\n \"email\": \"john@company.com\", \n \"ssn\": \"***-**-1234\",\n \"department\": \"Engineering\"\n },\n \"permissions\": [\"read\", \"write\", \"admin\"],\n \"last_login\": \"2024-01-15T10:30:00Z\",\n \"settings\": {\n \"theme\": \"dark\",\n \"notifications\": True,\n \"api_key\": \"sk-abc123...xyz789\"\n }\n }\n ],\n \"system\": {\n \"version\": \"2.1.0\",\n \"environment\": \"production\",\n \"uptime\": 99.9,\n \"memory_usage\": 0.78\n }\n}\n\n# Static help text for specific fields\nhelp_text = {\n \"users[0].id\": \"Unique user identifier in the system\",\n \"system.version\": \"Current application version following semantic versioning\",\n \"system.environment\": \"Deployment environment (dev/staging/production)\"\n}\n\n# Field categorization with tags\ntags = {\n \"users[0].profile.email\": \"PII\",\n \"users[0].profile.ssn\": \"SENSITIVE\", \n \"users[0].profile.name\": \"PII\",\n \"users[0].settings.api_key\": \"SECRET\",\n \"system.environment\": \"CONFIG\",\n \"system.version\": \"INFO\"\n}\n\n# Advanced dynamic tooltips with context awareness\ndef advanced_tooltips(path, value, data):\n # Get user context for personalized tips\n if \"users[0]\" in path:\n user_name = data[\"users\"][0][\"profile\"][\"name\"]\n \n if path.endswith(\".permissions\"):\n perm_count = len(value)\n return {\n \"text\": f\"\ud83d\udd10 {user_name} has {perm_count} permission(s): {', '.join(value)}\",\n \"icon\": \"\ud83d\udd10\"\n }\n \n elif path.endswith(\".last_login\"):\n return {\n \"text\": f\"\ud83d\udd52 {user_name}'s last activity: {value}\",\n \"icon\": \"\ud83d\udd52\"\n }\n \n elif path.endswith(\".department\"):\n dept_info = {\n \"Engineering\": \"\ud83d\udc68\u200d\ud83d\udcbb Technical development team\",\n \"Sales\": \"\ud83d\udcbc Revenue generation team\",\n \"Marketing\": \"\ud83d\udce2 Brand and promotion team\"\n }\n return dept_info.get(value, f\"Department: {value}\")\n \n # System metrics with thresholds\n elif path.startswith(\"system.\"):\n if path.endswith(\".uptime\"):\n if value >= 99.9:\n return {\"text\": f\"\ud83d\udfe2 Excellent uptime: {value}%\", \"icon\": \"\ud83d\udfe2\"}\n elif value >= 99.0:\n return {\"text\": f\"\ud83d\udfe1 Good uptime: {value}%\", \"icon\": \"\ud83d\udfe1\"}\n else:\n return {\"text\": f\"\ud83d\udd34 Poor uptime: {value}%\", \"icon\": \"\ud83d\udd34\"}\n \n elif path.endswith(\".memory_usage\"):\n percentage = f\"{value * 100:.1f}%\"\n if value > 0.9:\n return {\"text\": f\"\u26a0\ufe0f Critical memory usage: {percentage}\", \"icon\": \"\u26a0\ufe0f\"}\n elif value > 0.7:\n return {\"text\": f\"\ud83d\udfe1 High memory usage: {percentage}\", \"icon\": \"\ud83d\udfe1\"}\n else:\n return {\"text\": f\"\ud83d\udfe2 Normal memory usage: {percentage}\", \"icon\": \"\ud83d\udfe2\"}\n \n # Sensitive data warnings\n if any(keyword in path for keyword in [\"ssn\", \"api_key\", \"password\"]):\n return {\n \"text\": \"\ud83d\udea8 Sensitive data - handle with care\",\n \"icon\": \"\ud83d\udea8\"\n }\n \n return None\n\n# Advanced tooltip configuration for better UX\nadvanced_config = {\n \"placement\": \"auto\", # Auto-position based on available space\n \"animation\": \"fade\", # Smooth fade animation\n \"delay\": [300, 100], # Quick show, delayed hide\n \"interactive\": True, # Allow interaction with tooltip content\n \"maxWidth\": 400, # Wider tooltips for more content\n \"hideOnClick\": False, # Keep tooltips persistent\n \"appendTo\": \"parent\" # Better positioning within container\n}\n\nselected = json_viewer(\n data=data,\n help_text=help_text,\n tags=tags,\n dynamic_tooltips=advanced_tooltips,\n tooltip_config=advanced_config,\n tooltip_icon=\"\u2139\ufe0f\",\n height=600\n)\n\n# Handle field selection with detailed information\nif selected:\n st.sidebar.header(\"Field Details\")\n st.sidebar.json({\n \"Path\": selected['path'],\n \"Value\": selected['value'],\n \"Type\": type(selected['value']).__name__,\n \"Help\": selected.get('help_text', 'No help available')\n })\n```\n\n## Parameters\n\n- **data** (dict): The JSON data to display\n- **help_text** (dict, optional): Dictionary mapping field paths to help text\n- **tags** (dict, optional): Dictionary mapping field paths to tags/labels\n- **dynamic_tooltips** (function, optional): Function that takes (field_path, field_value, full_data) and returns tooltip text or dict with text and icon\n- **tooltip_config** (dict, optional): Tippy.js configuration options (see Tooltip Configuration below)\n- **tooltip_icon** (str, optional): Default icon for tooltips (default: \"\u2139\ufe0f\")\n- **height** (int, optional): Height of the component in pixels (default: 400)\n- **key** (str, optional): Unique key for the component\n\n### Tooltip Configuration Options\n\nThe `tooltip_config` parameter accepts any valid [Tippy.js options](https://atomiks.github.io/tippyjs/v6/all-props/):\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `placement` | str | \"top\" | Tooltip position: \"top\", \"bottom\", \"left\", \"right\", \"auto\" |\n| `animation` | str | \"fade\" | Animation type: \"fade\", \"shift-away\", \"shift-toward\", \"scale\", \"perspective\" |\n| `delay` | int/list | 0 | Show delay in ms, or [show_delay, hide_delay] |\n| `duration` | int/list | [300, 250] | Animation duration in ms, or [show_duration, hide_duration] |\n| `interactive` | bool | False | Allow hovering over tooltip content |\n| `maxWidth` | int | 350 | Maximum width in pixels |\n| `trigger` | str | \"mouseenter focus\" | Events that trigger tooltip |\n| `hideOnClick` | bool | True | Hide tooltip when clicking |\n| `sticky` | bool | False | Tooltip follows cursor movement |\n| `arrow` | bool | True | Show pointing arrow |\n| `theme` | str | \"light\" | Tooltip theme |\n\n## Field Path Format\n\nField paths use dot notation for objects and bracket notation for arrays:\n- `\"user.name\"` - Object field\n- `\"items[0].title\"` - Array item field\n- `\"settings.preferences.theme\"` - Nested object field\n\n## Development\n\n### Frontend Development\n\n1. Set up the development environment (see Development Setup above)\n\n2. Navigate to the frontend directory:\n ```bash\n cd streamlit_json_tip/frontend\n ```\n\n3. Install frontend dependencies:\n ```bash\n npm install\n ```\n\n4. Start development server:\n ```bash\n npm start\n ```\n\n5. In your Python code, set `_RELEASE = False` in `__init__.py`\n\n6. Run the example app in another terminal:\n ```bash\n uv run streamlit run example_app.py\n ```\n\n### Running Tests\n\n#### Python Tests\n```bash\n# Run all Python unit tests with coverage\nuv run pytest\n\n# Run tests with verbose output\nuv run pytest -v\n\n# Generate HTML coverage report\nuv run pytest --cov-report=html\n```\n\n#### Frontend Tests\n```bash\ncd streamlit_json_tip/frontend\n\n# Run Jest tests once\nnpm test -- --ci --watchAll=false\n\n# Run tests with coverage\nnpm test -- --coverage --ci --watchAll=false\n\n# Run tests in watch mode (for development)\nnpm test\n```\n\n#### Run All Tests\nBoth Python and frontend tests run automatically in GitHub Actions on every push and pull request.\n\n### Building for Production\n\n1. Build the frontend:\n ```bash\n cd streamlit_json_tip/frontend\n npm run build\n ```\n\n2. Set `_RELEASE = True` in `__init__.py`\n\n3. Build the Python package:\n ```bash\n uv run python -m build\n ```\n\n4. Upload to PyPI:\n ```bash\n uv run python -m twine upload dist/*\n ```\n\n### Build Scripts\n\nThe project includes convenient uv scripts for common development tasks:\n\n#### Frontend Development\n```bash\ntask build-frontend\n```\n\n#### Package Building\n```bash\nuv run clean # Clean build artifacts\nuv run build # Clean + build Python package\nuv run build-check # Build + validate package with twine\n```\n\n#### Publishing\n```bash\ntask release-test # Build + upload to TestPyPI\ntask release # Build + upload to PyPI\n```\n\nThis will build the frontend, package the Python distribution, validate it, and upload to PyPI.\n\n## Releasing a New Version\n\nThis project uses automated GitHub Actions for releases. Follow these steps to release a new version:\n\n### 1. Update Version and Changelog\n\n1. **Update the version** in `pyproject.toml`:\n ```toml\n version = \"0.2.5\" # Increment according to semver\n ```\n\n2. **Add changelog entry** in `CHANGELOG.md`:\n ```markdown\n ## [0.2.5] - 2025-01-26\n\n ### \u2728 Added\n - New feature description\n\n ### \ud83d\udd27 Fixed \n - Bug fix description\n ```\n\n3. **Commit your changes**:\n ```bash\n git add pyproject.toml CHANGELOG.md\n git commit -m \"Bump version to 0.2.5\"\n git push origin main\n ```\n\n### 2. Create and Push Release Tag\n\n```bash\ngit tag v0.2.5\ngit push origin v0.2.5\n```\n\n### 3. Automated Release Process\n\nOnce you push the tag, GitHub Actions will automatically:\n\n- \u2705 Build the frontend (React components)\n- \u2705 Build the Python package (wheel + source distribution)\n- \u2705 Extract changelog section for this version\n- \u2705 Create GitHub Release with changelog as release notes\n- \u2705 Upload distribution files as release assets\n- \u2705 Publish to PyPI\n\n### 4. Monitor the Release\n\n1. **Check GitHub Actions**: Go to the Actions tab to monitor the release workflow\n2. **Verify GitHub Release**: Check that the release was created with proper changelog\n3. **Verify PyPI**: Confirm the new version appears on PyPI\n\n### Setup Requirements (One-time)\n\nTo use automated releases, you need:\n\n1. **PyPI API Token**: Add `PYPI_API_TOKEN` to your repository secrets\n - Go to: Repository \u2192 Settings \u2192 Secrets and variables \u2192 Actions\n - Add your PyPI token as `PYPI_API_TOKEN`\n\n### Manual Release (Alternative)\n\nIf you prefer manual releases or need to troubleshoot:\n\n```bash\n# Build everything\ntask build\n\n# Upload to PyPI manually\nexport TWINE_PASSWORD=your_pypi_token_here\npython -m twine upload --username __token__ dist/*\n```\n\n## License\n\nMIT License\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "A Streamlit custom component for viewing JSON with interactive tooltips and tags",
"version": "0.2.8",
"project_urls": {
"Bug Tracker": "https://github.com/isaac/streamlit-json-tip/issues",
"Documentation": "https://github.com/isaac/streamlit-json-tip#readme",
"Homepage": "https://github.com/isaac/streamlit-json-tip",
"Repository": "https://github.com/isaac/streamlit-json-tip"
},
"split_keywords": [
"streamlit",
" json",
" viewer",
" tooltip",
" component",
" interactive"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "e7c910571810a0ba53bc013d111981feb2ba2f54b3845b953cb12a3c60672a96",
"md5": "b4abc46f6e0451ffc7ac1b266161dd48",
"sha256": "d0deec64c1b32a1288dea76f132c99baa4ca2de84895e386efcb1864c7476f92"
},
"downloads": -1,
"filename": "streamlit_json_tip-0.2.8-py3-none-any.whl",
"has_sig": false,
"md5_digest": "b4abc46f6e0451ffc7ac1b266161dd48",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 667939,
"upload_time": "2025-08-21T02:39:18",
"upload_time_iso_8601": "2025-08-21T02:39:18.155822Z",
"url": "https://files.pythonhosted.org/packages/e7/c9/10571810a0ba53bc013d111981feb2ba2f54b3845b953cb12a3c60672a96/streamlit_json_tip-0.2.8-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "9b40e41de1c10de9e64e40c5f38f3d06a41720ad82a4c02b55215195c114e995",
"md5": "acd75b55fa9d6627c5d01818dc1d8630",
"sha256": "4a5083784e12e3e6b1821e7d5fcdd745546cc4ca16cd66691d279b73e1c6673c"
},
"downloads": -1,
"filename": "streamlit_json_tip-0.2.8.tar.gz",
"has_sig": false,
"md5_digest": "acd75b55fa9d6627c5d01818dc1d8630",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 941818,
"upload_time": "2025-08-21T02:39:19",
"upload_time_iso_8601": "2025-08-21T02:39:19.519387Z",
"url": "https://files.pythonhosted.org/packages/9b/40/e41de1c10de9e64e40c5f38f3d06a41720ad82a4c02b55215195c114e995/streamlit_json_tip-0.2.8.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-21 02:39:19",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "yourusername",
"github_project": "streamlit-json-tip",
"github_not_found": true,
"lcname": "streamlit-json-tip"
}