# Changelog
Source: https://docs.evidence.studio/changelog
Track the latest updates and improvements to Evidence
### ✨ Scheduled Reports
Email reports to your users on a regular schedule, or send one-off reports on demand.
### ✨ Access Viewer AI inside Slack
Connect a Slack workspace in Integration settings and message the Evidence bot to get answers from your data without leaving Slack.
* An admin adds the app from Settings → Integrations → Slack, then each person connects their own account — the bot only reads what you can already see.
* Direct message the bot, or @mention it in a channel.
* Answers can display charts, save insights to your library, and link back into Evidence.
* Admins can turn the bot off for the whole organization, and choose whether each person's first answer in a channel is shown to them before the channel sees it.
### 🐛 Partial filter initial values now apply on parent pages
Fixed an issue where filter initial values defined in partials could be empty when rendered on parent pages.
### 🐛 Filters load in partial page previews
Filters in partials now load when using View another page in the editor.
### 🐛 Link buttons support relative page URLs
Link buttons now navigate correctly with portable relative URLs across edit, preview, and published reports.
### 🐛 Table filters close safely without selections
Table filters now remain visible when a numeric or date picker is closed without a selection.
### 🐛 Sorting a table by a column it does not show
Sorting a table by a column that is not one of its dimensions or measures no longer splits the rows into extra groups, and no longer fails on Postgres, Fabric and Cube.
### 🐛 ClickHouse conditional aggregates
Fix `sumIf` and its `-If` siblings breaking date-filtered measures and comparison targets on ClickHouse, and no longer warn that they are missing an aggregation.
### 🐛 Snowflake table conditional colors
Fix conditional colors on table dimensions in Snowflake for literal colors and SQL expressions.
### 🐛 Sorting a table by a grouped date column
Sorting a table by a date column that has a `date_grain` now sorts by the grouped date instead of failing with a grouping error.
* `order="my_date desc"` alongside `{% dimension value="my_date" date_grain="day" /%}` sorted by the raw column, which the warehouse never grouped. ClickHouse rejected the query and the table rendered empty.
* A hidden sort column on a table with subtotals is now aggregated, so it no longer breaks the subtotal and total rows.
### 🐛 Creating files and folders is disabled on protected branches
The sidebar's create page, partial, SQL, component, folder, and agent-file actions are now disabled when the current branch is protected on GitHub, matching the existing branch-protection guard on Commit.
### 🚀 Big value titles are clickable when linked
Setting `link` on a big value now turns the title into a styled link instead of the number, matching typical score card conventions.
### ✨ Metrics
Evidence now has a metrics layer. Define metrics in `metrics/*.yaml` and reference them in charts and tables. Ask the agent to build one for you to get started.
### ✨ MCP Visualize Tool
The Evidence Studio Claude Connector and ChatGPT Plugin can now generate charts inline in the chat with the new `visualize` tool.
### ✨ Reports page for run history and schedules
A new top-level Reports page (next to Models) for viewing report run history and managing schedules.
* **History tab**: View all report runs with status, trigger type (manual/schedule/API), author, timing, and recipient count
* **Schedules tab**: View and manage recurring report schedules with pause/resume and delete actions
* **Admin-only actions**: Pause/resume schedules, delete schedules, re-run past reports, download PDFs
* **Developer access**: Developers (members) can view the page; admins can take all actions
* **Entitlement gate**: Available on Team, Pro, and Enterprise plans
### ✨ GitHub Enterprise Cloud support
Enterprise organizations can now connect Evidence Studio and the Evidence CLI to GitHub Enterprise Cloud accounts hosted on dedicated `*.ghe.com` domains.
* Create and install a private, organization-owned GitHub App through Organization Settings.
* Select accessible enterprise repositories in Project Settings and use Studio branches, pull requests, checks, and publishing as usual.
* Run `evidence launch` or `evidence link` from HTTPS and SSH GHE.com remotes.
### 🐛 Feature request dialogs remain accessible with long descriptions
Feature request dialogs now constrain long descriptions to a scrollable area so their controls remain accessible.
### 🐛 Table links now work in fullscreen reports
Table links now navigate to their destination while viewing a report in fullscreen presentation mode.
### ✨ MotherDuck direct connector
Connect Evidence directly to a MotherDuck database to build reports on live data without syncing it first.
[View Documentation](https://docs.evidence.studio/direct-connectors/motherduck)
### ✨ Custom Maps
Use the `custom_map` component to build fully customized maps with Mapbox GL or MapLibre GL.
* Write map code directly in the component body — pull page data with `evidence.query`, read and write page filters, and react to variables and theme changes.
* No key needed by default: keyless MapLibre out of the box, or Mapbox using Evidence's shared token under the hood.
* Import map-ecosystem plugins (mapbox-gl-draw, deck.gl, turf, and more) straight from a CDN.
### 🐛 Custom HTML and ECharts blocks work in the CLI
`{% html %}` and `{% custom_echart %}` blocks now render when running a project locally with the Evidence CLI.
* Both blocks previously rendered blank in `evidence dev` — the sandbox runtime they load was only built by the hosted app, so the CLI served nothing for it
* Requires CLI v0.7.4 or later
* If a sandbox runtime is ever missing, the block now reports an explicit error instead of staying blank
### 🚀 AI chat now consumes far fewer credits
We've significantly reduced how many credits AI chat consumes, so your balance goes much further.
### ✨ Cube Connector
Connect Evidence directly to your Cube semantic layer through its Postgres-wire SQL API.
* Query your cubes and views live from Evidence — metrics stay defined in Cube.
* Configure it in **Connectors → Warehouse → Cube** (host, port, user, password, SSL), or via `connection.yaml` (`type: cube`) in the CLI.
* The SQL editor validates expressions against Cube's documented function subset, so unsupported functions are flagged before you run a query.
### ✨ PDF "Use page colors" option
Preserve the exact colors from your page when generating PDFs.
* New "Use page colors" checkbox in the PDF settings modal (Cmd+P)
* When enabled, PDFs retain the theme's actual background colors (including dark mode or custom theme backgrounds)
* When disabled (default), PDFs use white backgrounds optimized for printing
* Preview updates to show how the PDF will look with the selected option
### ✨ Postgres Direct Connector
Connect Evidence directly to Postgres — including Amazon RDS/Aurora, Supabase, Neon, and Timescale — and query it live.
* Add Postgres under Settings → Warehouse: enter host, port, database, user, password, and SSL mode, test the connection, and save.
* Works with any Postgres-wire source: generic Postgres, Amazon RDS / Aurora, Supabase, Neon, and Timescale.
* Full SSL/TLS support with `disable` / `require` / `verify-ca` / `verify-full` modes, plus an optional CA bundle and mutual-TLS client certificate.
* The schema browser lists tables, views, and materialized views.
* Also available from the CLI via `connection.yaml` (`type: postgres`) or `evidence init --warehouse postgres`, with certificates referenced by file path.
### ✨ Search across your reports with Cmd+K
Press Cmd/Ctrl+K to instantly search across every report you have access to.
### ✨ Viewer AI & Insights
Report viewers can now ask questions of your data in a chat assistant and save the answers as insights to revisit later.
### 🐛 Fixed editor inserting characters at the wrong position on older reports
Typing in the editor now appears where you clicked on reports created before mid-2026.
### ✨ Evidence Studio MCP Server
Search your reports and query your data from your favorite AI client. Connect Claude, ChatGPT, and other MCP clients to your live Evidence workspace — every request runs as the signed-in user, so access policies and page controls are respected.
[View Documentation](https://docs.evidence.studio/mcp/studio)
### 🐛 CLI dev server no longer crashes when a subfolder has an index.md
Nested `index.md` / `home.md` / `README.md` files are no longer treated as the home page in the sidebar, so `evidence dev` renders normally instead of crashing with a duplicate-key error when a project has a root home page plus an `index.md` in a subfolder.
### ✨ Point Map Clustering
You can now include up to 100,000 points in a point layer by using `cluster=true`. Nearby points are grouped into aggregated bubbles that split apart as you zoom in, so large datasets stay fast and readable.
### ✨ 50 New Data Connectors
Connect 50 more data sources to Evidence, including Zendesk, Intercom, Mixpanel, Amplitude, Square, QuickBooks, Recurly, Pipedrive, Gong, LinkedIn Ads, and more. Set them up in a few clicks from the Connectors page.
### ✨ 50 More Data Connectors
Another 50 data sources are now available, including Jira, Airtable, Asana, Notion, Slack, Klaviyo, Mailchimp, Braze, SendGrid, TikTok Ads, Amazon Ads, Google Search Console, ServiceNow, and Okta. Set them up in a few clicks from the Connectors page.
### ✨ Lemlist Connector
Connect your Lemlist data to Evidence. Sync campaigns, leads, and activities from your email outreach.
[View Documentation](https://docs.evidence.studio/data-sources/lemlist)
### 🚀 Improved chart x-axis and tooltip labels
Better handling of dates and numbers on chart x-axes and tooltips.
### ✨ Table Access Restrictions
Restrict tables to a chosen set of users
Restrict specific tables to a chosen set of users from the Access Rules settings page. Unrestricted tables stay open to everyone in the organization, and restricted tables show a lock badge in the editor's schema list.
[View Documentation](https://docs.evidence.studio/features/access-rules)
### ✨ Image component accepts data queries
Add `data` and `column` props to the image component to load the image URL from a query and respond to filter changes — e.g. show the top-selling product's photo, a client logo driven by a dropdown, or a dark-mode variant via `dark_column`.
### ✨ Radar, Treemap, and Chord charts
Three new charts now available: radar\_chart, treemap, and chord\_chart
### ✨ Mix single and multi select columns in table filters
Add `single_select` and `multi_select` to `table_filter` to set the selection mode per column — e.g. restrict a client column to one value at a time while keeping region and product filters multi-select.
### 🐛 Y-axis titles stay legible above chart data
Chart contents no longer overlap the y-axis title — bars, areas, and lines that reach the top of the axis now render beneath the title instead of covering it. Gridlines are cut off cleanly behind the title rather than showing through the text, the title is vertically aligned with the top axis tick label, and a subtle text outline keeps it readable when data passes directly beneath it. Applies to both left and right (`y2`) axis titles.
### 🐛 range\_calendar "all time" no longer breaks raw SQL
Referencing `{{ date_filter.between }}` in a `where` or SQL template while "all time" was selected previously produced an empty string, which broke the query (`where date ` → syntax error). `.between` now emits `IS NOT NULL` for "all time", so `where="date {{ date_filter.between }}"` matches all rows and just works.
The new `all_time_range` attribute controls what "all time" means for a specific `range_calendar`:
* `all_time_range="none"` restores the previous empty-string behavior — pair it with `[[ ]]` conditional blocks or a `| fallback` when the whole clause should drop (e.g. to keep NULL-date rows, which `IS NOT NULL` otherwise excludes).
* Set it to a bounded range — a preset key (`"last 12 months"`), a `custom_ranges` label, or a range expression (`"from 2022-12-01"`) — and "all time" resolves to that range everywhere (`.between`, `.start`, `.end`, and the `date_range` value). If you were faking this with a `| fallback` in your `where` clause, set `all_time_range` to that range and delete the fallback.
`.start` / `.end` stay empty for unbounded "all time" (so date spines and axes fail loudly rather than silently wrong), and `.filter` / a `filters=[...]` reference stay a true no-op that keeps NULL rows.
### 🐛 Fix for AI chat losing conversation context
Fixed an issue where the AI chat could respond to an earlier message in long conversations instead of the one you just sent.
### 🐛 Sparkline hover values now use theme foreground
Sparkline hover values and the vertical tracking line follow the theme's foreground and muted-foreground tokens, restoring contrast in light mode (most visible on big\_value sparklines).
### ✨ AI Agent Multi-File Edits
The AI dev assistant can now edit multiple files in a single turn — as well as create, rename, and move files.
### ✨ Extra tooltip rows on chart series
Add `tooltip_fields` to any `bar_chart` / `line_chart` / `area_chart` / `scatter_chart` / `bubble_chart` — or to `bar`, `line`, `area`, `scatter`, `bubble` inside a `combo_chart` — to surface additional aggregated values on hover, with optional labels, format codes, and `color_by_sign` / `down_is_good` for delta-style coloring.
### ✨ Link charts together
Add `connect_group` to charts to sync their tooltips, axis-pointer, and zoom across any charts sharing the same id — e.g. stack a price chart above a volume chart, align KPIs that share a time axis, or coordinate small multiples.
### ✨ Customize built-in charts with ECharts options
Override any ECharts option on built-in charts via `echarts_options` (chart-wide) or `echarts_series_options` (looped across every series).
### ✨ Attach images to editor AI chat
Click the image button in the editor chat composer to attach screenshots or other images for the AI agent to see alongside your message.
### ✨ Custom components
Build your own Markdoc tags from `components/*.md` files — each component declares its attributes in frontmatter and gets autocomplete, slash-command, and AI-tool support just like a built-in.
### ✨ Pin color scale values in tables
Anchor a measure's color scale to specific data values with `color_stops`.
### ✨ Custom HTML in reports
Embed your own HTML and JavaScript anywhere in a report with the new `{% html %}` block. Build custom visualizations that integrate with Evidence's filters, queries, and theme — using any library, like D3 or deck.gl.
### 🐛 Hide unneeded subtotal rows in tables
Tables now hide duplicative subtotal rows that only summarize a single item, while keeping the grand total.
### ✨ Expanded theme options
Themes now include fonts, colors, corner roundness, spacing density, and chart defaults, applied consistently across the whole report. Override the theme for a single page when you need to.
### ✨ Custom date ranges
Add `custom_ranges` to `{% range_calendar %}` to generate named presets — e.g. fiscal years, seasons, and retail calendars.
### 🐛 Smoother schema panel refresh
The refresh button no longer pushes content down or hides the schema list while reloading, and long table or column names truncate instead of forcing horizontal scroll.
### ✨ Show size dimension in bubble and scatter chart tooltips
Bubble and scatter chart tooltips now display the size dimension value, with a new `size_fmt` attribute for formatting.
### 🐛 Faster, more reliable editor preview on heavy pages
Fixed an issue where the editor could lock up on pages with many charts and tables.
### 🐛 Fix heatmap collapsing at wider screen widths
Fixed heatmap charts collapsing into a small box at certain screen widths.
### ✨ Impersonate
Create and manage access tokens for programmatic API access from the new Access Tokens settings page. Admins and developers can impersonate team members to see exactly what they see (disabled by default).
### 🐛 Fix dropdown search failing on BigQuery
Fixed an issue with searching a dropdown or table filter for BigQuery direct connections.
### ✨ Failed Publishes No Longer Affect Viewers
If a publish fails, your project keeps serving the last successful version — viewers never see broken content.
### 🐛 Fix spurious markdown validation errors on PRs
Fixed the PR markdown-validation check reporting false-positive `undefined-translation-key` and `undefined-frontmatter-variable` errors on pages using translations and on partials that receive variables from the pages including them.
### ✨ Publish History & Rollback
View your project's publish history and roll back to any previous version.
### ✨ ClickHouse direct connector
Connect Evidence directly to your own ClickHouse instance to build reports on live data without syncing it first.
[View Documentation](https://docs.evidence.studio/direct-connectors/clickhouse)
### ✨ Make the selected option in `button_group` and `input_tabs` more noticeable
The selected button in `button_group` and the active tab in `input_tabs` now stand out more clearly.
### ✨ New share menu and additive page access
The redesigned share menu lets you grant page-level access on top of project access, so you can share a single dashboard with a stakeholder who shouldn't see anything else.
### ✨ Vibe code any visualization with the custom\_echart component
Need a chart Evidence doesn't have out of the box — a waterfall, a bridge, a radar, something bespoke? The new `custom_echart` component lets you build any visualization you can imagine. Describe what you want to the assistant and it writes the chart for you, wired up to your data, filters, and theme automatically.
### ✨ Pre-select the top N options in a multi-select dropdown
Multi-select dropdowns now accept a `default_top_n` attribute that pre-selects the first N options on load. Combine it with `order` to control which N are selected by default — which viewers can then change.
### ✨ New Publish Menu in Editor
View pending changes and open pull requests directly from Studio.
### ✨ See what each user, group, and customer can access
Admins and developers can now see every project and page a user, group, or customer can access, plus how that access was granted.
### 🐛 Share menu now lets you grant page access to any team member
The Page tab of the share menu now lists every internal team member, so you can grant page access directly without first adding them to the parent project.
### 🚀 Add users to groups when inviting, and see group memberships in the team table
Admins can now pick groups when inviting or manually creating users, and the Team settings page shows each member's group memberships in its own column.
### 🚀 HubSpot Connector
Updated the HubSpot connector with more reliable syncs and broader table coverage.
[View Documentation](https://docs.evidence.studio/data-sources/hubspot)
### ✨ Microsoft Fabric direct connector
Connect Evidence directly to a Microsoft Fabric Warehouse or Lakehouse SQL endpoint to build reports on live data without syncing it first.
[View Documentation](https://docs.evidence.studio/direct-connectors/fabric)
### 🐛 PDF exports preserve dropdown filter values
PDF exports of pages with a `select_first=true` dropdown no longer revert the filter to its auto-selected default when the URL specifies a different value.
### ✨ Map area layer min, max, and midpoint
Map `area_layer` and `point_layer` now accept `min`, `max`, and `midpoint` props so you can pin a diverging color scale at zero (or any other value).
### 🐛 Fixed bar chart tooltip not displaying point\_title
Fixed an issue where the `point_title` attribute on bar, line, and area charts was ignored in the tooltip.
### ✨ File change indicators in editor sidebar
Files with uncommitted changes now show colored status badges (M/A/D) in the editor sidebar file tree, so you can see which files have been modified without switching to the Version Control tab.
### ✨ Copy link to pages
Copy a shareable link to the current page from the page menu, with option to include the current filters.
### ✨ Download report as PNG
Save a full page as a PNG image from the page menu.
### 🚀 Dedicated Groups settings page
Groups now have their own page under Settings → Groups, separate from team members, with a detail view for managing each group's members and access.
### ✨ Snowflake and BigQuery direct connectors
Link Evidence to Snowflake or BigQuery directly to build reports without syncing data.
[View Documentation](https://docs.evidence.studio/direct-connectors/snowflake)
### 🚀 Improved discoverability of date input components in AI chat
Added search keywords to `range_calendar`, `date_grain_selector`, and `comparison_selector` so the AI assistant can find them when users ask for "date range filter", "date picker", "date input", etc.
### 🚀 Long chart label rotation
Charts now rotate long x-axis labels automatically so category names are easier to read without hovering.
### 🐛 Map area layer filter updates
Fixed a bug where area charts did not respond to filter changes.
### 🚀 Data download title filenames
Data downloads now use titles in file names.
### 🐛 Horizontal bar chart axis bound validation
The `horizontal_bar_chart` now reports a validation error when `x_axis_options.min` is greater than or equal to `x_axis_options.max`.
### ✨ Evidence CLI now available on Windows
The Evidence CLI now ships a Windows x64 binary, installable via PowerShell: `irm https://gaamozau3jchzs3r.public.blob.vercel-storage.com/cli/install.ps1 | iex`.
[View Documentation](https://docs.evidence.studio/cli)
### 🚀 Default tab selection
Add `default=true` to a `{% tab %}` to pre-select it on page load instead of always defaulting to the first tab.
### 🐛 Data labels render on area and line charts
Fixed `data_labels` not appearing on `area_chart`, `line_chart`, and `combo_chart` line/area series.
### ✨ Add today and yesterday range calendar presets
Range calendars can now opt into Today and Yesterday preset ranges.
### 🚀 Faster Page Create and Rename
Creating, renaming, and reorganizing pages and folders in the editor sidebar is noticeably faster.
### 🐛 Mobile sidebars close after navigation
Fixed mobile sidebars staying open after selecting a navigation link.
### 🐛 Improved SQL file support in GitHub integration
Improved how SQL files sync between Studio and GitHub.
### 🐛 Branch-aware link autocomplete and validation
Editor link autocomplete and validation now include pages that exist only on the current branch, and AI chat no longer flags them as broken.
### 🐛 AI chat current date awareness
Fixed AI chat date context so the agent knows today's date when answering in editor and viewer chats.
### 🐛 Locally-authored pages now appear in Studio
Fixed an issue where files created locally and synced to GitHub were not appearing in Studio.
### 🐛 Stable heading logo sizing
Fixed an issue where logos inside headings could briefly render at the wrong size on page load.
### 🐛 Fix unquoted variables in partial attributes
Fixed an issue where unquoted variable references in component attributes failed when rendered from partials.
### 🐛 Fix x\_sort="data" imposing an x-axis sort
Fixed an issue where setting `x_sort="data"` on bar and line charts still sorted by the x-axis instead of preserving the source query's row order.
### 🐛 Embedded page centering without TOC
Fixed an issue where embedded pages could stay shifted to the left after the table of contents was turned off.
### 🐛 Stable logo sizing on load
Fixed an issue where logos in headings could briefly render at the wrong size while the page was loading.
### 🐛 Improved models table readability
Fixed an issue where the models table was not sorted by name by default and long descriptions were hard to scan.
### ✨ Select content for PDF exports
Choose which sections and components to include when exporting a PDF.
### 🐛 Source failure modal fix
Fixed an issue where opening a failed source status could show a blank blocking modal instead of the failure details.
### 🚀 Longer AI chat sessions
Increased the maximum AI chat response time so longer agentic conversations no longer time out.
### 🚀 Collapsible projects in published and preview sidebars
Projects in the sidebar can now be collapsed and expanded by clicking the project name, with state persisted across sessions.
### 🚀 Table Actions
Download and Fullscreen buttons now available in Table footers.
### 🚀 Claude Opus 4.7
The Evidence agent now uses Claude Opus 4.7 by default.
### ✨ Connector renaming
You can now rename connectors directly from the connectors page or the connector detail page by clicking the pencil icon next to the name.
### 🐛 Dropdown search now handles nullable values safely
Fixed an issue where searching in a dropdown could fail when the value or label column contained empty values.
### ✨ Data lineage
See where your connectors and tables are used across projects, pages, models, and queries. Available in the connectors page, connector detail pages, models page, AI chat, and the CLI.
### 🚀 Resizable SQL console schema panel
The SQL console schema panel can now be resized by dragging its edge so long table names are easier to inspect.
### ✨ Connector and model health status
Connectors page now shows health status and sync schedule for all connector types. New `connectors` and `models` CLI commands let you check health statuses from the command line.
### 🐛 Fixed theme settings loading state while editing colors
Fixed an issue where editing theme color values could cause a broken loading state in settings.
### 🐛 Fixed inline SQL editor query references
Fixed an issue where inline SQL editor queries could fail when referencing other inline queries.
### 🐛 Fixed unexpectedly large branch diffs
Fixed an issue where small edits in Git-connected branches could appear as much larger diffs than expected.
### 🐛 Fixed stacked combo charts on time-based axes
Fixed an issue where stacked combo charts on time-based axes could render blank or incorrect series data.
### 🐛 Fixed filter bar not floating on scroll in published pages
Fixed an issue where the filter bar would not stay pinned to the top of the page when scrolling in published mode.
### ✨ Usage Analytics
Track how your team uses Evidence with built in analytics tables for sessions, users and page views.
### 🐛 AI theme updates apply instantly
Fixed an issue where theme changes made by the AI assistant only appeared after a page refresh.
### ✨ Audio Component
Embed an audio player in your reports with `{% audio url="..." /%}`. Supports mp3, wav, ogg, and other formats, with options for looping, autoplay, and preload behavior.
### 🐛 Calendar heatmap dark mode colors
Fixed an issue where calendar heatmaps could show white empty-day cells in dark mode instead of blending with the page or card background.
### ✨ Conditional colors for dimensions and rows
Apply conditional background colors to entire rows or individual dimension cells using SQL expressions.
### 🐛 Fixed table SQL error overlay spacing
Fixed an issue where table SQL errors could overlap content below the table.
### 🐛 Expanded background color options for AI theme updates
Expanded the background color options the AI agent can change in theme updates.
### ✨ YouTube Analytics Connector
Connect your YouTube Analytics data to Evidence. Sync channel reports, content owner reports, and metadata tables.
[View Documentation](https://docs.evidence.studio/data-sources/youtube_analytics)
### 🐛 Fixed combo chart SQL with toggle-driven inline queries
Fixed an issue where combo charts could fail when inline queries used toggle values in SQL conditions.
### ✨ Multiplayer editor
Collaborate with your team in real-time with live cursors and presence indicators.
### ✨ Axis titles for heatmaps
Heatmaps now support `x_axis_title` and `y_axis_title` so you can label both axes directly on the chart.
### 🐛 Fix for table column groups with link attribute
Fixed an issue where adding a `link` attribute to a table dimension would cause all column groups to disappear.
### 🐛 Fixed spacing in the back-to-partial label
Fixed an issue where the "Back to partial" label appeared without a space in preview mode.
### 🐛 Horizontal bar chart axis min/max now apply exactly
Fixed an issue where `x_axis_options.min` and `x_axis_options.max` on horizontal bar charts could be ignored instead of enforcing the requested axis range.
### ✨ SAP HANA Connector
Connect your SAP HANA data to Evidence. Sync data from SAP ECC and SAP S/4HANA systems running on the HANA platform.
[View Documentation](https://docs.evidence.studio/data-sources/sap_hana_db)
### 🐛 Fix slider lockup with invalid step values
Fixed an issue where sliders could freeze the page when configured with an invalid step value.
### ✨ Third-party analytics for published pages
You can now add your own Google Analytics (GA4) or PostHog tracking to published and embedded pages. Configure your analytics provider in Organization Settings under Third-Party Analytics. Available on Enterprise plans.
### 🚀 Collapsible folders in published and preview sidebars
Added click-to-expand and collapse behavior for sidebar folders in published and preview pages to make navigation easier in larger projects.
### ✨ Added This Month and Next Month date presets
Range calendars now support `this month` and `next month` presets so you can filter full calendar months including upcoming dates.
### 🐛 Dropdown options now support numeric values for initial selection
Fixed an issue where dropdown initial values could fail to apply when option values were provided as numbers.
### 🚀 Loading indicator for map components
Map components now show a loading indicator while map data is being fetched so blank maps are less confusing during slow queries.
### 🐛 Fix for occasional AI chat timeouts
Fixed an issue where the AI agent could appear to run out of time when working with large queries.
### 🐛 Fix for table search
Fixed an issue where searching in tables could produce errors or fail to recover after clearing a search.
### 🐛 Fix table sorting when subtotal rows are hidden
Fixed an issue where sorting by measure columns in tables could produce incorrect order when subtotal rows were hidden.
### 🚀 Add mmm-yy date format
Added a built-in `mmm-yy` format code so dates can be displayed as month and two-digit year, like `Jan-22`.
### 🐛 Fix mobile sidebar close animation flicker
Fixed an issue where the sidebar would briefly flash back into view at the end of its close animation on mobile devices.
### 🚀 Resizable Sidebar
The sidebar can now be resized by dragging its edge.
### 🐛 Comparison column formatting fix
Fixed an issue where prior period comparison columns in tables did not apply the same number format as the main value column.
### ✨ Evidence CLI
Develop Evidence Studio projects locally from the command line with `evidence dev`.
[View Documentation](https://docs.evidence.studio/cli)
### 🐛 Improve filter value visibility in the editor sidebar
Fixed an issue where filter values in the editor sidebar could be hard to read by showing each value on its own line.
### 🐛 Recent AI chats update instantly
Fixed an issue where new AI chats would not appear in Recent chats until the page was refreshed.
### 🐛 Improved spacing for small tables
Fixed an issue where tables with only a few rows could show unnecessary empty space.
### 🚀 Clearer error when defining queries inside components
Added a validation error when inline queries are defined inside components like tabs, accordion, or details. Queries should be defined at the top level of the page.
### 🐛 Accordion items now maintain their original order
Fixed an issue where accordion items could reorder themselves based on when they were last updated instead of their original document order.
### 🐛 Support for branch names with slashes in GitHub integration
Fixed an issue where branches containing slashes (e.g., `feature/my-branch`) would break navigation across the editor, preview, published views, and PDF generation.
### 🐛 Button group and dropdown initial value fix
Fixed an issue where button groups and dropdowns could not set an initial value when using a numeric value column.
### 🐛 Fixed organization logo display in dark mode on published pages
Fixed an issue where the organization logo in the sidebar could appear as a dark image on a dark background when viewing published pages in dark mode.
### 🚀 Option to hide axis title arrow
Added a `title_arrow` option to `x_axis_options` that lets you hide the arrow (→) on chart axis titles.
### 🚀 Demo data table references updated
Demo data tables have moved to the `demo` schema (e.g. `demo_daily_orders` → `demo.daily_orders`). You may need to update references in existing projects and models.
### 🐛 Fixed model save failing after validation
Fixed an issue where saving a model could fail if the SQL query contained leading or trailing whitespace.
### 🐛 PDF downloads from editor now use working version
Fixed an issue where downloading a PDF from the editor would always produce the committed version instead of the current working draft.
### 🐛 Print group cards spacing fix
Fixed an issue where wrapping components in a print group with cards layout enabled would remove the spacing between cards.
### 🐛 Google Analytics setup links to Evidence docs
Fixed an issue where the Google Analytics connector setup page linked only to the Fivetran docs instead of the Evidence docs page.
### 🚀 More reliable PDF generation
Improved PDF generation reliability, especially for pages with conditionals, partials, and many components.
### 🐛 PDF downloads from preview now use working version
Fixed an issue where downloading a PDF from the preview route would always produce the published version instead of the working draft.
### 🐛 Fixed chart rendering error on published pages with point\_title
Fixed an issue where charts using the `point_title` attribute could fail to render on published pages.
### 🐛 Fixed scatter chart tooltip with point\_title and series
Fixed an issue where the `point_title` attribute on scatter charts was ignored in the tooltip when a `series` attribute was also set.
### 🐛 Fixed scatter chart size attribute
Fixed an issue where the `size` attribute on scatter charts was ignored, causing all points to render at the same size.
### ✨ Date range support for map layers
Map layers (point\_layer, area\_layer, and heatmap\_layer) now support the `date_range` attribute for filtering data by time period.
### ✨ PayPal Connector
Connect your PayPal data to Evidence. Sync transactions, invoices, payments, subscriptions, and billing plans.
[View Documentation](https://docs.evidence.studio/data-sources/paypal)
### 🚀 Connection string autofill for PostgreSQL connections
You can now paste a PostgreSQL connection string into any field when setting up a PostgreSQL connection, and all fields will be automatically filled in.
### ✨ RevenueCat Connector
Connect your RevenueCat subscription data to Evidence. Sync subscribers, transactions, entitlements, offerings, and products.
[View Documentation](https://docs.evidence.studio/data-sources/revenuecat)
### 🚀 Invite team members from the Share menu
Added a quick link to Team Settings from the Share menu so you can invite new team members while managing page or project access.
### 🐛 Fix for dimension grid with inline queries
Fixed an issue where the dimension grid component could not use inline SQL queries as its data source.
### 🐛 Fix legend color for lines with explicit color in combo charts
Fixed an issue where lines in combo charts with an explicit color option (e.g., `options={color="black"}`) would display the palette color in the legend instead of the specified color.
### 🚀 Improved component search with keyword aliases
Added search keywords to component schemas so components can be found by common alternative names (e.g., "scatter plot" for scatter chart, "donut" for pie chart, "KPI" for big value).
### 🐛 Fix filters with multiple consecutive spaces in values
Fixed an issue where filter values containing multiple consecutive spaces would fail to match data correctly.
### 🐛 Fix collapsible table arrows not showing with hide\_row\_totals
Fixed an issue where collapsible table arrows were not visible when measures had `hide_row_totals` enabled.
### 🐛 Fix branch deletion when branch was already deleted on GitHub
Fixed an issue where deleting branches from the Evidence UI would fail with an error when the branch had already been deleted on GitHub (e.g., by GitHub's auto-delete on merge feature).
### ✨ Candlestick chart component
Added a new candlestick chart component for visualizing OHLC financial data with optional volume bars.
[View Documentation](https://docs.evidence.studio/components/candlestick)
### 🐛 Fix for overlapping content in PDF exports
Fixed an issue that could cause overlapping content in PDF exports.
### ✨ Percentage labels for pie charts
Added `pct` and `pct_fmt` options for pie charts to display percentage values directly on slice labels.
[View Documentation](https://docs.evidence.studio/components/pie_chart#param-pct)
### 🐛 Fix AI chat generating dropdowns and date range filters
Fixed an issue where AI chat could fail when generating dropdowns or date range filters.
### ✨ Salesforce Connector
Connect your Salesforce CRM data to Evidence. Sync accounts, contacts, opportunities, leads, and campaigns.
[View Documentation](https://docs.evidence.studio/data-sources/salesforce)
### 🐛 Fix x\_fmt not applying to chart tooltips
Fixed an issue where setting `x_fmt` on charts would format the axis labels but not the date value shown in the tooltip.
### 🐛 Improved AI chat reliability
Fixed an issue where AI chat could error out during longer conversations.
### ✨ Date Range Support for Input Components
Input components (dropdown, button\_group, input\_tabs, slider, dimension\_grid) now support the `date_range` attribute, allowing you to filter options by a specific time period or a range\_calendar selection.
### 🐛 Fix dropdown with manual options showing SQL error
Fixed an issue where dropdowns using manual child option tags (no `data` attribute) would show an "Unknown table function WHERE" error.
### ✨ Multiplayer editor now in beta
Multiplayer editor is now available in beta. Turn it on from Project Settings to collaborate with your team in real-time.
### 🐛 Graceful redirect when page not found after branch switch or rename
Fixed an issue where switching branches or renaming a page could result in a 404 when the current page doesn't exist on the target branch or at the old URL.
### 🐛 Fix dimension link navigation resulting in 404
Fixed an issue where clicking dimension links in tables would result in a 404 when navigating between pages, because the URL wasn't being resolved relative to the current project context.
### 🐛 Automatic chart padding for data labels
Charts now automatically add top padding when data labels are positioned above bars or points, preventing labels from being cut off at the top of the chart.
### ✨ External GitHub branch support and PR preview links
Projects connected to GitHub now show all repository branches in the branch switcher, not just branches created through Evidence Studio. When a pull request is opened or reopened, Evidence automatically posts a preview link comment on the PR.
### 🚀 SQL Console Table Grouping
Tables in the SQL console sidebar are now organized by schema/connection in a collapsible tree structure for easier navigation.
### ✨ Customizable Total Label for Tables
Tables now support a `total_label` attribute that allows customizing the text displayed in total/subtotal rows and columns, useful when using non-sum aggregations like avg, min, max, or count.
### ✨ Editor Sidebar
Enhanced editor sidebar, with diff viewer, search, table schema, and page filters.
### 🚀 Pivot Table Performance
Significant performance improvements for pivoted tables and increased row/column limits.
### 🐛 Fix dropdowns closing modals
Fixed an issue where clicking on dropdown menus inside a modal would cause the modal to close unexpectedly.
### 🐛 Stable AI Edit Previews
Prevent AI edits from causing full refresh
### ✨ Gradient fill for area charts
Area charts now support a gradient fill option that fades from the series color at the top to transparent at the bottom. Enable it with `area_options={ gradient=true }`.
[View Documentation](https://docs.evidence.studio/components/area_chart#param-area_options)
### ✨ Clock Component
Display a live clock with running seconds and the current date using `{% clock /%}`. Supports 12h/24h format, monospace font variant, and left/right alignment.
### ✨ Branching
Work on multiple versions of your reports at the same time. Create and switch between branches, commit your work, and publish when you're ready.
### ✨ Heat Grid
Visualize metrics across categories with color-coded cells based on configurable thresholds. Cells are colored red, yellow, or green depending on where values fall relative to your thresholds, with an optional `lower_is_better` mode.
### 🚀 Model Engine and Primary Key Settings
The model edit page now includes configurable refresh schedules, table engine selection, and primary key configuration with helpful tooltips explaining each engine type, data locations, and nullable primary key handling.
[View Documentation](https://docs.evidence.studio/core-concepts/models)
### ✨ Progress Bars
Display progress toward goals with horizontal bars showing numerator/denominator ratios. Supports threshold-based coloring and custom color gradients.
### ✨ PDF Export Options
PDF export now supports custom orientation, margins, and card styling options.
### ✨ Datadog Connector
Connect your Datadog monitoring and analytics data to Evidence. Sync metrics, dashboards, monitors, hosts, and usage data from your Datadog account.
[View Documentation](https://docs.evidence.studio/data-sources/datadog)
### ✨ Custom Title for Table Filter
Customize the Table Filter button text using the new `title` attribute.
### ✨ Table Repeat Dimension Values
Tables and dimensions now support a `repeat_values` attribute that forces dimension values to display on every row instead of being collapsed.
### 🚀 Improved code editor font
The code editor now uses Geist Mono, a modern monospace font designed for better readability and aesthetics.
### ✨ Custom AI Instructions
Configure custom instructions for the AI assistant in Settings > AI Agent.
### ✨ RDS PostgreSQL Connector
Connect your RDS PostgreSQL database to Evidence and sync your data automatically.
[View Documentation](https://docs.evidence.studio/data-sources/rds-postgres)
### 🚀 PostgreSQL TLS Requirement Documentation
Added documentation note for PostgreSQL and Azure PostgreSQL connectors specifying that TLS/SSL must be enabled on the database for secure connections.
### ✨ Collapsible Tables
Tables with subtotals can now be collapsed. Click subtotal rows to expand or collapse their children.
[View Documentation](https://docs.evidence.studio/components/table)
### 🐛 Fixed row link chevron styling for total and subtotal rows
Fixed chevron column styling in tables with row links to match total/subtotal row backgrounds.
### ✨ Total and Subtotal Position
Control where totals and subtotals appear with `total_position` and `subtotal_position`. Set to "top" or "bottom".
[View Documentation](https://docs.evidence.studio/components/table)
### 🚀 Table Filter Initial Values and Required Selections
Table filters now support `initial_values` to set default filter values when the page loads, and `require_selection` to prevent specific filters from being cleared.
### 🚀 Automatic Unit Formatting for Numbers
BigValue, Value, and Table components now auto-format large numbers with compact units (e.g., $1.2M instead of $1,234,567)
### ✨ Text Size Option for Big Value
The `big_value` component now supports a `text_size` attribute with predefined options (`sm`, `base`, `lg`, `xl`, `2xl`, `3xl`, `4xl`, `5xl`) for reliable text sizing.
### 🚀 Clear Table Sorting with Third Click
Click a column header a third time to clear sorting and return to the original order.
[View Documentation](https://docs.evidence.studio/components/table)
### ✨ Azure SQL Database Connector
Sync data from Azure SQL Database directly into Evidence.
[View Documentation](https://docs.evidence.studio/data-sources/azure-sql)
### ✨ Logo Attribute for Table Dimensions
Display company logos in table dimension columns. The new `logo` attribute accepts a column containing domains to look up logos, and `logo_options` lets you customize size, grayscale mode, and label visibility.
[View Documentation](https://docs.evidence.studio/components/dimension)
### ✨ PDF Export for Viewers
Viewers can now download published pages as PDFs using the page menu or the keyboard shortcut (Cmd/Ctrl+P).
### ✨ Twilio Connector
Connect your Twilio data to Evidence. Sync calls, messages, accounts, and usage records.
[View Documentation](https://docs.evidence.studio/data-sources/twilio)
### 🚀 BigQuery 1 Minute Incremental Syncs
BigQuery data connector now supports 1 minute incremental syncs for faster data freshness.
[View Documentation](https://docs.evidence.studio/data-sources/bigquery)
### ✨ Column Groups in Tables
Group related columns under shared headers using the new `column_group` attribute on measures and dimensions. Useful for organizing metrics by category, such as revenue metrics vs volume metrics.
### 🐛 Dark Mode Empty Circle Markers Fix
Fixed emptyCircle markers in charts to properly use the background color in dark mode instead of white.
### ✨ Databricks Data Connector
Sync data from Databricks directly into Evidence.
[View Documentation](https://docs.evidence.studio/data-sources/databricks)
### ✨ Google Ads & Facebook Ads Connectors
Connect your Google Ads and Facebook Ads data to Evidence. Sync campaigns, ad groups, ads, and performance metrics to build marketing analytics dashboards.
[View Documentation](https://docs.evidence.studio/data-sources/google-ads)
### 🐛 Horizontal Bar Chart Sorting Fix
Horizontal bar charts now default to sorting by value descending, showing the largest values at the top instead of the bottom.
### ✨ Logo Component
New logo component to display company logos using logo.dev. Supports light/dark theme switching, configurable sizes, and grayscale mode.
### ✨ MySQL Data Connector
Sync data from MySQL directly into Evidence.
[View Documentation](https://docs.evidence.studio/data-sources/mysql)
### ✨ PostHog Connector
Connect your PostHog product analytics data to Evidence. Sync events, persons, cohorts, feature flags, insights, and more from your PostHog account.
[View Documentation](https://docs.evidence.studio/data-sources/posthog)
### 🚀 Snowflake 1 Minute Incremental Syncs
Snowflake data connector now supports 1 minute incremental syncs for faster data freshness.
[View Documentation](https://docs.evidence.studio/data-sources/snowflake)
### ✨ SQL Server Data Connector
Sync data from SQL Server directly into Evidence.
[View Documentation](https://docs.evidence.studio/data-sources/sqlserver)
### ✨ Dimension Grid
New `dimension_grid` component for interactive multi-dimensional filtering.
### 🐛 Fix for frozen columns row shading
Frozen columns in tables now display the correct alternating row shading when `row_shading=true` is enabled. Previously, frozen columns would not show the shading because they had a solid background that overrode the row-level shading.
### ✨ Series colors for pie charts
Map specific category values to specific colors in pie charts using the `series_colors` option in `chart_options`. This ensures consistent, meaningful coloring regardless of which categories are present in the data.
### 🐛 Export Data Retains Filters
Table exports now correctly include filtered and sorted data, matching the visual display on screen.
### 🐛 PDF Export Now Retains Filters
When downloading a PDF, any selected filter values are now preserved in the exported PDF.
### 🚀 Adjusted Developer Role Privileges
Previously, developers and admins could manage users, groups and customers. This is now restricted to Admins only.
### ✨ Motherduck Connector Schema Support
You can now use schema with the Motherduck connector
### 🐛 Dropdown Component Now Supports 'where' Attribute
The `dropdown` component now supports the `where` attribute for filtering dropdown options with custom SQL WHERE conditions, bringing it to feature parity with other filter components like `button_group` and `input_tabs`.
### 🐛 Horizontal Bar Chart X-Axis Formatting
Fixed issue where the `x_fmt` parameter was not being applied to axis labels in horizontal bar charts. Formatting now works consistently for both axis labels and tooltips.
### ✨ Add your organization logo
Add your organization's logo in settings
### ✨ Github Data Connector
Sync data about your Github repos directly into Evidence.
### ✨ Deltalake (S3) Connector
Connect using your S3 with Delta Lake format your data remains at rest in your S3 bucket.
### ✨ Smooth Line Option
New `smooth` attribute inside line options lets you create a line with rounded corners

[View Documentation](https://docs.evidence.studio/components/line_chart#param-line-options)
### ✨ Chart `height` attribute
Control the height of your charts using the `height` attribute
[View Documentation](https://docs.evidence.studio/components/area_chart#param-height)
### ✨ Customer Groups
Create customers, and invite customer users to view reports that you choose.

[View Documentation](https://docs.evidence.studio/features/page-level-access-control#customers)
### ✨ Groups
Add team members to groups to simplify permissions on projects and pages
[View Documentation](https://docs.evidence.studio/features/page-level-access-control#groups)
### 🚀 Improved Excel Export
Excel exports now use component titles to create tab names, and exclude logic and filter components
### ✨ User Variables
Access the user's name, email and organization using variables in markdown.
[View Documentation](http://docs.evidence.studio/core-concepts/variables#built-in-variables)
### ✨ Themes
Set color themes at the organization, project, and page level - including background, chart, and card colors
Access theme settings in page settings, project settings, or org settings. You can override theme colors at each level (e.g., project can override org theme, page overrides project and org themes)

[View Documentation](https://docs.evidence.studio/core-concepts/themes)
### 🚀 Improved Translation Validation Errors
Incorrect structures for translation maps will provide useful errors
### 🚀 Translations Editor
Modify translations with a fully featured text editor
### 🚀 Improved bucket docs
Adds more information about using bucket connectors
[View Documentation](https://docs.evidence.studio/data-sources)
### ✨ Translation Management
Define variables with different translations for multi-language apps.

[View Documentation](https://docs.evidence.studio/core-concepts/translations)
### ✨ Standalone Horizontal Bar Chart Component
New dedicated `horizontal_bar_chart` component makes it easier to create horizontal bar charts
We recommend migrating any existing horizontal bar charts to this new component
[View Documentation](https://docs.evidence.studio/components/horizontal_bar_chart)
### ✨ Display control for total and subtotals in table
Choose which totals or subtotals to display in your table
[View Documentation](https://docs.evidence.studio/components/table#param-show-subtotal-rows)
### ✨ Dark Mode Chart Colors
Configure colors for both light and dark mode in your project and org settings
### ✨ Input tabs full\_width and align attributes
Input tabs now allows the same styling configuration as the Tabs component, including full width and right align
[View Documentation](https://docs.evidence.studio/components/input_tabs#param-full-width)
### ✨ Conditional Formatting
Apply conditional logic to choose colors for visualizations

### ✨ Series Color Mapping
Option to select specific colors for series in your charts

[View Documentation](https://docs.evidence.studio/components/bar_chart#bar-chart-with-series-colors)
### 🚀 Assign access to pending users
You can now grant project and page access to users who have not yet accepted invitations to join the Evidence organization.
### 🚀 Control order of series in combo chart
Combo chart now displays your series in the order you define them in your markdown
### ✨ Draft Diff Viewer
Review your changes using the diff viewer before you publish

### 🚀 Icons in Autocomplete
Find components more easily in component autocomplete menus using the mini-icons

### 🚀 Smoother chart loads on input changes
Improved chart loading behaviour and animation when changing inputs on your page
### 🐛 Fix for table pivoting issues
Fixed issue where tables were not pivoting in certain situations
### ✨ `fmt` property for input options
Use dynamic formats in viz components when creating an input to select a metric - e.g., show 'usd' for sales or 'pct1' for growth
[View Documentation](https://docs.evidence.studio/components/dropdown#fmt)
### ✨ Variable `label` property
You can now reference the `label` property of a variable - useful when adding labels to viz components based on input selection
[View Documentation](https://docs.evidence.studio/components/dropdown#label)
### 🐛 Fix for custom date range end dates
Fixes issue where custom end date defined in SQL was not taking effect
### 🐛 Fix for scale\_column
Fixes issue where scale\_column in the measure component was not properly assigning colors
### 🚀 Improved handling of date grains in charts
Automatically handles formatting and positioning of labels on x-axis for date grains including month of year and day of week
### ✨ Table of Contents
A generated table of contents from the headings in your report. Enable from page settings.

### ✨ Top padding option for charts
Top padding override option to allow more room for data labels - helps in cases where labels are cut off
### ✨ x\_sort attribute
Choose a specific sort order for your x-axis, including specifying explicit strings
### 🐛 Histogram support for inline queries
Fix for Histogram issue where it could not accept inline queries
### 🚀 Toggle `invert` attribute
Invert attribute added to make toggled state = `false` instead of `true`
### ✨ Slider Input
New slider input component to filter on numeric values

[View Documentation](https://docs.evidence.studio/components/slider)
### ✨ Query timing metadata
Queries in the SQL Console, and the pop out component inspector at the bottom of the editor now display how long the query took to run in the Evidence query engine
### ✨ Zoomable charts
Adds a new "zoom" chart option to enable zooming into the data
### ✨ Toggle input
New toggle input component which sets a boolean variable you can use in queries and components
[View Documentation](https://docs.evidence.studio/components/toggle)
### ✨ Button group and input tabs
New input components as visual alternatives to dropdowns: `button_group` and `input_tabs`
Note that this update also deprecates the `dropdown_option` component in favour of the more general `option` component. The `option` component can be used inside `dropdown`, `button_group`, or `input_tabs`
[View Documentation](https://docs.evidence.studio/components/button_group)
### 🚀 Info Links
Add links to info text popovers using info\_link and info\_link\_title atttributes.
### 🚀 User Management Performance
Adding and removing users from reports is now faster
### 🐛 Fix for custom pivot formatting
Formatting for pivots now works as expected for custom date formats - e.g., `fmt="yyyy-mm"`
### ✨ Select all in dropdown
New button to select all options in a dropdown
### ✨ Text input component
Input component accepting free text input
[View Documentation](https://docs.evidence.studio/components/text_input)
### ✨ Feature Requests
Submit and track feature requests directly in your settings menu
From Settings > Feature Requests, you can create requests or bug reports, and set their priority. This integrates directly with the Evidence team's roadmap, with status changes synced into your view
### ✨ Stacked bar series in combo charts
Bar series in combo charts can now be stacked using the new stack\_id attribute. Bars with the same stack\_id will be stacked together, allowing for flexible combinations of stacked and grouped bars.
[View Documentation](https://docs.evidence.studio/components/bar)
### ✨ Max label length for x-axis labels
Truncate labels after a certain number of characters using the `max_label_length` attribute inside `x_axis_options`
### ✨ Rotate x-axis labels
Use the new `label_rotate` option in `x_axis_options` to rotate the labels on your x-axis
[View Documentation](https://docs.evidence.studio/components/line_chart#param-x-axis-options)
### 🚀 Sidebar Icons and Sorting
Add custom icons and adjust the sort order of projects and pages in the sidebar
### ✨ Jump to Code
In the editor preview, Cmd/Ctrl + click on a component to jump to the code for that component
You can jump to code by Cmd/Ctrl + clicking a component in the preview pane, or you can jump to the component preview by Cmd/Ctrl + clicking the code in your editor
### 🐛 Fixes for table pivoting
Fixed issue where columns were not properly pivoting in tables
### 🚀 Drag and drop image support
Drag, or paste images into the editor to add them to your page.
### ✨ Models (Beta)
Join sources together and materialize the results to improve performance
Models can be used to execute joins across sources, centralize type casting, and create clean tables to use when building reports. Models are run and materialized every 8 hours
[View Documentation](https://docs.evidence.studio/core-concepts/models)
### ✨ Set custom end date for date ranges
Use a dynamic end date for date ranges based on your data or a standard offset
By default, date ranges end as of today's date, but this setting allows you to choose a date based on a standard offset (e.g., 1 day ago) or by passing a sql query to calculate the date (e.g., `select max(date) from my_table`)
### ✨ Bar chart opacity setting
Customize the opacity of bars in bar chart and combo chart components
### 🚀 Project Sections
Organize projects into sections for easier navigation during development
Sections will not impact how projects are arranged in the app published to Viewer users
### 🐛 Version control overflow
Fixes a bug where if you changed lots of files it overflowed the Version History panel
### ✨ Option to choose first day of week
In project settings, you can now choose whether weeks start on Sunday or Monday
### 🚀 Better SQL Autocomplete Suggestions
Improved SQL suggestions for columns, and tables after joins
### 🚀 Variable name shortcuts + use in markdown
Variables no longer require specifying a property - simply use the name, like `{{ my_var }}`
You can also use variables directly in markdown, including in headers and lists. You still have access to variable properties and can reference them like this: `{{ my_var.selected }}`
### 🚀 Performance improvement for table comparisons
Tables containing comparisons should now load much faster
### 🚀 More source sync info
View the number of rows in a source, and the amount of time it took for the source sync from the Sources page.
### ✨ Use variables inside components
You can now reference filter variables directly in component attributes
Supports the following attributes: title, subtitle, info, where, date\_grain, date\_range.range, comparison.compare\_vs
### ✨ Icon support for dropdowns
Include an icon in your dropdown using the icon option
### ✨ Selector components for date grain and comparisons
Special components for selecting date grain and comparisons
### 🚀 Dynamic date ranges
Input arbitrary ranges into the date\_range attribute in components, like "last 14 weeks" or "2023-01-14 to 2025-11-30"
### 🐛 Filter scroll fix
Fixed a bug where selecting a filter caused the page to jump back to the top.
### ✨ Select preset ranges in range calendar
Choose which preset ranges you want your users to see when clicking the range calendar component
### 🐛 SQL comments in inline queries
You can now add comments to inline queries without breaking them
### ✨ Option to turn legend off in charts
You can now turn off chart legends with legend=false
### 🚀 Conditional component render instantly
When previewing or viewing published pages, the initial state of any if/else\_if/else conditions will be pre-calculated before the page loads.
### 🚀 Better label spacing on x-axis
Improvement to the alignment and spacing of labels on the x-axis
### 🐛 Fix target comparison totals in table
Fixed an issue where target comparisons were hidden in total rows
### 🐛 Improved date behaviour
Previously, database columns that returned Date type would return DateTime precision, which is confusing in the UI. Now dates will return no additional time component
Values that are Date type will no longer display time component in Tables, Values, and in various input components. Eg a Date previously formatted 2025-09-22T14:05:23Z would now be returned as 2025-09-22.
### 🐛 Fix Explore table resize and scroll
Fixes an issue where tables on the Explore page would resize and cut off content
### 🚀 Comparison Tooltip Improvements
Fixed issue with percentage calculations for negative values. Added support for custom formats.
### ✨ Make Feature Requests in AI Chat
Now you can ask the Evidence chat to submit a feature request to the Evidence team
### 🐛 Fixed unexpected date offsets
In certain timezones, dates were being transposed by a small number of seconds in Chrome and Safari. This could cause date formats to render incorrectly, for example showing the day before the expected date.
### 🚀 RLS Enhancements
Added variable support for IN/NOT IN operators, 'Apply All' rule option, new panel interface, and per-user variable editing capabilities.
### 🚀 Improved Inline SQL Editor
See available variables, inline queries, and a preview of compiled SQL when editing queries in the inline SQL editor
### 🚀 Improved international character support in SQL queries
You can now include Japanese, Chinese, emoji, and other non-Latin characters directly in SQL passed to components
### ✨ Page Loading (table)
Tables now load instantly on preview and published pages
This is the first change in a journey to fully enable Server-Side Rendering in Evidence pages. The table is the first component to support this behavior, which enables the following features: - Tables load instantly on preview and published pages (no more loading spinner when the page loads) - Chat can now debug SQL query errors in Table components
This change lays the groundwork for other components to opt into this new Server-Side Rendering system.
### ✨ Add optional dark\_url prop to image component
Image components can now display different images in light and dark modes using the new dark\_url prop.
### ✨ Themes
Define a custom color palette to apply to all charts in a project
### 🚀 Improved Default Funnel Chart Styling
Funnel Charts are more intuitive to read, with a squared off style
[View Documentation](https://docs.evidence.studio/components/funnel_chart)
### 🐛 Fix Comparison Issues
Fixed bug for target comparisons which resulted in undefined error
### ✨ Inline SQL Editor
A new SQL editor for running and modifying inline queries on your page
### ✨ Icon Component
Add icons inline into markdown, with configuration for color and size
[View Documentation](https://docs.evidence.studio/components/icon)
### ✨ Row Level Security
Add rules to restrict which rows of are visible to users from sources
Add RLS rules to data source columns, and add user variables to determine which values in these columns allow access.
[View Documentation](https://docs.evidence.studio/features/access-rules)
### 🚀 Custom Color Palettes
All charts now support custom color palettes via the "chart\_options" attribute
Pass an array of hex codes to the color\_palette option e.g. `color_palette=["#ff0000","#00ff00"]`
[View Documentation](https://docs.evidence.studio/components/pie_chart#with-custom-colors)
### 🐛 Fix Editor Overwriting Bug
Fixed bug where switching pages and then hitting Ctrl+Z would overwrite your page with the content of the previous page.
### 🚀 Sidebar Hover Text
Adds hover text to sidebar items that are truncated due to length
### 🐛 Table Filter Option Overflow
Fixed a bug where long string values in the table filter overlapped each other
### 🚀 Charting Library Upgrade
Upgraded to ECharts 6, fixed some issues where labels got cut off
### 🐛 Expose SQL Errors
Exposes some SQL errors that were not being shown
### 🐛 Fix High Precision Decimals in Postgres
Resolves issue where tables containing decimal columns with more that 9 digits of precision were failing to publish
### 🚀 Editor Loading Speed
We've significantly improved the load speeds when switching between pages in the editor.
### ✨ Link Button
Use the link button to link to another page in Evidence or an external location
[View Documentation](https://docs.evidence.studio/components/link_button)
### ✨ Print Format Components
Add page breaks, print groups, and hide elements from PDF downloads
### ✨ PDF Download
Download your page as a PDF
### 🐛 If / Else Behaviour Fix
Fixed some issues with the if /else components which sometimes caused them to not display information when they should
### ✨ Accordian components
Organize content into collapsible accordian sections
### ✨ Axis Label Interval Control
More control over the intervals between labels on charts
### 🐛 Long Page Name Overflow
Long page and directory names now truncate in the sidebar to prevent the action button being hidden
### ✨ Range Calendar Input
New range calendar component for date filtering.
### ✨ Tabs
New Tabs, and Tab components for tabbed layouts.
### ✨ Variables
Define variables in frontmatter and use them in markdown, SQL and components
[View Documentation](https://docs.evidence.studio/core-concepts/variables)
### ✨ Column-level control for tables
Control formatting for each column in a table
### ✨ Conditional formatting in tables
Use color scale to conditionallyformat values in a table
### ✨ Image support in tables
Add images to columns in a table
### 🚀 Improved Explore page
Supports more date grain options and improved share experience
### 🚀 Improved pivot table
Table now supports more complex pivot table scenarios
### ✨ Link support in tables
Add links to columns in a table, or set up row links
### 🚀 New date grain options
Inclues special grains like 'day of week' and 'month of year', with built-in labels
### ✨ New table visualizations
Add bar charts, sparklines, and deltas to your columns
### ✨ Period over period comparisons
Automatically compare values vs. prior year, prior period, or target. Available in table and big value.
### 🐛 Delete Connections Fix
Fixed a bug which only allowed you to delete the most recently added connection
### ✨ Hubspot Connector
Import data from Hubspot directly into Evidence
[View Documentation](https://docs.evidence.studio/data-sources/hubspot)
### ✨ Modals
New modal component that can contain content in a dialogue or drawer.
[View Documentation](https://docs.evidence.studio/components/modal)
### ✨ Motherduck Connector
Add data sources from your Motherduck DB
[View Documentation](https://docs.evidence.studio/data-sources/motherduck)
### ✨ Page linking
Link to other Evidence pages using markdown links []() with Intellisense support
[View Documentation](https://docs.evidence.studio/components/link)
### 🐛 Respect columns option in table filter
Fix bug which ignored columns selection in table filter
### 🐛 Table filter responsiveness
Fix bug which prevented table filter inputs from taking effect immediately after adding the table filter to the page.
### ✨ Filter interpolation
Reference filter values inside of inlined queries, and view the state of your filters in the new filters pane of the devtools sidebar.
[View Documentation](https://docs.evidence.studio/core-concepts/markdown#filters)
### 🚀 Agent Keyboard Shortcut
Ctrl+Alt+I (Mac: Cmd+Shift+I) to open a chat with the Evidence agent from anywhere in the Editor
### ✨ If, Else If, Else
Use conditional blocks to choose what to render based on data.
[View Documentation](https://docs.evidence.studio/components/if)
### ✨ Reference Components
Use reference\_line, reference\_area, and reference\_point to add reference annotations to your charts
[View Documentation](https://docs.evidence.studio/components/reference_line)
### 🚀 Postgres Schema Support
Use tables in any Postgres schema (not just the default "public" schema)
### ✨ Import Views as Sources
All supported DBs now allow importing views as sources
### 🚀 Public Documentation
We've published full documentation at [https://docs.evidence.studio](https://docs.evidence.studio)
### ✨ Card Option for Row and Stack Components
Added card option to row and stack components to display their contents as a single card.
### ✨ Data Point Labels
Label each data point in your chart with the data\_labels option
### ✨ Downloadable Data
Right click any chart to download its data, or use the kebab menu in the top left of the published page to download a whole page's data.
### ✨ Chart, Axis, and Series Options
New chart\_options, x\_axis\_options, y\_axis\_options, y2\_axis\_options, and series options for customizing your charts.
### ✨ Partials
Define sections of markdown for re-use across pages.
### ✨ Polar Chart
Added a new polar chart component.
### ✨ Table Search
Search bar for the Table component.
### 🐛 Inline Query Date Validation
Fixes issue creating visualizations using inline queries with dates
### ✨ Histogram
Added a new histogram chart component.
### ✨ Markdown Comments
Adds support for mardown comments with \. Mac: Cmd + / Windows: Ctrl + /
### ✨ Calendar Heatmap
Added a new calendar heatmap chart.
### ✨ Combo Chart
Added a combo\_chart component that allows you to combine area, bar, bubble, line, and scatter series on one chart.
### ✨ Accept and Reject Changes Panel in Diff View
Added accept and reject buttons to the top of the diff view.
### 🚀 Connection Documentation
Added generaldocumentation for data connections.
### 🐛 Fix to give AI agent knowledge of inline queries
Fixed the issue where the AI agent did not know about inline queries on your page.
### 🐛 Fix to Maintain Chart Height
Fixed the issue where the chart height was shrinking when title and legend were added.
### ✨ Heatmap Chart
Added a new heatmap chart component.
### 🚀 Link to All Docs in Sidepane
Added a link to all docs in the docs tab of the editor.
### ✨ Custom X and Y Chart Titles
Added the ability to customize x\_title and y\_title for charts.
### ✨ Funnel Chart
Added a new funnel chart component.
### ✨ Sankey Chart
Added a new sankey chart component.
### ✨ Changelog
We're shipping features and fixes very quickly. Keep an eye out here for updates.
### 🐛 Fix Slash Commands When Inside Parent Component
Fixed the issue where slash commands were not working when inside a parent component.
### 🚀 Helpful Warning for Aggregating Columns
Added a warning to consider aggregating a column for a chart.
### ✨ Open Chat Automatically for Fix in Chat
When the fix in chat button is pressed, the chat window will open automatically.
### ✨ Pie and Donut Charts
Added a new pie chart component.
### 🚀 Collapse the Sidebar
Added the ability to collapse and expand the sidebar on all screen sizes.
### 🚀 Faster Sources Page
Significantly improved loading performance on the sources page.
### 🚀 Fix in Chat Now Available on All Error Messages
Error messages throughout the platform now include the fix in chat feature.
### 🚀 More Readable SQL Errors
SQL error messages have been redesigned to be clearer and more actionable.
### 🐛 Row and Stack Components
Fixed issues with Row and Stack components rendering and layout behavior.
### ✨ European Number Formatting
Support for European number format using comma as the decimal separator (e.g., 1.234,56 instead of 1,234.56).
### ✨ Azure Postgres Connector
Connect your Azure Database for PostgreSQL to Evidence and sync your data automatically.
[View Documentation](https://docs.evidence.studio/data-sources/azure-postgres)
### ✨ SQL Files
Create reusable SQL queries as standalone files. SQL files can be referenced from components using `data="path/to/query"` and from inline queries using `{{path/to/query}}` syntax.
# Commands
Source: https://docs.evidence.studio/cli/commands
Reference for all Evidence CLI commands.
## Development
### `evidence init`
Scaffold a new Evidence project.
```bash theme={null}
evidence init my-project
evidence init my-project --warehouse snowflake
```
| Option | Description |
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `--warehouse` | Scaffold a `connection.yaml` for a direct warehouse connection: `snowflake` or `bigquery`. See [Connecting a Warehouse](/cli/connections). |
Without `--warehouse`, the project uses the managed Evidence Warehouse. With it, the CLI writes a `connection.yaml` (gitignored) so queries run directly against your own warehouse.
### `evidence dev`
Start the local development server.
```bash theme={null}
evidence dev
evidence dev --port 8080
```
| Option | Description |
| -------------- | ------------------------------ |
| `--port`, `-p` | Port to run on (default: 3000) |
## Deploy
### `evidence launch`
Connect this project to Evidence Studio and GitHub, then deploy by pushing to your repo. Interactive by default — it walks you through installing the GitHub App and creating (or linking) the Studio project.
```bash theme={null}
evidence launch
evidence launch --name "My Project" --upload-credentials
```
| Option | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name` | Name for the Studio project to create. |
| `--branch` | Branch to publish from (default: auto-detected). |
| `--root-directory` | Project root within the repo (default: auto-detected). |
| `--upload-credentials` | Upload warehouse credentials from [`connection.yaml`](/cli/connections) to your org. Prompted for interactively; required to opt in when running non-interactively. |
`evidence launch` recognizes GitHub.com and GitHub Enterprise Cloud (`*.ghe.com`) remotes over HTTPS and SSH. If the detected GHE.com host is not connected yet, the CLI opens Organization Settings to guide an Evidence admin through creating and installing the private Enterprise GitHub App. GHE.com connections require an Enterprise plan.
### `evidence link`
Attach this repo to an **existing** Studio project. The project's content becomes git-managed — the next `git push` overwrites it with the repo's contents.
```bash theme={null}
evidence link my-project
evidence link --project my-project
```
| Option | Description |
| ------------------ | -------------------------------------------------------------------------------- |
| `--project` | Studio project to attach, by slug or id. Also accepted as a positional argument. |
| `--branch` | Branch to publish from (default: auto-detected). |
| `--root-directory` | Project root within the repo (default: auto-detected). |
The repository host must match the GitHub host connected to the Evidence organization.
### `evidence unlink`
Disconnect this repo from its Studio project. The org's GitHub App install and the project itself are left intact.
```bash theme={null}
evidence unlink
evidence unlink --project my-project
```
| Option | Description |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `--project` | Studio project to unlink, by slug or id. Inferred from the repo's binding when omitted. Also accepted as a positional argument. |
## Data
### `evidence query`
Run a SQL query against connected data sources.
```bash theme={null}
evidence query "SELECT * FROM orders LIMIT 10"
evidence query --file query.sql
cat query.sql | evidence query -
```
| Option | Description |
| ---------------- | -------------------------------------------------------- |
| `--format` | Output format: `json` (default), `jsonl`, `table`, `csv` |
| `--limit`, `-l` | Limit number of rows |
| `--quiet`, `-q` | Suppress status messages |
| `--columns` | Output only column names and types |
| `--file` | Read SQL from a file |
| `--output`, `-o` | Write results to a file |
### `evidence tables`
List available data tables.
```bash theme={null}
evidence tables
```
### `evidence describe`
Show schema for a table.
```bash theme={null}
evidence describe demo_daily_orders
```
### `evidence schema`
Show all tables with their columns.
```bash theme={null}
evidence schema
```
### `evidence connectors`
List all connectors with health status.
```bash theme={null}
evidence connectors
evidence connectors --json
```
Shows connector name, type, status, last sync, schedule, table count, and reference count for all connector types.
### `evidence models`
List all models with refresh status.
```bash theme={null}
evidence models
evidence models --json
```
Shows model name, status, last refresh time, and schedule.
### `evidence lineage`
Show where connections and tables are used across projects, pages, models, and queries.
```bash theme={null}
evidence lineage
evidence lineage table orders
evidence lineage --branch dev/alex
evidence lineage --json
```
| Option | Description |
| -------------- | ----------------------------------------- |
| `table ` | Show where a specific table is referenced |
| `--branch` | Query a specific branch (default: main) |
| `--json` | Output JSON for tooling |
## Project
### `evidence validate`
Validate all markdown files in the current project.
```bash theme={null}
evidence validate
evidence validate --json
```
### `evidence docs`
Browse and search component documentation.
```bash theme={null}
evidence docs # Overview
evidence docs search "chart" # Search docs
evidence docs component bar_chart # Component details
```
## Authentication
### `evidence signup`
Create an account and workspace. Opens Evidence in your browser; once done, run `evidence login` to connect the CLI.
```bash theme={null}
evidence signup
```
### `evidence login`
Authenticate with Evidence Studio using your browser.
```bash theme={null}
evidence login
```
### `evidence logout`
Clear stored credentials.
```bash theme={null}
evidence logout
```
### `evidence whoami`
Show the currently authenticated user.
```bash theme={null}
evidence whoami
```
### `evidence orgs`
List available organizations.
```bash theme={null}
evidence orgs
```
### `evidence switch`
Switch to a different organization.
```bash theme={null}
evidence switch "My Organization"
```
### `evidence token`
Generate a token for headless/CI use. Prints an `EVIDENCE_AUTH_TOKEN` value you can set as an environment variable to authenticate without an interactive login. Requires an active login and a selected organization.
```bash theme={null}
evidence token
```
The generated token contains a long-lived access token. Treat it as a secret.
## Utility
### `evidence version`
Print the current CLI version.
```bash theme={null}
evidence version
```
### `evidence upgrade`
Upgrade to the latest CLI version.
```bash theme={null}
evidence upgrade
```
### `evidence help`
Show help and available commands.
```bash theme={null}
evidence help
```
## Self-hosting
### `evidence serve`
Serve the project as a self-hosted site. Runs the built-in production server — no Evidence Studio account or session required.
```bash theme={null}
evidence serve
evidence serve --port 8080
evidence serve --host 0.0.0.0
```
| Option | Description |
| -------------- | ---------------------------------------------- |
| `--port`, `-p` | Port to run on (default: 3000) |
| `--host` | Bind address (default: `127.0.0.1`) |
| `--open` | Open the browser after starting (default: off) |
Requires a direct connector configured in [`connection.yaml`](/cli/connections) — the managed query engine is not supported for self-hosting.
To serve beyond localhost, set `EVIDENCE_BASIC_USER` and `EVIDENCE_BASIC_PASSWORD` to protect the site with HTTP Basic Auth. The server refuses to start on a non-localhost `--host` without these set.
On a trusted private network (VPN, Tailscale, internal VPC), `EVIDENCE_AUTH_DISABLED=true` skips authentication entirely.
# Connect your CLI to your data
Source: https://docs.evidence.studio/cli/connections
Connect the Evidence CLI to the Evidence Warehouse or to a warehouse you own.
How the CLI gets data depends on how your project is set up.
## Evidence Warehouse
If you use the [Evidence Warehouse](/data-sources), run `evidence login`. No further setup is needed.
## Other warehouses
If you use a [direct connection](/data-sources#direct-connectors) to a warehouse you own, add a `connection.yaml` file to the root of your project. When this file is present, the CLI queries your warehouse **directly from your machine** — no login required.
### Scaffold with `evidence init`
The quickest way to create a `connection.yaml` is to pass `--warehouse` to `evidence init`:
```bash theme={null}
evidence init my-project --warehouse snowflake
# or
evidence init my-project --warehouse bigquery
```
This writes a `connection.yaml` in the project root pre-filled with placeholder values, and adds it to `.gitignore` (the file holds credentials — keep it out of version control).
`connection.yaml` and any files it references — the Snowflake private-key `.pem` or the BigQuery service-account JSON — contain credentials. Never commit them. `evidence init --warehouse` gitignores `connection.yaml` for you, but **not** the referenced key files: add those to `.gitignore` yourself, or use the inline `private_key` / `keyfile_json` fields so there's no separate file to leak.
Fill in the placeholders with your own connection details. If `--warehouse` is omitted, no `connection.yaml` is written and the project uses the Evidence Warehouse.
### Configuration
```yaml theme={null}
type: snowflake
account: xy12345.us-east-1
user: evidence_user
private_key_path: ./snowflake-key.pem
warehouse: COMPUTE_WH
database: ANALYTICS
# role: EVIDENCE_READER
# schema: { production: ANALYTICS, devSchemas: [DEV_ALICE] }
```
Provide exactly one of `password`, `private_key`, or `private_key_path`. Paths (`private_key_path`) are resolved relative to `connection.yaml`.
See the [Snowflake direct connector](/direct-connectors/snowflake) for the full field reference and how to create a read-only Snowflake user.
```yaml theme={null}
type: bigquery
project: my-gcp-project
keyfile: ./evidence-bq-primary.json
datasets:
- analytics
- reporting
# dataset: analytics
# location: US
```
Provide exactly one of `keyfile` or `keyfile_json`. The `keyfile` path is resolved relative to `connection.yaml`.
See the [BigQuery direct connector](/direct-connectors/bigquery) for the full field reference and the service-account setup steps.
# CLI
Source: https://docs.evidence.studio/cli/index
Develop Evidence Studio projects locally or with the agent of your choice.
The Evidence CLI lets you run and develop Evidence projects locally from the command line.
It includes a development server for previewing your reports locally as you work, commands for running queries, viewing metadata, and validating your code.
If you are going to use the CLI for development, you should set up the [GitHub Integration](../features/version-control#github-integration).
## Install
```bash theme={null}
curl -fsSL https://evidence.studio/install.sh | sh
```
Installs to `/usr/local/bin` (falls back to `~/.local/bin` if not writable).
```powershell theme={null}
irm https://evidence.studio/install.ps1 | iex
```
Installs to `%LOCALAPPDATA%\Evidence\bin` and adds it to your user PATH. Restart your terminal after install.
Both `evidence` and `evd` commands are available after install.
### Supported Platforms
* macOS arm64 (Apple Silicon)
* macOS x64 (Intel)
* Linux x64
* Linux arm64
* Windows x64
### Verify Installation
```bash theme={null}
evidence version
```
## Getting Started
1. **Create a project** in [Evidence Studio](https://evidence.studio) and connect it to a GitHub repo.
2. **Clone the repo** to your local machine.
3. **Log in** to your Evidence account via the CLI:
```bash theme={null}
evidence login
```
4. **Start developing** from inside your cloned project directory:
```bash theme={null}
evidence dev
```
5. Open a pull request on the repo. Evidence Studio will reply with a preview link. Merging the PR releases your changes.
## Upgrade
```bash theme={null}
evidence upgrade
```
The CLI checks for updates on startup. If a newer version is available, you'll see a warning. If your version is below the minimum supported version, the CLI will require an upgrade before running.
## Telemetry
The CLI reports anonymous usage — to opt out set EVIDENCE\_TELEMETRY\_DISABLED=1 or DO\_NOT\_TRACK=1
# Accordion
Source: https://docs.evidence.studio/components/accordion
An accordion component that organizes content into collapsible sections.
```liquid theme={null}
{% accordion %}
...
{% /accordion %}
```
## Attributes
Whether only one item can be open at a time
Visual style variant of the accordion
**Allowed values:**
* `default`
* `well`
* `card`
Set the width of this component (in percent) relative to the page width
## Allowed Children
* [accordion\_item](/components/accordion_item)
# Accordion Item
Source: https://docs.evidence.studio/components/accordion_item
An accordion item that can be expanded or collapsed.
```liquid theme={null}
{% accordion %}
{% accordion_item title="Section 1" open=true %}
Content for section 1.
{% /accordion_item %}
{% accordion_item title="Section 2" %}
Content for section 2.
{% /accordion_item %}
{% accordion_item title="Section 3" icon="settings" %}
Content for section 3 with an icon.
{% /accordion_item %}
{% /accordion %}
```
## Examples
### Accordion with Items
```liquid theme={null}
{% accordion %}
{% accordion_item title="Section 1" open=true %}
Content for section 1.
{% /accordion_item %}
{% accordion_item title="Section 2" %}
Content for section 2.
{% /accordion_item %}
{% accordion_item title="Section 3" icon="settings" %}
Content for section 3 with an icon.
{% /accordion_item %}
{% /accordion %}
```
## Attributes
Title displayed in the accordion item header. For rich titles (e.g. containing another component), nest an `accordion_title` tag instead. When both are provided, the nested `accordion_title` takes precedence and this attribute is ignored.
Icon to display in the accordion item header
**Allowed values:**
* `trending-up`
* `trending-down`
* `clock`
* `calendar`
* `check`
* `x`
* `info`
* `alert-circle`
* `help-circle`
* `eye`
* `eye-off`
* `user`
* `users`
* `settings`
* `cog`
* `plus`
* `minus`
* `up`
* `down`
* `right`
* `left`
* `star`
* `heart`
* `search`
* `file`
* `file-text`
* `home`
* `mail`
* `filter`
* `share`
* `bell`
* `trash`
* `credit-card`
* `globe`
* `key`
* `croissant`
* `map`
* `rotate`
* `rewind`
* `bank`
* `receipt`
* `activity`
* `chart-column`
* `chart-pie`
* `chart-no-axes-combined`
* `goal`
* `rocket`
* `trophy`
* `apple`
* `cookie`
* `donut`
* `beef`
* `cake`
* `soup`
* `utensils`
* `milk`
* `nut`
* `pyramid`
* `triangle`
* `arrow-down`
* `arrow-left`
* `arrow-right`
* `arrow-up`
* `chevron-down`
* `chevron-left`
* `chevron-right`
* `chevron-up`
* `chevrons-down`
* `chevrons-left`
* `chevrons-right`
* `chevrons-up`
* `menu`
* `external-link`
* `check-circle`
* `x-circle`
* `edit`
* `trash-2`
* `copy`
* `save`
* `download`
* `upload`
* `send`
* `refresh`
* `redo`
* `undo`
* `folder`
* `folder-open`
* `image`
* `file-image`
* `user-plus`
* `user-minus`
* `user-check`
* `lock`
* `unlock`
* `log-in`
* `log-out`
* `message-square`
* `message-circle`
* `phone`
* `phone-call`
* `bell-off`
* `video`
* `video-off`
* `play`
* `pause`
* `stop`
* `skip-back`
* `skip-forward`
* `volume`
* `volume-1`
* `volume-2`
* `volume-off`
* `volume-x`
* `bookmark`
* `tag`
* `link`
* `unlink`
* `share-2`
* `alert-triangle`
* `loader`
* `more-vertical`
* `more-horizontal`
* `grid`
* `list`
* `maximize`
* `minimize`
* `zoom-in`
* `zoom-out`
* `thumbs-up`
* `thumbs-down`
* `shopping-cart`
* `dollar-sign`
* `camera`
* `printer`
* `monitor`
* `smartphone`
* `laptop`
* `calculator`
* `cloud-sun-rain`
* `sun-snow`
* `thermometer-sun`
* `thermometer-snowflake`
* `cloudy`
* `cloud-rain-wind`
* `cloud-rain`
* `wind`
* `sun`
* `cloud-snow`
* `thermometer`
* `cloud-drizzle`
* `cloud-sun`
* `cloud`
* `cloud-lightning`
* `snowflake`
* `flame`
* `atom`
* `fuel`
* `magnet`
* `factory`
* `tree-deciduous`
* `waypoints`
* `plug`
* `dam`
* `battery`
Whether the accordion item is initially open
## Allowed Parents
* [accordion](/components/accordion)
# Accordion Title
Source: https://docs.evidence.studio/components/accordion_title
Rich title content for an accordion item. Use this instead of the `title` attribute when the title needs to contain other components (e.g. `big_value`).
## Examples
### Accordion item with a big\_value in the title
```liquid theme={null}
{% accordion %}
{% accordion_item %}
{% accordion_title padding_top=8 padding_bottom=8 %}
{% big_value data="orders" value="sum(sales)" fmt="usd" /%}
{% /accordion_title %}
Body content for this section.
{% /accordion_item %}
{% /accordion %}
```
## Attributes
Top padding of the accordion trigger, in pixels. Lower this when the slotted content already provides its own top padding.
Bottom padding of the accordion trigger, in pixels. Lower this when the slotted content already provides its own bottom padding.
## Allowed Parents
* [accordion\_item](/components/accordion_item)
# Area
Source: https://docs.evidence.studio/components/area
Add an area series to a [combo_chart](/components/combo_chart)
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% area y="sum(total_sales)" /%}
{% /combo_chart %}
```
## Examples
### Basic Area Series
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% area y="sum(total_sales)" /%}
{% /combo_chart %}
```
### Unstacked Areas
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% area y="sum(total_sales)" series="category" stacked=false /%}
{% /combo_chart %}
```
### Area with Gradient Fill
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% area y="sum(total_sales)" stacked=false options={
gradient=true
} /%}
{% /combo_chart %}
```
## Attributes
Column name for y-axis. Aggregated at the parent combo\_chart's `x=`. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
Column name for series grouping
The axis to render the series on
**Allowed values:**
* `y1`
* `y2`
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
**Example:**
```
options={
step = "start"
smooth = true
gradient = true
}
```
**Attributes:**
* step: `string` - Show a stepped line rather than a smooth line between points and control where the step happens (start, middle, or end)
* **Allowed values:**
* `start`
* `middle`
* `end`
* smooth: `boolean`
* gradient: `boolean` - Apply a color-to-transparent gradient fill to the area, fading from the series color at the top to transparent at the bottom
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into this series only. For overrides that apply to every series on the chart, set `echarts_series_options` on the parent chart instead.
**Example:**
```
echarts_options={
endLabel={ show=true }
markPoint={ data=[{ type="max" } { type="min" }] }
}
```
Whether to stack areas with the same series value. Set to "100%" for percentage stacking.
Stack identifier - areas with the same stack\_id value will be stacked together. Overrides the stacked prop.
## Allowed Parents
* [combo\_chart](/components/combo_chart)
# Area Chart
Source: https://docs.evidence.studio/components/area_chart
Display an area chart
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
date_grain="month"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
date_grain="month"
/%}
```
### Area Chart with Series
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
series="category"
date_grain="month"
/%}
```
### Area Chart with Formatting
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
title="Sales Over Time"
subtitle="Monthly sales performance"
date_grain="month"
/%}
```
### 100% Stacked Area Chart
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
series="category"
stacked="100%"
date_grain="month"
title="Sales Distribution by Category"
/%}
```
### Revenue by Day of Week
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of week"
title="Revenue by Day of Week"
subtitle="Weekday vs weekend sales patterns"
/%}
```
### Seasonality Analysis (Month of Year)
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="month of year"
title="Seasonality Analysis"
subtitle="Sales patterns across months"
/%}
```
### Quarterly Trends
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="quarter of year"
title="Quarterly Performance"
subtitle="Q1 through Q4 comparison"
/%}
```
### Monthly Billing Cycle Patterns
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of month"
title="Daily Revenue by Day of Month"
subtitle="Identify billing cycle patterns"
/%}
```
### Week Number Analysis
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="week of year"
title="Revenue by Week of Year"
subtitle="Weekly performance across the year"
/%}
```
### Day of Year Analysis
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of year"
title="Revenue by Day of Year"
subtitle="Identify patterns across 365 days"
/%}
```
### Area Chart with Gradient Fill
```liquid theme={null}
{% area_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="month"
stacked=false
area_options={
gradient=true
}
/%}
```
## Attributes
Name of the table to query. Required unless every child series uses `metric="..."` — metric children resolve their own base from the metric view.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
How to handle missing data points. "connect" auto-connects points (default), "gaps" shows visual breaks, "zero" fills with zeros.
**Allowed values:**
* `connect`
* `gaps`
* `zero`
Column name for x-axis. Required unless every child series uses `metric="..."` — metric children fall back to the metric view's time column.
Format for x values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y2 values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Column name for series grouping (applies to all series)
Column name for individual point labels displayed at the top of the tooltip
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Sort order for x-axis categories. Options: `asc` (alphabetical), `desc` (reverse alphabetical), `data` (preserve query order), or an array for custom order like `["A", "B", "C"]`
**Allowed values:**
* `asc`
* `desc`
* `data`
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the secondary y-axis
**Example:**
```
y2_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Show legend. Studio's built-in legend renders a compact color swatch + series name. For chart-wide style overrides that need the legend to reflect them precisely (line width, custom symbols, richer styling), set `legend=false` and provide `legend={ show=true ... }` inside `echarts_options` to use ECharts' native legend instead.
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Array of series names to define the order of series in the chart and legend. Series not in the array will appear after the ordered ones.
Studio-shaped chart styling shortcuts (palette, series colors, zoom, padding). For raw ECharts overrides, use `echarts_options` instead.
**Example:**
```
chart_options={
color_palette = ["#3b82f6", "#8b5cf6", "#ec4899"]
series_colors = {
"Series A" = "#3b82f6"
"Series B" = "#10b981"
"Series C" = "#f59e0b"
}
zoom = true
top_padding = 0
}
```
**Attributes:**
* color\_palette: `array of strings` - Array of hex color codes to use for series colors
* series\_colors: `map of key-value pairs` - Map of series names to hex color codes for custom series coloring
* zoom: `boolean` - Enables zoom by dragging on the chart area
* top\_padding: `number` - Additional padding (in px) above the chart area to prevent labels from being cut off
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `dataZoom`, `visualMap`, `graphic`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For per-series overrides, use `echarts_series_options` or the per-series `echarts_options` on a `line`/`bar`/etc. child.
**Example:**
```
echarts_options={
tooltip={ position="top" }
dataZoom=[{ type="slider" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into every data series in the chart. Use when the same override should apply to all series. Skips reference lines/areas/points. For a single series, set `echarts_options` on the series child instead.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
markLine={ data=[{ type="average" }] }
}
```
Column name for y-axis
Semantic metric name(s) to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes. Pass an array for multiple series (e.g. `metric=["revenue", "orders"]`).
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
**Example:**
```
options={
step = "start"
smooth = true
gradient = true
}
```
**Attributes:**
* step: `string` - Show a stepped line rather than a smooth line between points and control where the step happens (start, middle, or end)
* **Allowed values:**
* `start`
* `middle`
* `end`
* smooth: `boolean`
* gradient: `boolean` - Apply a color-to-transparent gradient fill to the area, fading from the series color at the top to transparent at the bottom
Whether to stack the areas. Set to "100%" for percentage stacking where each area shows its proportion of the total.
Column name for secondary y-axis
**Example:**
```
area_options={
step = "start"
smooth = true
gradient = true
}
```
**Attributes:**
* step: `string` - Show a stepped line rather than a smooth line between points and control where the step happens (start, middle, or end)
* **Allowed values:**
* `start`
* `middle`
* `end`
* smooth: `boolean`
* gradient: `boolean` - Apply a color-to-transparent gradient fill to the area, fading from the series color at the top to transparent at the bottom
## Allowed Children
* [reference\_line](/components/reference_line)
* [reference\_area](/components/reference_area)
* [reference\_point](/components/reference_point)
# Area Layer
Source: https://docs.evidence.studio/components/area_layer
Add a choropleth layer to a map
```liquid theme={null}
{% map %}
{% area_layer
geography="us_states"
match_by="name"
data="state_sales"
area_id="state"
value="sum(sales)"
/%}
{% /map %}
```
## Examples
### US States by Name
```liquid theme={null}
{% map %}
{% area_layer
geography="us_states"
match_by="name"
data="state_sales"
area_id="state"
value="sum(sales)"
/%}
{% /map %}
```
### US States by Abbreviation
```liquid theme={null}
{% map %}
{% area_layer
geography="us_states"
match_by="abbr"
data="state_sales"
area_id="state_abbr"
value="sum(sales)"
/%}
{% /map %}
```
### US Counties by State + County
```liquid theme={null}
{% map %}
{% area_layer
geography="us_counties"
match_by="state-county"
data="county_sales"
area_id="state || '-' || county"
value="sum(sales)"
/%}
{% /map %}
```
### US Counties by FIPS
```liquid theme={null}
{% map %}
{% area_layer
geography="us_counties"
match_by="fips"
data="county_sales"
area_id="state_fips || county_fips"
value="sum(sales)"
/%}
{% /map %}
```
### Custom GeoJSON
```liquid theme={null}
{% area_layer
geojson_url="https://example.com/custom.geojson"
geojson_id="id"
data="my_data"
area_id="region_id"
value="sum(sales)"
/%}
```
### Diverging Scale Centered at 0
```liquid theme={null}
{% map %}
{% area_layer
geography="us_states"
match_by="abbr"
data="state_growth"
area_id="state_abbr"
value="growth_pct"
color_scale=["#d73027", "#ffffbf", "#1a9850"]
min=-100
max=100
midpoint=0
/%}
{% /map %}
```
## Attributes
Name of the table to query
Array of filter IDs to apply
Pre-provided geography (use this OR geojson\_url + geojson\_id)
**Allowed values:**
* `us_states`
* `us_counties`
How to match areas. For us\_states: "name", "abbr", or "fips". For us\_counties: "state-county" or "fips".
URL to custom GeoJSON file (use with geojson\_id for custom maps)
GeoJSON property to join on. Use a string for single property (e.g., "NAME") or array for composite key (e.g., \["STATE", "COUNTY"]).
Column name in data that matches geo\_id (e.g., "state\_id")
Column or expression for coloring the choropleth (e.g., "sum(sales)")
Array of colors for the choropleth gradient. A single-color array auto-expands to \[background, color].
Deprecated. Use `color_scale`.
Lower bound for the color scale. Values below this clamp to the first color in the scale. Defaults to the minimum value in the data.
Upper bound for the color scale. Values above this clamp to the last color in the scale. Defaults to the maximum value in the data.
Anchor a specific value (typically 0) at the middle of a diverging color scale. Requires a color\_scale with 3 or more colors.
Whether to show areas that do not have matching data
Show tooltips on hover
Array of SQL expressions for additional fields to show in tooltip (e.g., \["category", "emissions"])
GeoJSON property to use for area name in tooltip (defaults to "NAME")
Format for values in tooltip. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Zoom range \[min, max] where this layer is visible (e.g., \[0, 8] shows layer from zoom 0 to 8)
Show legend for this layer
Custom label for the legend (defaults to table name)
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
## Allowed Parents
* [map](/components/map)
# Audio
Source: https://docs.evidence.studio/components/audio
Embed an audio player for mp3, wav, and other audio formats
```liquid theme={null}
{% audio url="https://files.example.com/podcast/episode-01.mp3" /%}
```
## Examples
### Basic Audio Player
```liquid theme={null}
{% audio url="https://files.example.com/podcast/episode-01.mp3" /%}
```
### WAV File with Title
```liquid theme={null}
{% audio url="https://files.example.com/recordings/call.wav" type="wav" title="Call Recording" /%}
```
## Attributes
URL of the audio file (may include query parameters such as SAS tokens)
MIME subtype of the audio file (e.g. mpeg, wav, ogg, mp4). Mapped to audio/\[type] for the browser.
Accessible label for the audio player
# Bar
Source: https://docs.evidence.studio/components/bar
Add a bar series to a [combo_chart](/components/combo_chart)
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bar y="sum(total_sales)" /%}
{% /combo_chart %}
```
## Examples
### Basic Bar Series
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bar y="sum(total_sales)" /%}
{% /combo_chart %}
```
### Unstacked Bars
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bar y="sum(total_sales)" series="category" stacked=false /%}
{% /combo_chart %}
```
### Multiple Stacks
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bar y="sum(total_sales)" stack_id="sales" /%}
{% bar y="sum(total_sales)+1000000" stack_id="sales" /%}
{% bar y="sum(quantity)" stack_id="quantity" /%}
{% /combo_chart %}
```
### Extra tooltip fields
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bar
y="sum(total_sales)"
fmt="usd"
tooltip_fields=[
{ value="count(distinct order_id)", label="Orders" },
{ value="sum(total_sales) - lag(sum(total_sales)) over (order by date_trunc('month', date))", label="MoM Δ", fmt="usd", color_by_sign=true }
]
/%}
{% /combo_chart %}
```
## Attributes
Column name for y-axis. Aggregated at the parent combo\_chart's `x=`. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
Column name for series grouping
The axis to render the series on
**Allowed values:**
* `y1`
* `y2`
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
**Attributes:**
* color: `string`
* opacity: `number` - Between 0 and 1
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into this series only. For overrides that apply to every series on the chart, set `echarts_series_options` on the parent chart instead.
**Example:**
```
echarts_options={
endLabel={ show=true }
markPoint={ data=[{ type="max" } { type="min" }] }
}
```
Whether to stack bars with the same series value. Set to "100%" for percentage stacking.
Stack identifier - bars with the same stack\_id value will be stacked together. Overrides the stacked prop.
## Allowed Parents
* [combo\_chart](/components/combo_chart)
# Bar Chart
Source: https://docs.evidence.studio/components/bar_chart
Display a bar chart
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
/%}
```
### Bar Chart with Date Grain
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
date_grain="month"
/%}
```
### Sorting by Value
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
order="sum(total_sales) desc"
/%}
```
### Custom Category Order
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
x_sort=["Clothing", "Home", "Sports", "Electronics"]
/%}
```
### Bar Chart with Series Colors
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
series="case when sum(total_sales) > 7000 then '>$7k' when sum(total_sales) > 3500 then '>$3.5k' else '<$3.5k' end"
title="Sales by Category and Performance"
chart_options={
series_colors={
">$7k"="#22c55e"
">$3.5k"="#f59e0b"
"<$3.5k"="#ef4444"
}
}
/%}
```
### 100% Stacked Bar Chart
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
series="category"
stacked="100%"
date_grain="month"
title="Sales Distribution by Category"
/%}
```
### Revenue by Day of Week
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of week"
title="Revenue by Day of Week"
subtitle="Weekday vs weekend sales patterns"
/%}
```
### Seasonality Analysis (Month of Year)
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="month of year"
title="Seasonality Analysis"
subtitle="Sales patterns across months"
/%}
```
### Quarterly Trends
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="quarter of year"
title="Quarterly Performance"
subtitle="Q1 through Q4 comparison"
/%}
```
### Monthly Billing Cycle Patterns
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of month"
title="Daily Revenue by Day of Month"
subtitle="Identify billing cycle patterns"
/%}
```
### Week Number Analysis
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="week of year"
title="Revenue by Week of Year"
subtitle="Weekly performance across the year"
/%}
```
### Day of Year Analysis
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="day of year"
title="Revenue by Day of Year"
subtitle="Identify patterns across 365 days"
/%}
```
### Extra tooltip fields
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
y_fmt="usd"
date_grain="month"
tooltip_fields=[
{ value="count(distinct order_id)", label="Orders" },
{ value="sum(total_sales) / nullif(count(distinct order_id), 0)", label="Avg order", fmt="usd" }
]
/%}
```
### Raw ECharts overrides (rounded bars, background track)
```liquid theme={null}
{% bar_chart
data="demo.daily_orders"
x="category"
y="sum(total_sales)"
echarts_series_options={
itemStyle={ borderRadius=[6 6 0 0] }
showBackground=true
backgroundStyle={ color="rgba(0,0,0,0.04)" }
}
/%}
```
## Attributes
Name of the table to query. Required unless every child series uses `metric="..."` — metric children resolve their own base from the metric view.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
How to handle missing data points. "connect" auto-connects points (default), "gaps" shows visual breaks, "zero" fills with zeros.
**Allowed values:**
* `connect`
* `gaps`
* `zero`
Column name for x-axis. Required unless every child series uses `metric="..."` — metric children fall back to the metric view's time column.
Format for x values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y2 values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Column name for series grouping (applies to all series)
Column name for individual point labels displayed at the top of the tooltip
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Sort order for x-axis categories. Options: `asc` (alphabetical), `desc` (reverse alphabetical), `data` (preserve query order), or an array for custom order like `["A", "B", "C"]`
**Allowed values:**
* `asc`
* `desc`
* `data`
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the secondary y-axis
**Example:**
```
y2_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Show legend. Studio's built-in legend renders a compact color swatch + series name. For chart-wide style overrides that need the legend to reflect them precisely (line width, custom symbols, richer styling), set `legend=false` and provide `legend={ show=true ... }` inside `echarts_options` to use ECharts' native legend instead.
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Array of series names to define the order of series in the chart and legend. Series not in the array will appear after the ordered ones.
Studio-shaped chart styling shortcuts (palette, series colors, zoom, padding). For raw ECharts overrides, use `echarts_options` instead.
**Example:**
```
chart_options={
color_palette = ["#3b82f6", "#8b5cf6", "#ec4899"]
series_colors = {
"Series A" = "#3b82f6"
"Series B" = "#10b981"
"Series C" = "#f59e0b"
}
zoom = true
top_padding = 0
}
```
**Attributes:**
* color\_palette: `array of strings` - Array of hex color codes to use for series colors
* series\_colors: `map of key-value pairs` - Map of series names to hex color codes for custom series coloring
* zoom: `boolean` - Enables zoom by dragging on the chart area
* top\_padding: `number` - Additional padding (in px) above the chart area to prevent labels from being cut off
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `dataZoom`, `visualMap`, `graphic`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For per-series overrides, use `echarts_series_options` or the per-series `echarts_options` on a `line`/`bar`/etc. child.
**Example:**
```
echarts_options={
tooltip={ position="top" }
dataZoom=[{ type="slider" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into every data series in the chart. Use when the same override should apply to all series. Skips reference lines/areas/points. For a single series, set `echarts_options` on the series child instead.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
markLine={ data=[{ type="average" }] }
}
```
Column name for y-axis
Semantic metric name(s) to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes. Pass an array for multiple series (e.g. `metric=["revenue", "orders"]`).
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
**Attributes:**
* color: `string`
* opacity: `number` - Between 0 and 1
Whether to stack the bars. Set to "100%" for percentage stacking where each bar shows its proportion of the total.
Column name for secondary y-axis
**Attributes:**
* color: `string`
* opacity: `number` - Between 0 and 1
## Allowed Children
* [reference\_line](/components/reference_line)
* [reference\_area](/components/reference_area)
* [reference\_point](/components/reference_point)
# Benchmark Comparison
Source: https://docs.evidence.studio/components/benchmark_comparison
Define a custom benchmark comparison option for a comparison_selector
```liquid theme={null}
{% benchmark_comparison
name="vs Franchisees"
agg="avg"
subject="store_id"
where="ownership_type = 'franchise'"
/%}
```
## Examples
### Compare vs Franchisees
```liquid theme={null}
{% benchmark_comparison
name="vs Franchisees"
agg="avg"
subject="store_id"
where="ownership_type = 'franchise'"
/%}
```
### Compare vs Full Network
```liquid theme={null}
{% benchmark_comparison
name="vs Full Network"
agg="avg"
subject="store_id"
/%}
```
### Compare vs Region Average
```liquid theme={null}
{% benchmark_comparison
name="vs Region Avg"
agg="avg"
subject="store_id"
within=["region"]
/%}
```
## Attributes
Display name shown in the dropdown (e.g., "vs Franchisees")
Aggregation function to apply across benchmark entities. Options: avg, median, min, max, sum, count, count\_distinct
**Allowed values:**
* `avg`
* `median`
* `min`
* `max`
* `sum`
* `count`
* `count_distinct`
Column that defines individual entities (e.g., "store\_id", "customer\_id"). Required for benchmark calculations.
Optional column or expression to use for benchmark calculation. If not specified, uses the main value column. Useful if you have a pre-aggregated benchmark table for RLS reasons.
SQL WHERE clause to filter which entities are included in the benchmark (e.g., "ownership\_type = 'franchise'")
Dimension columns to group the benchmark by (e.g., \["region"]). Leave empty for dataset-wide benchmark.
Exclude the current row from its own benchmark calculation (table context only). Default: false
Default display type for this comparison. Options: pct (percentage change), abs (absolute change), compared\_value (benchmark value)
**Allowed values:**
* `pct`
* `abs`
* `compared_value`
Custom comparison label text (overrides default "vs ")
Format code for percentage values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format code for absolute values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
If true, negative changes are shown as positive (green)
## Allowed Parents
* [comparison\_selector](/components/comparison_selector)
# Big Value
Source: https://docs.evidence.studio/components/big_value
Display a big value with optional comparison, delta, and sparkline
```liquid theme={null}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
/%}
```
### Comparison
```liquid theme={null}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
date_range={
date="date"
range="last 12 months"
}
comparison={
compare_vs="prior year"
}
/%}
```
### Sparkline
```liquid theme={null}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
sparkline={
type="line"
x="date"
}
/%}
```
### Text Size
```liquid theme={null}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
text_size="4xl"
/%}
```
## Attributes
Table or view to query. Omit when using `metric`.
Semantic metric to display (the whole reference — a metric is a single number). Use instead of `data` + `value`.
The SQL aggregation to display (with `data`). Omit when using `metric`.
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Comparison configuration object
**Example:**
```
comparison={
compare_vs = "prior year"
display_type = "compared_value"
target = "string"
benchmark = {
agg = "avg"
subject = "store_name"
within = ["region"]
}
hide_pct = true
pct_fmt = "string"
abs_fmt = "string"
text = "string"
delta = true
down_is_good = true
neutral_range = []
}
```
**Attributes:**
* compare\_vs: `string` - Type of comparison to perform. Options: prior year (same period last year), prior period (previous period of same duration), target (compare against a target value), benchmark (compare against group average/aggregate)
* **Allowed values:**
* `prior year`
* `prior period`
* `target`
* `benchmark`
* display\_type: `string` - What to display for comparison. Options: compared\_value (comparison period value), abs (absolute change), pct (percentage change). Default: pct
* **Allowed values:**
* `compared_value`
* `abs`
* `pct`
* target: `string` - Target value for target comparison. Can be a column name, aggregation (e.g., "sum(target\_sales)"), or literal value.
* benchmark: `options group`
* **Options:**
* agg: `string` - Aggregation function to apply across benchmark group. Options: avg (average), median, min, max, sum, count, count\_distinct
* **Allowed values:**
* `avg`
* `median`
* `min`
* `max`
* `sum`
* `count`
* `count_distinct`
* subject: `string` - Column or expression that defines individual entities in the benchmark (e.g., "store\_name", "customer\_id"). Required for single-value components.
* value: `string` - Optional column or expression to use for benchmark calculation. If not specified, uses the main value column. Useful if you have a pre-aggregated benchmark table for RLS reasons.
* within: `array of strings` - Dimension columns to group the benchmark by (e.g., \["region"]). Leave empty for dataset-wide benchmark.
* where: `string` - SQL WHERE clause to filter which entities are included in the benchmark
* exclude\_self: `boolean` - Exclude the current row from its own benchmark calculation (table context only). Default: false
* hide\_pct: `boolean` - Hide the percentage change line in comparison tooltips
* pct\_fmt: `string` - Format code for percentage values in comparison tooltips
* abs\_fmt: `string` - Format code for absolute values in comparison tooltips
* text: `string` - Text displayed after the comparison value
* delta: `boolean` - Whether to display the comparison as a delta
* down\_is\_good: `boolean` - Whether a decrease is considered positive
* neutral\_range: `array` - Range \[min, max] for neutral values. Use null for infinity (e.g., \[null, 0] means anything ≤ 0 is neutral)
Sparkline configuration object
**Example:**
```
sparkline={
type = "line"
color = "string"
x = "string"
y_fmt = "string"
x_fmt = "string"
fit_to_data = true
connect_group = "string"
date_grain = "year"
date_range = {
range = "today"
date = "string"
}
}
```
**Attributes:**
* type: `string` - The type of sparkline to display
* **Allowed values:**
* `line`
* `area`
* `bar`
* color: `string` - Color for the sparkline
* x: `string` - X column for the sparkline
* y\_fmt: `string` - Value format for the sparkline tooltips
* x\_fmt: `string` - Date format for the sparkline tooltips
* fit\_to\_data: `boolean` - Whether to fit the Y axis scale to the data range
* connect\_group: `string` - Connect group for the sparkline
* date\_grain: `string` - Time grain for the sparkline data points
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* `minute`
* date\_range: `options group`
* **Options:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Format for the main value. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Title for the main value
Maximum width of the component
Minimum width of the component
Text size for the value. Options: sm, base, lg, xl (default), 2xl, 3xl, 4xl, 5xl
**Allowed values:**
* `sm`
* `base`
* `lg`
* `xl`
* `2xl`
* `3xl`
* `4xl`
* `5xl`
Additional CSS classes for the title
Additional CSS classes for the value
URL to link the title to
Information tooltip text
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
IDs of filters to apply to the query
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Additional CSS classes for the component
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Set the width of this component (in percent) relative to the page width
# Bubble
Source: https://docs.evidence.studio/components/bubble
Add a bubble series to a [combo_chart](/components/combo_chart)
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bubble
y="avg(avg_transaction_value)"
size="sum(transactions)"
/%}
{% /combo_chart %}
```
## Examples
### Basic Bubble Series
```liquid theme={null}
{% combo_chart data="demo.daily_orders" x="date" date_grain="month" %}
{% bubble
y="avg(avg_transaction_value)"
size="sum(transactions)"
/%}
{% /combo_chart %}
```
## Attributes
Column name for y-axis. Aggregated at the parent combo\_chart's `x=`. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
Column name for series grouping
The axis to render the series on
**Allowed values:**
* `y1`
* `y2`
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
The opacity of the series
Column to use for the size of the bubbles
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into this series only. For overrides that apply to every series on the chart, set `echarts_series_options` on the parent chart instead.
**Example:**
```
echarts_options={
endLabel={ show=true }
markPoint={ data=[{ type="max" } { type="min" }] }
}
```
## Allowed Parents
* [combo\_chart](/components/combo_chart)
# Bubble Chart
Source: https://docs.evidence.studio/components/bubble_chart
Display a bubble chart
```liquid theme={null}
{% bubble_chart
data="demo.daily_orders"
x="sum(total_sales)"
y="avg(avg_transaction_value)"
size="sum(transactions)"
series="category"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% bubble_chart
data="demo.daily_orders"
x="sum(total_sales)"
y="avg(avg_transaction_value)"
size="sum(transactions)"
series="category"
/%}
```
### Bubble Chart with Formatting
```liquid theme={null}
{% bubble_chart
data="demo.daily_orders"
x="sum(total_sales)"
y="avg(avg_transaction_value)"
size="sum(transactions)"
x_fmt="usd"
y_fmt="usd"
title="Sales Performance Analysis"
subtitle="Bubble size represents transaction count"
series="category"
/%}
```
### Bubble Chart with Point Titles
```liquid theme={null}
{% bubble_chart
data="demo.daily_orders"
x="sum(total_sales)"
y="avg(avg_transaction_value)"
size="sum(transactions)"
point_title="category"
x_fmt="usd"
y_fmt="usd"
/%}
```
## Attributes
Name of the table to query. Required unless every child series uses `metric="..."` — metric children resolve their own base from the metric view.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
How to handle missing data points. "connect" auto-connects points (default), "gaps" shows visual breaks, "zero" fills with zeros.
**Allowed values:**
* `connect`
* `gaps`
* `zero`
Column name for x-axis. Required unless every child series uses `metric="..."` — metric children fall back to the metric view's time column.
Format for x values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y2 values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Column name for series grouping (applies to all series)
Column name for individual point labels displayed at the top of the tooltip
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Sort order for x-axis categories. Options: `asc` (alphabetical), `desc` (reverse alphabetical), `data` (preserve query order), or an array for custom order like `["A", "B", "C"]`
**Allowed values:**
* `asc`
* `desc`
* `data`
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the secondary y-axis
**Example:**
```
y2_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Show legend. Studio's built-in legend renders a compact color swatch + series name. For chart-wide style overrides that need the legend to reflect them precisely (line width, custom symbols, richer styling), set `legend=false` and provide `legend={ show=true ... }` inside `echarts_options` to use ECharts' native legend instead.
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Array of series names to define the order of series in the chart and legend. Series not in the array will appear after the ordered ones.
Studio-shaped chart styling shortcuts (palette, series colors, zoom, padding). For raw ECharts overrides, use `echarts_options` instead.
**Example:**
```
chart_options={
color_palette = ["#3b82f6", "#8b5cf6", "#ec4899"]
series_colors = {
"Series A" = "#3b82f6"
"Series B" = "#10b981"
"Series C" = "#f59e0b"
}
zoom = true
top_padding = 0
}
```
**Attributes:**
* color\_palette: `array of strings` - Array of hex color codes to use for series colors
* series\_colors: `map of key-value pairs` - Map of series names to hex color codes for custom series coloring
* zoom: `boolean` - Enables zoom by dragging on the chart area
* top\_padding: `number` - Additional padding (in px) above the chart area to prevent labels from being cut off
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `dataZoom`, `visualMap`, `graphic`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For per-series overrides, use `echarts_series_options` or the per-series `echarts_options` on a `line`/`bar`/etc. child.
**Example:**
```
echarts_options={
tooltip={ position="top" }
dataZoom=[{ type="slider" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into every data series in the chart. Use when the same override should apply to all series. Skips reference lines/areas/points. For a single series, set `echarts_options` on the series child instead.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
markLine={ data=[{ type="average" }] }
}
```
Column name for y-axis
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
Format for this series' values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
The opacity of the series
Column to use for the size of the bubbles
Column name for secondary y-axis
Format for size values in tooltips. See [Value Formatting](/core-concepts/value-formatting) for available formats.
## Allowed Children
* [reference\_line](/components/reference_line)
* [reference\_area](/components/reference_area)
* [reference\_point](/components/reference_point)
# Button Group
Source: https://docs.evidence.studio/components/button_group
Display a segmented button group with distinct values from a database column to use in filters
```liquid theme={null}
{% button_group
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
filters=["category_filter"]
date_grain="month"
/%}
```
## Examples
### Using `filters`
```liquid theme={null}
{% button_group
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
filters=["category_filter"]
date_grain="month"
/%}
```
### Using `where`
```liquid theme={null}
{% button_group
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
where="category = {{category_filter}}"
date_grain="month"
/%}
```
### Using Inline SQL
````liquid theme={null}
{% button_group
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
```sql filtered_orders
select * from demo.daily_orders
where category = {{category_filter}}
```
{% table data="filtered_orders" /%}
````
### Vertical orientation inside a row
```liquid theme={null}
{% row %}
{% button_group
id="category_filter"
data="demo.daily_orders"
value_column="category"
orientation="vertical"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
filters=["category_filter"]
date_grain="month"
/%}
{% /row %}
```
## Attributes
The id of the button group to be used in a `filters` prop
Name of the table to query
Array of filter IDs to apply when querying for options
Column name to use as the value for each option, and the column to filter by when this button group's `id` is used in the `filters` prop of a chart
Column name to use as the label for each option
Text displayed above the button group
Information tooltip text
Initial selected value(s)
Allows multiple selections
Automatically select the first option when the component loads
Layout direction of the button group. Use "vertical" to stack buttons in a column. Best paired with a sibling element inside a `row` so the stack sits alongside its target content.
**Allowed values:**
* `horizontal`
* `vertical`
Maximum height in pixels for the button stack when `orientation="vertical"`. Buttons scroll if the list overflows. Ignored when horizontal.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
## Using the Filter Variable
Reference this filter using `{{filter_id}}`. The value returned depends on where you use it.
The examples below show values for three scenarios:
* **No selection**
* **Single select:** "Electronics" selected
* **Multi select:** "Sports" and "Home" selected (when `multiple=true`)
| Context | Default Property | No Selection | Single Select | Multi Select |
| ----------------- | ---------------- | ------------ | --------------- | -------------------- |
| Inline SQL query | `.selected` | `''` | `'Electronics'` | `('Sports', 'Home')` |
| `where` attribute | `.selected` | `''` | `'Electronics'` | `('Sports', 'Home')` |
| Text / Markdown | `.literal` | | `Electronics` | `Sports, Home` |
### Available Properties
You can also access specific properties using `{{filter_id.property}}`:
#### .filter
Returns a complete SQL filter expression ready to use in WHERE clauses. Returns `true` when no value is selected.
````liquid theme={null}
{% button_group id="category_filter" data="products" value_column="category" /%}
```sql filtered_products
select * from products
where {{category_filter.filter}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | -------------------------- | -------------------------------- |
| `true` | `category = 'Electronics'` | `category IN ('Sports', 'Home')` |
#### .selected
Returns the selected value(s) wrapped in quotes, suitable for SQL comparisons. Returns an empty string when no value is selected.
````liquid theme={null}
{% button_group id="category_filter" data="products" value_column="category" /%}
```sql products_by_category
select * from products
where category = {{category_filter.selected}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | --------------- | -------------------- |
| `''` | `'Electronics'` | `('Sports', 'Home')` |
#### .literal
Returns the raw unescaped selected value(s), useful for display in text or dynamic column selection.
````liquid theme={null}
{% button_group id="sort_column" data="products" value_column="column_name" /%}
```sql dynamic_sort
select * from products
order by {{sort_column.literal}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | -------------- |
| \`\` | `Electronics` | `Sports, Home` |
#### .label
Returns the display label for the selected option(s). Falls back to the value if no label is defined.
```liquid theme={null}
{% button_group id="category_filter" %}
{% option value="Electronics" label="Electronics" /%}
{% option value="Sports" label="Sports" /%}
{% option value="Home" label="Home" /%}
{% /button_group %}
Selected: {{category_filter.label}}
```
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | -------------- |
| \`\` | `Electronics` | `Sports, Home` |
#### .fmt
Returns the format string associated with the selected option. For multiple selections, returns the first format.
```liquid theme={null}
{% button_group id="metric_selector" %}
{% option value="revenue" label="Revenue" fmt="usd" /%}
{% option value="growth_rate" label="Growth Rate" fmt="pct1" /%}
{% /button_group %}
{% big_value data={metrics} value=value fmt={{metric_selector.fmt}} /%}
```
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | ------------ |
| \`\` | `usd` | `usd` |
## Allowed Children
* [option](/components/option)
# Calendar Heatmap
Source: https://docs.evidence.studio/components/calendar_heatmap
Display a calendar heatmap visualization
```liquid theme={null}
{% calendar_heatmap
data="demo.daily_orders"
date="date"
value="sum(total_sales)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% calendar_heatmap
data="demo.daily_orders"
date="date"
value="sum(total_sales)"
/%}
```
### Calendar Heatmap with Custom Colors
```liquid theme={null}
{% calendar_heatmap
data="demo.daily_orders"
date="date"
value="sum(total_sales)"
title="Daily Sales Heatmap"
chart_options={
color_scale = ["#0d0887", "#6300a7", "#a62098", "#d5546e", "#f68d45", "#fcd225", "#f0f921"]
}
/%}
```
### Calendar Heatmap with Conditional Colors
```liquid theme={null}
{% calendar_heatmap
data="demo.daily_orders"
date="date"
value="sum(total_sales)"
title="Sales Performance Heatmap"
chart_options={
conditional_colors = "case when sum(total_sales) > 65000 then '#22c55e' when sum(total_sales) > 40000 then '#f59e0b' else '#ef4444' end"
}
/%}
```
### Calendar Heatmap with Conditional Colors and Legend
```liquid theme={null}
{% calendar_heatmap
data="demo.daily_orders"
date="date"
value="sum(total_sales)"
title="Sales Performance Heatmap"
chart_options={
conditional_colors="case when sum(total_sales) > 65000 then '#22c55e' when sum(total_sales) > 40000 then '#f59e0b' else '#ef4444' end"
color_map={
"#22c55e"="High Sales"
"#f59e0b"="Medium Sales"
"#ef4444"="Low Sales"
}
}
/%}
```
## Attributes
Name of the table to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Column name for dates
Column name for cell values. Omit when using `metric`.
Title to display above the chart
Subtitle to display below the title
Information tooltip text (can only be used with title)
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Format for values (defaults to `num`, or the metric format in metric mode). See [Value Formatting](/core-concepts/value-formatting) for available formats.
Show color scale legend
Show borders between calendar cells
Color and styling options for the heatmap
**Example:**
```
chart_options={
color_scale = ["value1", "value2"]
color_palette = ["value1", "value2"]
conditional_colors = "string"
color_map = {
"key1" = "value1"
"key2" = "value2"
}
}
```
**Attributes:**
* color\_scale: `array of strings` - Array of hex colors for the heatmap gradient. A single-color array auto-expands to \[background, color].
* color\_palette: `array of strings` - Deprecated. Use `color_scale`.
* conditional\_colors: `string` - SQL CASE expression returning hex colors based on value
* color\_map: `map of key-value pairs` - Maps hex colors to legend labels when using conditional\_colors
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into the chart series. Use for series-level styling the structured props do not expose.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
}
```
# Callout
Source: https://docs.evidence.studio/components/callout
Add a callout box to show a message or highlight a section of text
```liquid theme={null}
{% callout type="info" title="Report Info"%}
This is an info callout
{% /callout %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% callout type="info" title="Report Info"%}
This is an info callout
{% /callout %}
```
## Attributes
**Allowed values:**
* `info`
* `success`
* `warning`
* `error`
Set the width of this component (in percent) relative to the page width
# Candlestick
Source: https://docs.evidence.studio/components/candlestick
Display a candlestick chart for OHLC (Open, High, Low, Close) financial data visualization
````liquid theme={null}
```sql stock_prices
SELECT '2024-01-01'::date as date, 100.0 as open, 105.0 as high, 95.0 as low, 102.0 as close
UNION ALL SELECT '2024-01-02'::date, 102.0, 108.0, 100.0, 105.0
UNION ALL SELECT '2024-01-03'::date, 105.0, 110.0, 103.0, 108.0
UNION ALL SELECT '2024-01-04'::date, 108.0, 112.0, 106.0, 104.0
UNION ALL SELECT '2024-01-05'::date, 104.0, 107.0, 98.0, 100.0
```
{% candlestick
data="stock_prices"
x="date"
open="open"
high="high"
low="low"
close="close"
y_axis_options={
min=90
max=115
}
/%}
````
## Examples
### Basic Usage
````liquid theme={null}
```sql stock_prices
SELECT '2024-01-01'::date as date, 100.0 as open, 105.0 as high, 95.0 as low, 102.0 as close
UNION ALL SELECT '2024-01-02'::date, 102.0, 108.0, 100.0, 105.0
UNION ALL SELECT '2024-01-03'::date, 105.0, 110.0, 103.0, 108.0
UNION ALL SELECT '2024-01-04'::date, 108.0, 112.0, 106.0, 104.0
UNION ALL SELECT '2024-01-05'::date, 104.0, 107.0, 98.0, 100.0
```
{% candlestick
data="stock_prices"
x="date"
open="open"
high="high"
low="low"
close="close"
y_axis_options={
min=90
max=115
}
/%}
````
### With Volume
````liquid theme={null}
```sql stock_prices
SELECT '2024-01-01'::date as date, 100.0 as open, 105.0 as high, 95.0 as low, 102.0 as close, 1500000 as volume
UNION ALL SELECT '2024-01-02'::date, 102.0, 108.0, 100.0, 105.0, 2100000
UNION ALL SELECT '2024-01-03'::date, 105.0, 110.0, 103.0, 108.0, 1800000
UNION ALL SELECT '2024-01-04'::date, 108.0, 112.0, 106.0, 104.0, 2500000
UNION ALL SELECT '2024-01-05'::date, 104.0, 107.0, 98.0, 100.0, 3200000
```
{% candlestick
data="stock_prices"
x="date"
open="open"
high="high"
low="low"
close="close"
volume="volume"
y2_fmt="num0"
title="Stock Price with Volume"
y_axis_options={
min=90
max=115
}
/%}
````
### With Custom Colors
````liquid theme={null}
```sql stock_prices
SELECT '2024-01-01'::date as date, 100.0 as open, 105.0 as high, 95.0 as low, 102.0 as close
UNION ALL SELECT '2024-01-02'::date, 102.0, 108.0, 100.0, 105.0
UNION ALL SELECT '2024-01-03'::date, 105.0, 110.0, 103.0, 108.0
UNION ALL SELECT '2024-01-04'::date, 108.0, 112.0, 106.0, 104.0
UNION ALL SELECT '2024-01-05'::date, 104.0, 107.0, 98.0, 100.0
```
{% candlestick
data="stock_prices"
x="date"
open="open"
high="high"
low="low"
close="close"
chart_options={
up_color="#22c55e"
down_color="#ef4444"
}
y_axis_options={
min=90
max=115
}
/%}
````
## Attributes
Name of the table or view to query
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
Column for x-axis (typically date/time)
Column for opening price
Column for high price
Column for low price
Column for closing price
Column for trading volume (displayed as bars on secondary y-axis)
Format for x-axis values and labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y-axis values and labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for secondary y-axis (volume) values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Candlestick chart configuration options
**Attributes:**
* up\_color: `string` - Color for bullish (up) candles
* down\_color: `string` - Color for bearish (down) candles
* zoom: `boolean` - Enables zoom by dragging on the chart area
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
# Chord Chart
Source: https://docs.evidence.studio/components/chord_chart
Display a chord diagram showing flows between nodes around a circle
```liquid theme={null}
{% chord_chart
data="demo.order_details"
source="category"
target="item_name"
value="sum(quantity)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% chord_chart
data="demo.order_details"
source="category"
target="item_name"
value="sum(quantity)"
/%}
```
### Chord Chart with Custom Colors
```liquid theme={null}
{% chord_chart
data="demo.order_details"
source="category"
target="item_name"
value="sum(quantity)"
title="Category to Item Flow"
chart_options={
color_palette = ["#0d0887", "#6300a7", "#a62098", "#d5546e", "#f68d45", "#fcd225", "#f0f921"]
}
/%}
```
### Chord Chart with Raw ECharts Overrides
```liquid theme={null}
{% chord_chart
data="demo.order_details"
source="category"
target="item_name"
value="sum(quantity)"
echarts_options={
series=[{ startAngle=0 padAngle=6 }]
}
echarts_series_options={
itemStyle={ borderRadius=6 }
}
/%}
```
## Attributes
Name of the table or view to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Column name for source nodes
Column name for target nodes
Column name for flow values (chord thickness). Omit when using `metric`.
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Format for values (defaults to `num`, or the metric format in metric mode). See [Value Formatting](/core-concepts/value-formatting) for available formats.
Show node labels around the circle
Chart configuration options
**Example:**
```
chart_options={
color_palette = ["value1", "value2"]
series_colors = {
"key1" = "value1"
"key2" = "value2"
}
}
```
**Attributes:**
* color\_palette: `array of strings`
* series\_colors: `map of key-value pairs`
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into the chart series. Use for series-level styling the structured props do not expose.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
}
```
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
# Clock
Source: https://docs.evidence.studio/components/clock
Display a live clock with running seconds and the current date
```liquid theme={null}
{% clock /%}
```
## Examples
### Default Clock (12h)
```liquid theme={null}
{% clock /%}
```
### 24-Hour Clock
```liquid theme={null}
{% clock format="24h" /%}
```
## Attributes
Time format: 12-hour or 24-hour
**Allowed values:**
* `12h`
* `24h`
Font variant: sans-serif or monospace
**Allowed values:**
* `sans`
* `mono`
Text alignment
**Allowed values:**
* `left`
* `right`
# Combo Chart
Source: https://docs.evidence.studio/components/combo_chart
Display a chart with a combination of multiple series types. Accepts area, bar, bubble, line, and scatter children series.
```liquid theme={null}
{% combo_chart
data="demo.daily_orders"
x="date"
date_grain="month"
%}
{% line
y="sum(total_sales)"
/%}
{% bar
y="sum(transactions)"
axis="y2"
/%}
{% /combo_chart %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% combo_chart
data="demo.daily_orders"
x="date"
date_grain="month"
%}
{% line
y="sum(total_sales)"
/%}
{% bar
y="sum(transactions)"
axis="y2"
/%}
{% /combo_chart %}
```
### Combo Chart with Area and Line
```liquid theme={null}
{% combo_chart
data="demo.daily_orders"
x="date"
date_grain="month"
%}
{% area
y="sum(total_sales)"
/%}
{% line
y="avg(avg_transaction_value)"
axis="y2"
/%}
{% /combo_chart %}
```
### Combo Chart with Formatting
```liquid theme={null}
{% combo_chart
data="demo.daily_orders"
x="date"
y_fmt="usd"
y2_fmt="num0"
title="Sales and Transactions Overview"
subtitle="Combined view of sales and transaction volume"
date_grain="month"
%}
{% line
y="sum(total_sales)"
/%}
{% bar
y="sum(transactions)"
axis="y2"
/%}
{% /combo_chart %}
```
### Raw ECharts overrides
```liquid theme={null}
{% combo_chart
data="demo.daily_orders"
x="date"
date_grain="month"
echarts_options={
dataZoom=[{ type="slider" }]
tooltip={ position="top" }
}
echarts_series_options={
itemStyle={ borderRadius=4 }
}
%}
{% bar y="sum(total_sales)" /%}
{% /combo_chart %}
```
## Attributes
Name of the table to query. Required unless every child series uses `metric="..."` — metric children resolve their own base from the metric view.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
How to handle missing data points. "connect" auto-connects points (default), "gaps" shows visual breaks, "zero" fills with zeros.
**Allowed values:**
* `connect`
* `gaps`
* `zero`
Column name for x-axis. Required unless every child series uses `metric="..."` — metric children fall back to the metric view's time column.
Format for x values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y2 values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Column name for series
Column name for individual point labels displayed at the top of the tooltip
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Sort order for x-axis categories. Options: `asc` (alphabetical), `desc` (reverse alphabetical), `data` (preserve query order), or an array for custom order like `["A", "B", "C"]`
**Allowed values:**
* `asc`
* `desc`
* `data`
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the secondary y-axis
**Example:**
```
y2_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Show legend. Studio's built-in legend renders a compact color swatch + series name. For chart-wide style overrides that need the legend to reflect them precisely (line width, custom symbols, richer styling), set `legend=false` and provide `legend={ show=true ... }` inside `echarts_options` to use ECharts' native legend instead.
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Array of series names to define the order of series in the chart and legend. Series not in the array will appear after the ordered ones.
Studio-shaped chart styling shortcuts (palette, series colors, zoom, padding). For raw ECharts overrides, use `echarts_options` instead.
**Example:**
```
chart_options={
color_palette = ["#3b82f6", "#8b5cf6", "#ec4899"]
series_colors = {
"Series A" = "#3b82f6"
"Series B" = "#10b981"
"Series C" = "#f59e0b"
}
zoom = true
top_padding = 0
}
```
**Attributes:**
* color\_palette: `array of strings` - Array of hex color codes to use for series colors
* series\_colors: `map of key-value pairs` - Map of series names to hex color codes for custom series coloring
* zoom: `boolean` - Enables zoom by dragging on the chart area
* top\_padding: `number` - Additional padding (in px) above the chart area to prevent labels from being cut off
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `dataZoom`, `visualMap`, `graphic`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For per-series overrides, use `echarts_series_options` or the per-series `echarts_options` on a `line`/`bar`/etc. child.
**Example:**
```
echarts_options={
tooltip={ position="top" }
dataZoom=[{ type="slider" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into every data series in the chart. Use when the same override should apply to all series. Skips reference lines/areas/points. For a single series, set `echarts_options` on the series child instead.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
markLine={ data=[{ type="average" }] }
}
```
## Allowed Children
* [area](/components/area)
* [bar](/components/bar)
* [bubble](/components/bubble)
* [line](/components/line)
* [scatter](/components/scatter)
* [reference\_line](/components/reference_line)
* [reference\_area](/components/reference_area)
* [reference\_point](/components/reference_point)
# Commentary
Source: https://docs.evidence.studio/components/commentary
Allows users to input commentary to be saved with the page
```liquid theme={null}
{% commentary
id=""
/%}
```
## Attributes
Unique identifier for the commentary component
Placeholder text to show when the commentary is empty
Additional CSS classes to apply to the component
Emails of allowed commentary editors
Title to display above the commentary
When to hide the edit metadata
**Allowed values:**
* `always`
* `never`
* `print`
Style of the commentary
**Allowed values:**
* `quote`
* `normal`
Set the width of this component (in percent) relative to the page width
# Comparison Selector
Source: https://docs.evidence.studio/components/comparison_selector
Display a selector for comparison options to use in SQL query templates
```liquid theme={null}
{% comparison_selector
id="comp"
default_value="prior year"
/%}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
date_range={
date="date"
range="last 12 months"
}
comparison={
compare_vs={{comp}}
}
/%}
```
## Examples
### Using `comparison`
```liquid theme={null}
{% comparison_selector
id="comp"
default_value="prior year"
/%}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
fmt="usd1m"
date_range={
date="date"
range="last 12 months"
}
comparison={
compare_vs={{comp}}
}
/%}
```
## Attributes
The id of the comparison selector to be used in SQL query templates
Optional array of preset comparison values to show. If not provided, all comparison options will be available.
Default comparison to select on load
**Allowed values:**
* `prior year`
* `prior period`
* `target`
* `benchmark`
Text displayed above the selector
Information tooltip text
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Placeholder text displayed when no value is selected
Icon to display
Set the width of this component (in percent) relative to the page width
## Using the Filter Variable
Reference this filter using `{{filter_id}}`. The value returned depends on where you use it.
| Context | Default Property | No Selection | Result |
| ----------------- | ---------------- | ------------ | ------------------------------ |
| Inline SQL query | `.comparison` | | `{"compare_vs": "prior year"}` |
| `where` attribute | `.comparison` | | `{"compare_vs": "prior year"}` |
| Text / Markdown | `.comparison` | | `{"compare_vs": "prior year"}` |
### Available Properties
You can also access specific properties using `{{filter_id.property}}`:
#### .selected
Returns the selected comparison value with quotes. Returns an empty string when no value is selected.
````liquid theme={null}
{% comparison_selector id="comparison" preset_values=["prior year", "prior period"] /%}
```sql sales_comparison
select
date,
sum(sales) as total_sales,
'{{comparison.selected}}' as comparison_type
from orders
group by date
```
````
**Example value:** `'prior year'`
#### .literal
Returns the raw unescaped selected value.
````liquid theme={null}
{% comparison_selector id="comparison" preset_values=["prior year", "prior period"] /%}
```sql sales_comparison
select
date,
sum(sales) as total_sales,
{{comparison.literal}} as comparison_type
from orders
group by date
```
````
**Example value:** `prior year`
#### .compare\_vs
Returns the comparison type.
**Example value:** `prior year`
#### .comparison
Returns the full comparison configuration as JSON. Use `{{comp}}` directly with `compare_vs` to dynamically configure comparisons.
```liquid theme={null}
{% comparison_selector id="comp" /%}
{% big_value
data="demo.daily_orders"
value="sum(total_sales)"
comparison={ compare_vs={{comp}} }
/%}
```
**Example value:** `{"compare_vs": "prior year"}`
#### .agg
For benchmark comparisons: returns the aggregation function.
**Example value:** `avg`
#### .subject
For benchmark comparisons: returns the subject column that defines entities.
**Example value:** `region`
#### .target
For target comparisons: returns the target value or expression.
**Example value:** `100000`
## Allowed Children
* [benchmark\_comparison](/components/benchmark_comparison)
* [target\_comparison](/components/target_comparison)
# Custom Echart
Source: https://docs.evidence.studio/components/custom_echart
Render any Apache ECharts chart type using a raw ECharts config in the tag body. An escape hatch for charts the built-in components cannot express.
```liquid theme={null}
{% custom_echart data="demo.daily_orders" %}
{
xAxis: { type: 'category' },
yAxis: {},
series: [{ type: 'bar', encode: { x: 'category', y: 'total_sales' } }]
}
{% /custom_echart %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% custom_echart data="demo.daily_orders" %}
{
xAxis: { type: 'category' },
yAxis: {},
series: [{ type: 'bar', encode: { x: 'category', y: 'total_sales' } }]
}
{% /custom_echart %}
```
### Multiple Series with Tooltip
```liquid theme={null}
{% custom_echart data="demo.daily_orders" %}
{
tooltip: { trigger: 'axis' },
legend: { show: true },
xAxis: { type: 'category' },
yAxis: {},
series: [
{ type: 'bar', name: 'Sales', encode: { x: 'category', y: 'total_sales' } },
{ type: 'line', name: 'Transactions', encode: { x: 'category', y: 'transactions' } }
]
}
{% /custom_echart %}
```
### Dataset Transform
```liquid theme={null}
{% custom_echart data="demo.daily_orders" %}
{
dataset: [
{},
{ transform: { type: 'sort', config: { dimension: 'total_sales', order: 'desc' } } }
],
xAxis: { type: 'category' },
yAxis: {},
series: [{ type: 'bar', datasetIndex: 1, encode: { x: 'category', y: 'total_sales' } }]
}
{% /custom_echart %}
```
### Waterfall (EBITDA Bridge)
````liquid theme={null}
```sql ebitda_bridge
select 'Prior EBITDA' as step, 1 as ord, 0 as placeholder, null as inc, null as dec, 32000000 as tot
union all select 'Home', 2, 32000000, 6200000, null, null
union all select 'Sports', 3, 38200000, 4100000, null, null
union all select 'Groceries', 4, 40000000, null, 2300000, null
union all select 'Current EBITDA', 5, 0, null, null, 40000000
order by ord
```
{% custom_echart data="ebitda_bridge" title="EBITDA Bridge" %}
{
tooltip: { trigger: 'axis', valueFormatter: 'fmt:usd1m' },
xAxis: { type: 'category', axisLabel: { interval: 0 } },
yAxis: { axisLabel: { formatter: 'fmt:usd0m' } },
series: [
{ type: 'bar', stack: 'bridge', silent: true,
itemStyle: { color: 'transparent' },
encode: { x: 'step', y: 'placeholder' } },
{ type: 'bar', stack: 'bridge', name: 'Increase',
itemStyle: { color: '#22A39F' },
label: { show: true, position: 'top', formatter: 'fmt:usd1m' },
encode: { x: 'step', y: 'inc' } },
{ type: 'bar', stack: 'bridge', name: 'Decrease',
itemStyle: { color: '#E2483D' },
label: { show: true, position: 'bottom', formatter: 'fmt:usd1m' },
encode: { x: 'step', y: 'dec' } },
{ type: 'bar', stack: 'bridge', name: 'Total',
itemStyle: { color: '#475569' },
label: { show: true, position: 'top', formatter: 'fmt:usd1m' },
encode: { x: 'step', y: 'tot' } }
]
}
{% /custom_echart %}
````
### JavaScript mode (functions, gradients)
```liquid theme={null}
{% custom_echart data="demo.daily_orders" %}
{
tooltip: { trigger: 'axis', valueFormatter: (value) => fmt(value, 'usd0') },
xAxis: { type: 'category' },
yAxis: { axisLabel: { formatter: (value) => fmt(value, 'usd0m') } },
series: [
{
type: 'bar',
encode: { x: 'category', y: 'total_sales' },
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: theme.colorPalettes.default[0] },
{ offset: 1, color: theme.colorPalettes.default[1] }
])
},
label: { show: true, formatter: (params) => fmt(params.value.total_sales, 'usd0') }
}
]
}
{% /custom_echart %}
```
## Attributes
Name of the table to query
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Title to display above the chart
Subtitle to display below the title
Information tooltip text (can only be used with title)
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
ECharts rendering engine
**Allowed values:**
* `canvas`
* `svg`
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
# Custom Map
Source: https://docs.evidence.studio/components/custom_map
Write a map in JavaScript with Mapbox GL or MapLibre GL, using your page data. Use it when the built-in map component does not cover what you need.
```liquid theme={null}
{% custom_map height=400 %}
// mapgl is Mapbox GL when a token is available, else MapLibre GL.
// container and the access token are provided for you.
const map = new mapgl.Map({
container,
center: [-71.06, 42.36],
zoom: 9
});
// Tiles load asynchronously — signal readiness once painted so PDF/PNG
// export captures a finished map rather than a blank frame.
map.on('idle', () => evidence.ready());
{% /custom_map %}
```
## Examples
### Basic map
```liquid theme={null}
{% custom_map height=400 %}
// mapgl is Mapbox GL when a token is available, else MapLibre GL.
// container and the access token are provided for you.
const map = new mapgl.Map({
container,
center: [-71.06, 42.36],
zoom: 9
});
// Tiles load asynchronously — signal readiness once painted so PDF/PNG
// export captures a finished map rather than a blank frame.
map.on('idle', () => evidence.ready());
{% /custom_map %}
```
### Plot Evidence data as points
````liquid theme={null}
```sql locations
select 'New York' as name, -74.01 as lng, 40.71 as lat
union all select 'Los Angeles', -118.24, 34.05
union all select 'Chicago', -87.63, 41.88
union all select 'Houston', -95.37, 29.76
union all select 'Denver', -104.99, 39.74
union all select 'Seattle', -122.33, 47.61
union all select 'Miami', -80.19, 25.76
```
{% custom_map height=500 %}
const map = new mapgl.Map({ container, center: [-98, 39], zoom: 3 });
map.on('load', async () => {
const rows = await evidence.query('locations');
map.addSource('pts', {
type: 'geojson',
data: {
type: 'FeatureCollection',
features: rows.map((r) => ({
type: 'Feature',
geometry: { type: 'Point', coordinates: [r.lng, r.lat] },
properties: r
}))
}
});
map.addLayer({ id: 'pts', type: 'circle', source: 'pts', paint: { 'circle-radius': 5 } });
});
{% /custom_map %}
````
### Import a plugin (lasso / draw)
```liquid theme={null}
{% custom_map height=500 %}
// The draw control's buttons are CSS sprites — load its stylesheet or they render blank.
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdn.jsdelivr.net/npm/@mapbox/mapbox-gl-draw@1/dist/mapbox-gl-draw.css';
document.head.appendChild(link);
const { default: MapboxDraw } = await import('https://cdn.jsdelivr.net/npm/@mapbox/mapbox-gl-draw@1/+esm');
const map = new mapgl.Map({ container, center: [-98, 39], zoom: 3 });
map.on('load', () => {
map.addControl(new MapboxDraw({ displayControlsDefault: false, controls: { polygon: true, trash: true } }));
});
{% /custom_map %}
```
## How it works
The body of the tag is JavaScript that draws a map. It runs in a sandboxed iframe with three things already in scope:
* `container` — the element to render the map into.
* `mapgl` — the map library (Mapbox GL, or MapLibre GL when there is no Mapbox token). Write standard Mapbox / MapLibre code against it.
* `evidence` — your page's data and state: run queries, read and write filters, and follow the report theme.
A minimal map:
```js theme={null}
const map = new mapgl.Map({ container, center: [-71.06, 42.36], zoom: 9 });
map.on('idle', () => evidence.ready());
```
From there you write the same code you would anywhere else with Mapbox GL or MapLibre GL: load data with `evidence.query`, add sources and layers, and import any map plugin from a CDN. Because the code runs in an isolated iframe it cannot reach the rest of the page — it interacts with the report only through `evidence`. The full list of what is in scope is below.
## Globals available to your code
The tag body runs as JavaScript inside an isolated iframe with these globals already in scope:
| Global | What it is |
| -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `container` | The element to mount your map into. |
| `mapgl` | The active map library — Mapbox GL when a token is available, otherwise MapLibre GL. Use `new mapgl.Map({ container, ... })` for provider-agnostic code. |
| `maplibregl` | MapLibre GL, always available. |
| `mapboxgl` | Mapbox GL, with the access token already set. `undefined` when there is no token. |
| `provider` / `token` | The resolved provider and Mapbox token. |
| `evidence.query(name)` | Rows for a named query or `sql` block on the page. Returns a promise; page filters are already applied. |
| `evidence.variables` | Values passed via `variables={…}`. Always current; `onVariablesChange` fires on change. |
| `evidence.onVariablesChange(cb)` | Fires when any `variables` value changes. Returns an unsubscribe fn. |
| `evidence.filters` | `get()`, `set(id, value)`, `create(id, value, { column })`, `subscribe(cb)` — read and write page filters. |
| `evidence.subscribe(cb)` | Fires on any state change (variables, filters, or theme). Returns unsubscribe. |
| `evidence.theme` | `{ mode, palette }` — resolved light/dark mode and categorical palette. |
| `evidence.onThemeChange(cb)` | Fires on theme/mode change — swap the basemap style here for dark mode. |
| `evidence.onResize(cb)` | Fires when the block resizes. Call `map.resize()` in the callback. |
| `evidence.onTeardown(cb)` | Register cleanup (e.g. `() => map.remove()`) run before the map re-renders on an edit. |
| `evidence.ready()` | Signal the first render is done, so PDF/PNG export captures a finished frame. |
## Basemaps and keys
You don't need a Mapbox key in Studio. Maps render with a Mapbox basemap and the token is applied for you, so `new mapboxgl.Map({ container })` works with no `accessToken`.
Where no token is configured — such as the open-source CLI or local development — maps use **MapLibre GL** with a free OpenFreeMap basemap instead. `mapgl` points at whichever library is active, so `new mapgl.Map({ container })` works either way.
* `provider="maplibre"` always uses the keyless MapLibre basemap.
* `token="..."` uses your own Mapbox account.
Choose a basemap style for the current theme with `evidence.theme.mode`:
* Mapbox — `mapbox://styles/mapbox/light-v11`, `mapbox://styles/mapbox/dark-v11`
* MapLibre — `https://tiles.openfreemap.org/styles/positron` (light), `https://tiles.openfreemap.org/styles/dark`
Switch the style when the report toggles light/dark:
```js theme={null}
evidence.onThemeChange((t) => map.setStyle(styleFor(t.mode)));
```
## Theming panels and overlays
Custom panels, legends, and controls you add to the map match the report theme with these CSS variables — set for you and updated on light/dark toggle (a sandboxed iframe has no host CSS otherwise, so use these rather than assuming a background):
* `var(--evidence-background)` — surface background
* `var(--evidence-foreground)` — text
* `var(--evidence-muted-foreground)` — secondary text
* `var(--evidence-border)` — borders / dividers
`evidence.theme.mode` (`light` / `dark`) plus `evidence.onThemeChange(cb)` let you swap the basemap style to match dark mode.
## Reacting to page filters and variables
A map and the rest of the page interact in three separate ways. Pick the one that matches what you need:
**1. Filter the map's data by a page input (dropdown, date range).** A filter takes effect where a query *references* it — passing it via `variables=` does not filter anything. Reference it in the SQL of the query the map runs, then `evidence.query()` that query:
```sql theme={null}
-- city_sales (the query the map consumes)
select * from city_sales_all where {{ region_filter.filter }}
```
```js theme={null}
const rows = await evidence.query('city_sales'); // re-runs with a region predicate when the dropdown changes
```
Selecting the dropdown re-runs `city_sales`; call `evidence.query` again from `evidence.subscribe` / `evidence.filters.subscribe` to redraw with the filtered rows.
**2. Read a filter/variable value in map JS (labels, client-side logic — not filtering).** Pass it via `variables=` as a quoted `{{ }}` expression — use `.literal` for the raw value or `.selected` for a SQL-quoted value. This gives you the value in `evidence.variables`; it does not filter any query.
```
{% custom_map height=400 variables={ region="{{ region_filter.literal }}" } %}
const label = evidence.variables.region; // e.g. show the selected region in a badge
evidence.onVariablesChange((v) => { /* re-label */ });
{% /custom_map %}
```
**3. Write a filter back from the map (lasso/click → filter other components or a server re-query).** Use `evidence.filters` and reference the filter in your query's SQL — the large-dataset pattern where you can't ship every row to the browser. A viewport-driven re-query on pan/zoom:
```js theme={null}
const map = new mapgl.Map({ container, center: [-98, 39], zoom: 4 });
async function load() {
const rows = await evidence.query('points_in_view'); // SQL references {{ min_lng.literal }} etc.
// ...update your source with rows...
}
map.on('load', load);
map.on('moveend', () => {
const b = map.getBounds();
evidence.filters.set('min_lng', b.getWest());
evidence.filters.set('max_lng', b.getEast());
evidence.filters.set('min_lat', b.getSouth());
evidence.filters.set('max_lat', b.getNorth());
});
evidence.filters.subscribe(load); // re-query when the bbox filters change
```
Call `evidence.filters.create('min_lng', -130)` once at startup for any filter the page's SQL references before the user interacts.
When you write a selection back as a list of ids, an empty list is ambiguous — it can mean "nothing selected yet" or "selected, matched nothing." Track selection state explicitly rather than checking the array length. And because `id IN ()` is invalid SQL, write a value that matches no rows (e.g. `['__none__']`) rather than an empty array when a selection matches nothing.
## PDF and PNG export
Map tiles load after your setup code returns, so signal completion once the map has painted or export captures a blank frame:
```js theme={null}
map.on('idle', () => evidence.ready());
```
PNG export (image download) reads the WebGL canvas, which requires `preserveDrawingBuffer` — custom\_map turns it on for you, so image export works by default. (PDF export uses a page screenshot and needs nothing extra.) On a very heavy map you can trade image export for a small perf win by opting out:
```js theme={null}
const map = new mapgl.Map({ container, preserveDrawingBuffer: false }); // opt out: PNG blank, PDF still works
```
## Adding plugins
Import any map-ecosystem library from a CDN — mapbox-gl-draw (lasso / box select), deck.gl, turf, h3-js, and so on. They load as normal dynamic imports. A plugin with its own UI (buttons, icons) also needs its stylesheet loaded, or its controls render blank:
```js theme={null}
// load the plugin's CSS too — icons are CSS sprites
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'https://cdn.jsdelivr.net/npm/@mapbox/mapbox-gl-draw@1/dist/mapbox-gl-draw.css';
document.head.appendChild(link);
const { default: MapboxDraw } = await import('https://cdn.jsdelivr.net/npm/@mapbox/mapbox-gl-draw@1/+esm');
map.addControl(new MapboxDraw());
```
mapbox-gl-draw's controls appear only on the Mapbox provider; on MapLibre use `@maplibre/maplibre-gl-draw`.
## Common issues
**Blank map.** If you passed a `token`, check it is valid — an invalid token still loads Mapbox but then fails to fetch tiles. Remove the token to fall back to the keyless MapLibre basemap.
**Export shows a blank map.** Tiles load after your setup code returns, so call `evidence.ready()` once the map has painted: `map.on('idle', () => evidence.ready())`.
**Different basemap locally than when published.** Local development and the CLI often have no Mapbox token, so they use MapLibre while Studio uses Mapbox. Set `PUBLIC_MAPBOX_TOKEN` locally to match, or set `provider` to pin one everywhere. If you rely on a Mapbox-only plugin, pin `provider="mapbox"`.
## Attributes
Title shown above the map
Subtitle shown below the title
Information tooltip text (can only be used with title)
URL to link the info text to (can only be used with info)
Custom text for the info link
Mapbox access token. Not required in Studio — a token is provided for you. Pass one to use your own Mapbox account. With no token, maps use keyless MapLibre.
Force a basemap provider. Defaults to Mapbox when a token is available, otherwise MapLibre.
**Allowed values:**
* `mapbox`
* `maplibre`
Page values to expose to the map as `evidence.variables` — e.g. `variables={ region=$region label="static" }` (Markdoc object syntax: whitespace-separated `key=value`, no commas). Changing a value fires `evidence.onVariablesChange(cb)` / `evidence.subscribe(cb)`.
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
# Date Grain Selector
Source: https://docs.evidence.studio/components/date_grain_selector
Display a selector for date grain options to use in SQL query templates
```liquid theme={null}
{% date_grain_selector
id="time_grain"
default_value="month"
/%}
{% line_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
date_grain={{time_grain}}
/%}
```
## Examples
### Using `date_grain`
```liquid theme={null}
{% date_grain_selector
id="time_grain"
default_value="month"
/%}
{% line_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
date_grain={{time_grain}}
/%}
```
### Using Inline SQL
````liquid theme={null}
{% date_grain_selector
id="time_grain"
default_value="month"
/%}
```sql sales_by_period
select
date_trunc({{time_grain}}, date) as period,
sum(total_sales) as total_sales
from demo.daily_orders
group by 1
order by 1
```
{% line_chart
data="sales_by_period"
x="period"
y="total_sales"
/%}
````
## Attributes
The id of the date grain selector to be used in SQL query templates
Optional array of preset date grain values to show. If not provided, all date grain options will be available.
Default date grain to select on load
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
Text displayed above the selector
Information tooltip text
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Placeholder text displayed when no value is selected
Icon to display
Set the width of this component (in percent) relative to the page width
## Using the Filter Variable
Reference this filter using `{{filter_id}}`. The value returned depends on where you use it.
| Context | Default Property | No Selection | Result |
| ----------------- | ---------------- | ------------ | --------- |
| Inline SQL query | `.selected` | `''` | `'month'` |
| `where` attribute | `.selected` | `''` | `'month'` |
| Text / Markdown | `.literal` | | `month` |
### Available Properties
You can also access specific properties using `{{filter_id.property}}`:
#### .selected
Returns the selected date grain value with quotes. Returns an empty string when no value is selected.
````liquid theme={null}
{% date_grain_selector id="grain" preset_values=["day", "week", "month"] /%}
```sql sales_by_grain
select
toStartOf{{grain.selected}}(date) as period,
sum(sales) as total_sales
from orders
group by period
```
````
**Example value:** `'month'`
#### .literal
Returns the raw unescaped selected value. Use this with the `date_grain` attribute.
````liquid theme={null}
{% date_grain_selector id="grain" preset_values=["day", "week", "month"] /%}
```sql sales_by_grain
select
{{grain.literal}} as period,
sum(sales) as total_sales
from orders
group by period
```
````
**Example value:** `month`
# Delta
Source: https://docs.evidence.studio/components/delta
Display an inline delta value with an up/down indicator
```liquid theme={null}
{% delta
data="demo.daily_orders"
value="sum(total_sales)"
comparison={
compare_vs="target"
target="120000000"
}
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% delta
data="demo.daily_orders"
value="sum(total_sales)"
comparison={
compare_vs="target"
target="120000000"
}
/%}
```
### Semantic metric
```liquid theme={null}
{% delta metric="revenue" comparison={ compare_vs="prior year" } /%}
```
## Attributes
Table or view to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
SQL expression to insert into the SELECT part of the query (e.g., "COUNT(\*)", "SUM(sales)"). Omit when using `metric`.
Format code for the value (e.g., "num", "usd", "pct"). See formatValue documentation for available formats. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Text appearing after the delta (e.g., vs. prev month)
Whether to display as a chip
Comparison configuration object
**Example:**
```
comparison={
compare_vs = "prior year"
display_type = "compared_value"
target = "string"
benchmark = {
agg = "avg"
subject = "store_name"
within = ["region"]
}
hide_pct = true
pct_fmt = "string"
abs_fmt = "string"
down_is_good = true
}
```
**Attributes:**
* compare\_vs: `string` - Type of comparison to perform. Options: prior year (same period last year), prior period (previous period of same duration), target (compare against a target value), benchmark (compare against group average/aggregate)
* **Allowed values:**
* `prior year`
* `prior period`
* `target`
* `benchmark`
* display\_type: `string` - What to display for comparison. Options: compared\_value (comparison period value), abs (absolute change), pct (percentage change). Default: pct
* **Allowed values:**
* `compared_value`
* `abs`
* `pct`
* target: `string` - Target value for target comparison. Can be a column name, aggregation (e.g., "sum(target\_sales)"), or literal value.
* benchmark: `options group`
* **Options:**
* agg: `string` - Aggregation function to apply across benchmark group. Options: avg (average), median, min, max, sum, count, count\_distinct
* **Allowed values:**
* `avg`
* `median`
* `min`
* `max`
* `sum`
* `count`
* `count_distinct`
* subject: `string` - Column or expression that defines individual entities in the benchmark (e.g., "store\_name", "customer\_id"). Required for single-value components.
* value: `string` - Optional column or expression to use for benchmark calculation. If not specified, uses the main value column. Useful if you have a pre-aggregated benchmark table for RLS reasons.
* within: `array of strings` - Dimension columns to group the benchmark by (e.g., \["region"]). Leave empty for dataset-wide benchmark.
* where: `string` - SQL WHERE clause to filter which entities are included in the benchmark
* exclude\_self: `boolean` - Exclude the current row from its own benchmark calculation (table context only). Default: false
* hide\_pct: `boolean` - Hide the percentage change line in comparison tooltips
* pct\_fmt: `string` - Format code for percentage values in comparison tooltips
* abs\_fmt: `string` - Format code for absolute values in comparison tooltips
* down\_is\_good: `boolean` - Whether a downward trend is considered positive
Whether to show the value
Whether to show the delta symbol
Position of the delta symbol relative to the value
**Allowed values:**
* `left`
* `right`
Range \[min, max] for neutral values. Use null for infinity (e.g., \[null, 0] means anything ≤ 0 is neutral)
IDs of filters to apply to the query
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Set the width of this component (in percent) relative to the page width
# Details
Source: https://docs.evidence.studio/components/details
The details component
```liquid theme={null}
{% details
title="Metric Definitions"
%}
**Sales:** includes sales of all core products in all regions
**Sales Growth:** YoY growth in sales
{% /details %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% details
title="Metric Definitions"
%}
**Sales:** includes sales of all core products in all regions
**Sales Growth:** YoY growth in sales
{% /details %}
```
## Attributes
Title of the details section
Whether the details section is open
Set the width of this component (in percent) relative to the page width
# Dimension
Source: https://docs.evidence.studio/components/dimension
Add a dimension to a table, including date filtering, date grains, formatting, and more
```liquid theme={null}
{% table data="demo.daily_orders" %}
{% dimension value="category" /%}
{% dimension value="date" date_grain="month" title="Month" /%}
{% /table %}
```
## Examples
### Table with Dimensions
```liquid theme={null}
{% table data="demo.daily_orders" %}
{% dimension value="category" /%}
{% dimension value="date" date_grain="month" title="Month" /%}
{% /table %}
```
### With Image
```liquid theme={null}
{% table data="demo.daily_orders" %}
{% dimension value="category" image="image_url" /%}
{% measure value="sum(total_sales)" /%}
{% /table %}
```
### With Link
```liquid theme={null}
{% table data="demo.daily_orders" %}
{% dimension value="category" link="concat('https://www.google.com/search?q=', category)" /%}
{% measure value="sum(total_sales)" /%}
{% /table %}
```
### With Logo
```liquid theme={null}
{% table data="sales" %}
{% dimension value="vendor" logo="domain" /%}
{% measure value="sum(amount)" /%}
{% /table %}
```
### Conditional Colors
```liquid theme={null}
{% table data="demo.daily_orders" %}
{% dimension value="category" conditional_colors="case when sum(total_sales) > 20000000 then '#22c55e' when sum(total_sales) > 10000000 then '#f59e0b' else '#ef4444' end" /%}
{% measure value="sum(total_sales)" fmt="usd1m" /%}
{% /table %}
```
## Attributes
**Allowed values:**
* `left`
* `center`
* `right`
Whether to allow content in this dimension column to wrap across multiple lines
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Whether to hide this column from the table display. Hidden columns are still included in queries and can be referenced by other columns.
Whether to render the dimension value as HTML
Image display options (used when image prop is set)
**Attributes:**
* height: `number` - Height of the image in pixels
* width: `number` - Width of the image in pixels
* alt: `string` - Alt text for the image
* hide\_label: `boolean` - Whether to hide the text label and show only the image
Column name or SQL expression containing the image URL for this dimension
Column name or SQL expression containing the domain to look up a company logo for this dimension
Logo display options (used when logo prop is set)
**Example:**
```
logo_options={
size = "sm"
grayscale = true
hide_label = true
}
```
**Attributes:**
* size: `string` - Logo size: sm, base, lg, xl
* **Allowed values:**
* `sm`
* `base`
* `lg`
* `xl`
* grayscale: `boolean` - Display logo in grayscale
* hide\_label: `boolean` - Whether to hide the text label and show only the logo
Column name or SQL expression containing the URL for linking this dimension
Static text to use as the link label instead of the cell content
Whether to open the link in a new tab
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
Format code for displaying dimension values (e.g., "yyyy" for years, "mmm" for months)
Sort direction for this dimension column. When specified, the table will be sorted by this column.
**Allowed values:**
* `asc`
* `desc`
Group name for this column. Columns with matching group names will be visually grouped under a shared header.
Whether to repeat this dimension value on every row. When true, the value is displayed on every row even when it is the same as the row above. Overrides the table-level repeat\_values setting for this dimension.
SQL expression that returns color values for each row. Used to conditionally color dimension cells based on data (e.g., "case when count(\*) > 0 then '#22c55e' else null end").
## Allowed Parents
* [table](/components/table)
# Dimension Grid
Source: https://docs.evidence.studio/components/dimension_grid
Display an interactive grid of dimension columns with aggregated metrics and bar visualizations for filtering
```liquid theme={null}
{% dimension_grid
id="product_filter"
data="demo.daily_orders"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% dimension_grid
id="product_filter"
data="demo.daily_orders"
/%}
```
### With Explicit Dimensions and Metric
```liquid theme={null}
{% dimension_grid
id="sales_filter"
data="orders"
dimensions=["category", "region"]
metric="sum(sales)"
fmt="usd"
limit=5
/%}
```
### Using Filter in Query
````liquid theme={null}
{% dimension_grid id="order_filter" data="orders" /%}
```sql filtered_orders
select * from orders
where {{order_filter.filter}}
```
````
## Attributes
The id of the dimension grid to use in a `filters` prop
Name of the table to query
Array of column names to display as dimensions. If not provided, auto-detects string columns.
SQL aggregation expression (default: count(\*))
Label displayed above the metric values
Format code for the metric values (e.g., "num0", "usd", "pct1"). See [Value Formatting](/core-concepts/value-formatting) for available formats.
Maximum number of values to show per dimension (default: 10)
Allow multiple selections per dimension (default: true)
Array of filter IDs to apply when querying dimension values
SQL WHERE clause to filter data
Title displayed above the dimension grid
Subtitle displayed below the title
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Set the width of this component (in percent) relative to the page width
## Using the Filter Variable
Reference this filter using `{{filter_id}}`. The value returned depends on where you use it.
| Context | Default Property | No Selection | Result |
| ------- | ---------------- | ------------ | ------ |
### Available Properties
You can also access specific properties using `{{filter_id.property}}`:
#### .filter
Returns a complete SQL filter expression combining all dimension selections. Returns `true` when no values are selected.
````liquid theme={null}
{% dimension_grid id="dim_filter" data="orders" /%}
```sql filtered_orders
select * from orders
where {{dim_filter.filter}}
```
````
#### .selected
Returns an object with dimension names as keys and selected values as arrays. Useful for accessing individual dimension selections.
```liquid theme={null}
{% dimension_grid id="dim_filter" data="orders" dimensions=["category", "region"] /%}
Selected categories: {{dim_filter.category}}
Selected regions: {{dim_filter.region}}
```
#### .literal
Returns a human-readable summary of all selections.
```liquid theme={null}
{% dimension_grid id="dim_filter" data="orders" /%}
Active filters: {{dim_filter.literal}}
```
# Download
Source: https://docs.evidence.studio/components/download
A button to download data as an Excel file, supports up to 500,000 row downloads via the limit attribute.
```liquid theme={null}
{% download data="demo.daily_orders" /%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% download data="demo.daily_orders" /%}
```
### Custom Label and Filename
```liquid theme={null}
{% download
data="demo.daily_orders"
label="Export Orders"
filename="daily_orders_export"
/%}
```
### With Variant
```liquid theme={null}
{% download
data="demo.daily_orders"
label="Export Data"
variant="primary"
/%}
```
### With Large Limit
```liquid theme={null}
{% download
data="demo.daily_orders"
label="Download Recent Orders"
limit=50000
/%}
```
## Attributes
Table or view to download
Text displayed on the download button
Name of the downloaded file (without extension)
Button style variant
**Allowed values:**
* `default`
* `primary`
* `destructive`
* `secondary`
* `ghost`
* `link`
IDs of filters to apply to the query
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
# Dropdown
Source: https://docs.evidence.studio/components/dropdown
Display a dropdown with distinct values from a database column to use in filters
```liquid theme={null}
{% dropdown
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
filters=["category_filter"]
date_grain="month"
/%}
```
## Examples
### Using `filters`
```liquid theme={null}
{% dropdown
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
filters=["category_filter"]
date_grain="month"
/%}
```
### Using `where`
```liquid theme={null}
{% dropdown
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
{% bar_chart
data="demo.daily_orders"
x="date"
y="sum(total_sales)"
where="category = {{category_filter}}"
date_grain="month"
/%}
```
### Using Inline SQL
````liquid theme={null}
{% dropdown
id="category_filter"
data="demo.daily_orders"
value_column="category"
/%}
```sql filtered_orders
select * from demo.daily_orders
where category = {{category_filter}}
```
{% table data="filtered_orders" /%}
````
### Using `date_range`
```liquid theme={null}
{% dropdown
id="category_filter"
data="demo.daily_orders"
value_column="category"
date_range={
date="date"
range="last 12 months"
}
/%}
```
### Cascading Dropdowns (Linked Filters)
```liquid theme={null}
{% dropdown
id="category"
data="demo.order_details"
value_column="category"
title="Category"
/%}
{% dropdown
id="item"
data="demo.order_details"
value_column="item_name"
title="Item"
filters=["category"]
/%}
{% table
data="demo.order_details"
filters=["category", "item"]
/%}
```
## Attributes
The id of the dropdown to be used in a `filters` prop
Name of the table to query
Array of filter IDs to apply when querying for dropdown options. Use this to create cascading/linked dropdowns where selecting a value in one dropdown narrows the available options in this dropdown.
Column name to use as the value for each option, and the column to filter by when this dropdown's `id` is used in the `filters` prop of a chart
Column name to use as the label for each option
List of options to display in the dropdown
Text displayed above the dropdown
Information tooltip text
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Icon to display in the dropdown trigger
**Allowed values:**
* `trending-up`
* `trending-down`
* `clock`
* `calendar`
* `check`
* `x`
* `info`
* `alert-circle`
* `help-circle`
* `eye`
* `eye-off`
* `user`
* `users`
* `settings`
* `cog`
* `plus`
* `minus`
* `up`
* `down`
* `right`
* `left`
* `star`
* `heart`
* `search`
* `file`
* `file-text`
* `home`
* `mail`
* `filter`
* `share`
* `bell`
* `trash`
* `credit-card`
* `globe`
* `key`
* `croissant`
* `map`
* `rotate`
* `rewind`
* `bank`
* `receipt`
* `activity`
* `chart-column`
* `chart-pie`
* `chart-no-axes-combined`
* `goal`
* `rocket`
* `trophy`
* `apple`
* `cookie`
* `donut`
* `beef`
* `cake`
* `soup`
* `utensils`
* `milk`
* `nut`
* `pyramid`
* `triangle`
* `arrow-down`
* `arrow-left`
* `arrow-right`
* `arrow-up`
* `chevron-down`
* `chevron-left`
* `chevron-right`
* `chevron-up`
* `chevrons-down`
* `chevrons-left`
* `chevrons-right`
* `chevrons-up`
* `menu`
* `external-link`
* `check-circle`
* `x-circle`
* `edit`
* `trash-2`
* `copy`
* `save`
* `download`
* `upload`
* `send`
* `refresh`
* `redo`
* `undo`
* `folder`
* `folder-open`
* `image`
* `file-image`
* `user-plus`
* `user-minus`
* `user-check`
* `lock`
* `unlock`
* `log-in`
* `log-out`
* `message-square`
* `message-circle`
* `phone`
* `phone-call`
* `bell-off`
* `video`
* `video-off`
* `play`
* `pause`
* `stop`
* `skip-back`
* `skip-forward`
* `volume`
* `volume-1`
* `volume-2`
* `volume-off`
* `volume-x`
* `bookmark`
* `tag`
* `link`
* `unlink`
* `share-2`
* `alert-triangle`
* `loader`
* `more-vertical`
* `more-horizontal`
* `grid`
* `list`
* `maximize`
* `minimize`
* `zoom-in`
* `zoom-out`
* `thumbs-up`
* `thumbs-down`
* `shopping-cart`
* `dollar-sign`
* `camera`
* `printer`
* `monitor`
* `smartphone`
* `laptop`
* `calculator`
* `cloud-sun-rain`
* `sun-snow`
* `thermometer-sun`
* `thermometer-snowflake`
* `cloudy`
* `cloud-rain-wind`
* `cloud-rain`
* `wind`
* `sun`
* `cloud-snow`
* `thermometer`
* `cloud-drizzle`
* `cloud-sun`
* `cloud`
* `cloud-lightning`
* `snowflake`
* `flame`
* `atom`
* `fuel`
* `magnet`
* `factory`
* `tree-deciduous`
* `waypoints`
* `plug`
* `dam`
* `battery`
Initial selected value(s)
Automatically select the first option when the component loads
For a multi-select dropdown, pre-selects the first N options (after `order` is applied) when the component loads. Generalizes `select_first`. Does not limit the option list and has no effect when `multiple=false`.
Placeholder text displayed when no value is selected
Includes a search input within the dropdown menu
Allows multiple selections
Includes a clear button to unselect the selected value(s)
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Set the width of this component (in percent) relative to the page width
## Using the Filter Variable
Reference this filter using `{{filter_id}}`. The value returned depends on where you use it.
The examples below show values for three scenarios:
* **No selection**
* **Single select:** "Electronics" selected
* **Multi select:** "Sports" and "Home" selected (when `multiple=true`)
| Context | Default Property | No Selection | Single Select | Multi Select |
| ----------------- | ---------------- | ------------ | --------------- | -------------------- |
| Inline SQL query | `.selected` | `''` | `'Electronics'` | `('Sports', 'Home')` |
| `where` attribute | `.selected` | `''` | `'Electronics'` | `('Sports', 'Home')` |
| Text / Markdown | `.literal` | | `Electronics` | `Sports, Home` |
### Available Properties
You can also access specific properties using `{{filter_id.property}}`:
#### .filter
Returns a complete SQL filter expression ready to use in WHERE clauses. Returns `true` when no value is selected.
````liquid theme={null}
{% dropdown id="category_filter" data="products" value_column="category" /%}
```sql filtered_products
select * from products
where {{category_filter.filter}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | -------------------------- | -------------------------------- |
| `true` | `category = 'Electronics'` | `category IN ('Sports', 'Home')` |
#### .selected
Returns the selected value(s) wrapped in quotes, suitable for SQL comparisons. Returns an empty string when no value is selected.
````liquid theme={null}
{% dropdown id="category_filter" data="products" value_column="category" /%}
```sql products_by_category
select * from products
where category = {{category_filter.selected}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | --------------- | -------------------- |
| `''` | `'Electronics'` | `('Sports', 'Home')` |
#### .literal
Returns the raw unescaped selected value(s), useful for display in text or dynamic column selection.
````liquid theme={null}
{% dropdown id="sort_column" data="products" value_column="column_name" /%}
```sql dynamic_sort
select * from products
order by {{sort_column.literal}}
```
````
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | -------------- |
| \`\` | `Electronics` | `Sports, Home` |
#### .label
Returns the display label for the selected option(s). Falls back to the value if no label is defined.
```liquid theme={null}
{% dropdown id="category_filter" %}
{% option value="Electronics" label="Electronics" /%}
{% option value="Sports" label="Sports" /%}
{% option value="Home" label="Home" /%}
{% /dropdown %}
Selected: {{category_filter.label}}
```
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | -------------- |
| \`\` | `Electronics` | `Sports, Home` |
#### .fmt
Returns the format string associated with the selected option. For multiple selections, returns the first format.
```liquid theme={null}
{% dropdown id="metric_selector" %}
{% option value="revenue" label="Revenue" fmt="usd" /%}
{% option value="growth_rate" label="Growth Rate" fmt="pct1" /%}
{% /dropdown %}
{% big_value data={metrics} value=value fmt={{metric_selector.fmt}} /%}
```
| No Selection | Single Select | Multi Select |
| ------------ | ------------- | ------------ |
| \`\` | `usd` | `usd` |
## Allowed Children
* [option](/components/option)
# Else
Source: https://docs.evidence.studio/components/else
If prior conditional blocks do not pass, the contents of the else block are rendered.
```liquid theme={null}
{% if data="demo.daily_orders" %}
If Content
{% /if %}
{% else %}
Else Content
{% /else %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% if data="demo.daily_orders" %}
If Content
{% /if %}
{% else %}
Else Content
{% /else %}
```
## Attributes
This component has no attributes.
# Else If
Source: https://docs.evidence.studio/components/else_if
If prior conditional blocks do not pass, conditionally render the contents based on whether rows are returned by the query.
```liquid theme={null}
{% if data="demo.daily_orders" condition="no_rows" %}
If Content
{% /if %}
{% else_if data="demo.daily_orders" %}
Else If Content
{% /else_if %}
```
## Examples
### Basic Usage
```liquid theme={null}
{% if data="demo.daily_orders" condition="no_rows" %}
If Content
{% /if %}
{% else_if data="demo.daily_orders" %}
Else If Content
{% /else_if %}
```
## Attributes
Table or view to query
IDs of filters to apply to the query
Set to "no\_rows" to render children only if the query returns no rows. Set to "has\_rows" (or omit) to render if query returns rows.
**Allowed values:**
* `no_rows`
* `has_rows`
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
# Fence
Source: https://docs.evidence.studio/components/fence
Display a code block
````liquid theme={null}
```language query_name
content
```
````
## Examples
### Basic Usage
````liquid theme={null}
```language query_name
content
```
````
### Define a SQL query
````liquid theme={null}
```sql electronics_orders
SELECT * FROM demo.daily_orders WHERE category = 'Electronics'
```
{% table data="electronics_orders" /%}
````
## Attributes
The language of the code block
The content of the code block
Optional name for the code block. If provided and language is "sql", this will register the query as an inline query that can be used by other components. Inline queries must be defined at the top level of the page, not inside other components (e.g. tabs, accordion, details).
Set the width of this component (in percent) relative to the page width
# Filter Bar
Source: https://docs.evidence.studio/components/filter_bar
Renders a floating bar of filters at the top or bottom of your page
```liquid theme={null}
{% filter_bar %}
...
{% /filter_bar %}
```
## Attributes
This component has no attributes.
## Allowed Children
* [dropdown](/components/dropdown)
* [table\_filter](/components/table_filter)
* [date\_grain\_selector](/components/date_grain_selector)
* [comparison\_selector](/components/comparison_selector)
* [range\_calendar](/components/range_calendar)
* [button\_group](/components/button_group)
# Funnel Chart
Source: https://docs.evidence.studio/components/funnel_chart
Display a funnel chart showing conversion rates through stages
```liquid theme={null}
{% funnel_chart
data="demo.daily_orders"
category="category"
value="sum(transactions)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% funnel_chart
data="demo.daily_orders"
category="category"
value="sum(transactions)"
/%}
```
### Funnel Chart with Custom Styling
```liquid theme={null}
{% funnel_chart
data="demo.daily_orders"
category="category"
value="sum(transactions)"
align="left"
label_position="outside"
gap=5
title="Styled Funnel"
/%}
```
### Funnel Chart with Custom Colors
```liquid theme={null}
{% funnel_chart
data="demo.daily_orders"
category="category"
value="sum(transactions)"
chart_options={
color_palette = ["#0d0887", "#6300a7", "#a62098", "#d5546e", "#f68d45", "#fcd225", "#f0f921"]
}
/%}
```
## Attributes
Name of the table to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Column name for funnel stages/categories
Column name for values. Omit when using `metric`.
Title to display above the chart
Subtitle to display below the title
Information tooltip text (can only be used with title)
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Format for values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Show a legend above the chart (stages are labeled directly on the funnel by default)
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Label position: auto places labels inside each stage, moving them beside stages that are too narrow; outside places all labels in a rail beside the chart (left of the chart unless the funnel is right-aligned)
**Allowed values:**
* `auto`
* `inside`
* `outside`
* `center`
Chart configuration options
**Example:**
```
chart_options={
color_palette = ["value1", "value2"]
}
```
**Attributes:**
* color\_palette: `array of strings`
Funnel alignment
**Allowed values:**
* `center`
* `left`
* `right`
Show percentages relative to first stage
Minimum size of funnel stages
Maximum size of funnel stages
Gap between funnel stages in pixels
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into the chart series. Use for series-level styling the structured props do not expose.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
}
```
# Heat Grid
Source: https://docs.evidence.studio/components/heat_grid
Display a grid of color-coded cells based on metric thresholds
```liquid theme={null}
{% heat_grid
data="appointments"
dimension="province"
value="avg(wait_time)"
thresholds=[60, 90]
units="MIN"
lower_is_better=true
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% heat_grid
data="appointments"
dimension="province"
value="avg(wait_time)"
thresholds=[60, 90]
units="MIN"
lower_is_better=true
/%}
```
## Attributes
Table or view to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
Column for cell labels (e.g., province)
SQL aggregation expression for the metric (e.g., avg(wait\_time)). Omit when using `metric`.
Two numeric thresholds creating 3 color zones: \[low, high]. Values below low are zone 1, between low and high are zone 2, at or above high are zone 3.
Units label shown below the value in each cell (e.g., "MIN")
Format code for the metric value. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Component title
If true, low values are green and high values are red. Default (false) means high values are green.
If true, removes gaps and borders between cells and applies a single border radius to the outer grid.
IDs of filters to apply to the query
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
# Heatmap
Source: https://docs.evidence.studio/components/heatmap
Display a heatmap chart with color-coded cells
```liquid theme={null}
{% heatmap
data="demo.daily_orders"
x="date"
x_date_grain="year"
y="category"
value="sum(total_sales)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% heatmap
data="demo.daily_orders"
x="date"
x_date_grain="year"
y="category"
value="sum(total_sales)"
/%}
```
### With Custom Colors
```liquid theme={null}
{% heatmap
data="demo.daily_orders"
x="date"
x_date_grain="year"
y="category"
value="sum(total_sales)"
title="Sales Intensity by Year and Category"
chart_options={
color_scale = ["#f7fafc", "#e2e8f0", "#cbd5e0", "#a0aec0", "#718096", "#4a5568", "#2d3748"]
}
/%}
```
## Attributes
Name of the table to query. Omit when using `metric`.
Semantic metric name to display, from metrics/\*.yaml. Use instead of the raw data/value/x/y attributes.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
Column name for x-axis categories
Column name for y-axis categories
Title to display for the x-axis
Title to display for the y-axis
Column name for cell values. Omit when using `metric`.
Title to display above the chart
Subtitle to display below the title
Info text to display in a tooltip next to the title. Can only be used with the title prop.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Format for values (defaults to `num`, or the metric format in metric mode). See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for x axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Sort order for x axis categories (asc or desc)
**Allowed values:**
* `asc`
* `desc`
Sort order for y axis categories (asc or desc)
**Allowed values:**
* `asc`
* `desc`
Sort categories by total value (asc or desc). Applies to the first axis without explicit sort.
**Allowed values:**
* `asc`
* `desc`
Show color scale legend
Show borders around heatmap cells
Chart configuration options
**Example:**
```
chart_options={
color_scale = ["value1", "value2"]
color_palette = ["value1", "value2"]
}
```
**Attributes:**
* color\_scale: `array of strings` - Array of hex colors for the heatmap gradient. A single-color array auto-expands to \[background, color].
* color\_palette: `array of strings` - Deprecated. Use `color_scale`.
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into the chart series. Use for series-level styling the structured props do not expose.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
}
```
# Heatmap Layer
Source: https://docs.evidence.studio/components/heatmap_layer
Add a heatmap layer to a map showing density of lat/lng coordinates
```liquid theme={null}
{% map %}
{% heatmap_layer
data="events"
lat="latitude"
lng="longitude"
/%}
{% /map %}
```
## Examples
### Basic Heatmap
```liquid theme={null}
{% map %}
{% heatmap_layer
data="events"
lat="latitude"
lng="longitude"
/%}
{% /map %}
```
### Weighted Heatmap
```liquid theme={null}
{% map %}
{% heatmap_layer
data="sales"
lat="latitude"
lng="longitude"
weight="sum(revenue)"
/%}
{% /map %}
```
### Custom Color Palette
```liquid theme={null}
{% map %}
{% heatmap_layer
data="incidents"
lat="latitude"
lng="longitude"
color_scale=["#ffffb2", "#fecc5c", "#fd8d3c", "#f03b20", "#bd0026"]
/%}
{% /map %}
```
### Adjusted Radius and Intensity
```liquid theme={null}
{% map %}
{% heatmap_layer
data="visits"
lat="latitude"
lng="longitude"
weight="visit_count"
radius=50
intensity=2
/%}
{% /map %}
```
## Attributes
Name of the table to query
Array of filter IDs to apply
Column name for latitude values
Column name for longitude values
Column or expression for weighting points in the heatmap (e.g., "sum(sales)"). Higher values create more intense heat
Base radius of influence for each point in pixels (adjusts with zoom)
Intensity multiplier for the heatmap. Higher values create more pronounced heat
Opacity of the heatmap layer (0-1)
Array of colors for the heatmap gradient, from lowest to highest density. A single-color array auto-expands to \[background, color]. Defaults to the theme color scale.
Deprecated. Use `color_scale`.
Zoom range \[min, max] where this layer is visible (e.g., \[0, 8] shows layer from zoom 0 to 8)
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
## Allowed Parents
* [map](/components/map)
# Histogram
Source: https://docs.evidence.studio/components/histogram
Display a histogram chart showing the distribution of values in a column.
```liquid theme={null}
{% histogram
data="demo.daily_orders"
value="transactions"
bin_count=30
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% histogram
data="demo.daily_orders"
value="transactions"
bin_count=30
/%}
```
## Attributes
Name of the table to query
SQL expression for the values to create histogram for
Column name to group data by series
Chart configuration options
**Example:**
```
chart_options={
color_palette = ["value1", "value2"]
}
```
**Attributes:**
* color\_palette: `array of strings`
Number of bins for the histogram (takes precedence over bin\_width)
Width of each bin (ignored if bin\_count is specified)
Format for the column values displayed in bin ranges. See [Value Formatting](/core-concepts/value-formatting) for available formats.
IDs of filters to apply to the query
Title to display above the histogram
Subtitle to display below the title
Info text to display in a tooltip next to the title. Can only be used with the title prop.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Show legend
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `graphic`, `visualMap`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For overrides scoped to the data series, use `echarts_series_options`.
**Example:**
```
echarts_options={
tooltip={ position="top" }
graphic=[{ type="text" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into the chart series. Use for series-level styling the structured props do not expose.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
}
```
# Horizontal Bar Chart
Source: https://docs.evidence.studio/components/horizontal_bar_chart
Display a horizontal bar chart
```liquid theme={null}
{% horizontal_bar_chart
data="demo.daily_orders"
y="category"
x="sum(total_sales)"
/%}
```
## Examples
### Basic Usage
```liquid theme={null}
{% horizontal_bar_chart
data="demo.daily_orders"
y="category"
x="sum(total_sales)"
/%}
```
## Attributes
Name of the table to query. Required unless every child series uses `metric="..."` — metric children resolve their own base from the metric view.
IDs of filters to apply to the query
Filter data to a time period. `date_range` is an OBJECT with `range` (the period) and optionally `date` (which column to filter on when the table has more than one). Shape: `date_range={ range="last 12 months" date="order_date" }`. `range` accepts predefined values (`last 7 days`, `month to date`), dynamic patterns (`Last 90 days`), custom windows (`2020-01-01 to 2023-03-01`), or partial ranges (`from 2020-01-01`, `until 2023-03-01`). Pass a plain string for `range` — the whole object is NOT a string.
**Example:**
```
date_range={
range = "today"
date = "string"
}
```
**Attributes:**
* range: `string` - Time period to filter. Use presets like 'last 7 days', dynamic patterns like 'Last 90 days', custom ranges like '2020-01-01 to 2023-03-01', or partial ranges like 'from 2020-01-01'.
* **Allowed values:**
* `today`
* `yesterday`
* `last 7 days`
* `last 30 days`
* `last 3 months`
* `last 6 months`
* `last 12 months`
* `previous week`
* `previous month`
* `previous quarter`
* `previous year`
* `this week`
* `this month`
* `this quarter`
* `this year`
* `next week`
* `next month`
* `next quarter`
* `next year`
* `week to date`
* `month to date`
* `quarter to date`
* `year to date`
* `all time`
* date: `string` - Date column to filter on. Required when the data has multiple date columns.
Bucket dates into a grain. Pass the raw date column as `x` and the chart truncates and groups for you. Temporal grains (`day`, `week`, `month`, `quarter`, `year`, `hour`) preserve the year — use for time-series. Seasonality grains (`day of week`, `day of month`, `day of year`, `week of year`, `month of year`, `quarter of year`) collapse across years — use for cyclical patterns like "which month sells most regardless of year".
**Allowed values:**
* `day`
* `week`
* `month`
* `quarter`
* `year`
* `hour`
* `day of week`
* `day of month`
* `day of year`
* `week of year`
* `month of year`
* `quarter of year`
How to handle missing data points. "connect" auto-connects points (default), "gaps" shows visual breaks, "zero" fills with zeros.
**Allowed values:**
* `connect`
* `gaps`
* `zero`
Column name for x-axis (value, extends horizontally)
Format for x values. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Format for y values and axis labels. See [Value Formatting](/core-concepts/value-formatting) for available formats.
Column name for series
Column name for individual point labels displayed at the top of the tooltip
Title to display above the component
Subtitle to display below the title
Information tooltip text (can only be used with title). Displays an info icon next to the title.
URL to link the info text to (can only be used with info)
Create a custom link title for the info link, placed after the info text (can only be used with info\_link)
Time in seconds between automatic data refreshes (minimum 30). Overrides the page-level auto-refresh setting for this component.
Custom SQL WHERE condition to apply to the query. For date filters, use date\_range instead.
Custom SQL HAVING condition to apply to the query after GROUP BY
Maximum number of rows to return from the query. Note: When used with tables, limit will disable subtotals to prevent incomplete subtotal rows.
Column name(s) with optional direction (e.g. "column\_name", "column\_name desc")
Custom SQL QUALIFY condition to filter windowed results
Set the width of this component (in percent) relative to the page width
Set a fixed height for the chart in pixels
Link this chart to others sharing the same id, syncing their tooltips, axis-pointer, and zoom
Configure the y-axis
**Example:**
```
y_axis_options={
title = "string"
title_position = "top"
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
interval = 0
}
```
**Attributes:**
* title: `string`
* title\_position: `string` - Position of the axis title. "top" places it horizontally at the top, "side" places it vertically along the axis. Defaults to "side" for 100% stacked charts, "top" otherwise.
* **Allowed values:**
* `top`
* `side`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
Configure the x-axis
**Example:**
```
x_axis_options={
title = "string"
show_title = true
label_wrap = true
ticks = true
baseline = true
labels = true
gridlines = true
min = 0
max = 0
fit_to_data = true
min_interval = "year"
max_interval = "year"
interval = 0
label_rotate = 0
title_arrow = true
max_label_length = 0
}
```
**Attributes:**
* title: `string`
* show\_title: `boolean` - When `true`, renders the auto-derived axis title (the x column name) below the chart. Ignored when `title` is set explicitly. Defaults to `false` — auto-derived column-name titles usually read as visual noise and the axis labels speak for themselves.
* label\_wrap: `boolean`
* ticks: `boolean`
* baseline: `boolean`
* labels: `boolean` - Show/hide axis labels
* gridlines: `boolean` - Show/hide gridlines
* min: `number` - Minimum value for this axis (number for numeric axes, date string for date axes)
* max: `number` - Maximum value for this axis (number for numeric axes, date string for date axes)
* fit\_to\_data: `boolean` - Fit the axis to the data instead of including 0. Defaults to true for numeric x-axes, false otherwise.
* min\_interval: `string` - Minimum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* max\_interval: `string` - Maximum interval between axis ticks for time-based axes. This option is a suggestion, the actual interval may differ.
* **Allowed values:**
* `year`
* `quarter`
* `month`
* `week`
* `day`
* `hour`
* interval: `number` - Interval between axis ticks for numeric axes. This option is a suggestion, the actual interval may differ.
* label\_rotate: `number` - Rotation angle of axis label in degrees. Positive values rotate clockwise, negative values rotate counter-clockwise.
* title\_arrow: `boolean` - Show/hide the arrow (→) on the axis title
* max\_label\_length: `number` - Maximum character length for axis labels. Labels exceeding this length will be truncated with an ellipsis. Defaults to 20 characters when labels are rotated.
Show legend. Studio's built-in legend renders a compact color swatch + series name. For chart-wide style overrides that need the legend to reflect them precisely (line width, custom symbols, richer styling), set `legend=false` and provide `legend={ show=true ... }` inside `echarts_options` to use ECharts' native legend instead.
Position of the legend (top or bottom)
**Allowed values:**
* `top`
* `bottom`
Array of series names to define the order of series in the chart and legend. Series not in the array will appear after the ordered ones.
Additional chart configuration options
**Example:**
```
chart_options={
color_palette = ["value1", "value2"]
series_colors = {
"key1" = "value1"
"key2" = "value2"
}
top_padding = 0
}
```
**Attributes:**
* color\_palette: `array of strings`
* series\_colors: `map of key-value pairs`
* top\_padding: `number` - Additional padding (in px) above the chart area to prevent labels from being cut off
Raw [ECharts options](https://echarts.apache.org/en/option.html) deep-merged over the chart's final configuration. Use for anything the structured props do not expose — `dataZoom`, `visualMap`, `graphic`, tooltip styling, and so on. Partial overrides win key-by-key without clobbering Studio's computed siblings. For per-series overrides, use `echarts_series_options` or the per-series `echarts_options` on a `line`/`bar`/etc. child.
**Example:**
```
echarts_options={
tooltip={ position="top" }
dataZoom=[{ type="slider" }]
}
```
Raw [ECharts series options](https://echarts.apache.org/en/option.html#series) deep-merged into every data series in the chart. Use when the same override should apply to all series. Skips reference lines/areas/points. For a single series, set `echarts_options` on the series child instead.
**Example:**
```
echarts_series_options={
itemStyle={ borderRadius=8 }
markLine={ data=[{ type="average" }] }
}
```
Column name for y-axis (category, extends vertically)
Sort order for y-axis categories. Options: `asc` (alphabetical), `desc` (reverse alphabetical), `data` (preserve query order), or an array for custom order like `["A", "B", "C"]`
**Allowed values:**
* `asc`
* `desc`
* `data`
Label each point in the series with its value
**Example:**
```
data_labels={
position = "above"
fmt = "date"
size = 0
distance = 0
rotate = 0
color = "string"
border_color = "string"
show_overlap = true
}
```
**Attributes:**
* position: `string` - Position the label relative to its data point
* **Allowed values:**
* `above`
* `below`
* `left`
* `right`
* `middle`
* fmt: `string` - Format the label value. Defaults to series or axis fmt.
* **Allowed values:** See [Value Formatting](/core-concepts/value-formatting) for all available formats.
* size: `number` - Font size in px
* distance: `number` - How far the label is from the data point
* rotate: `number` - Rotate each label (degrees)
* color: `string` - Change the text color of the labels
* border\_color: `string` - Change the border color surrounding text labels, defaults to chart background
* show\_overlap: `boolean` - Show labels for every point even when they overlap
Extra columns to include in the tooltip on hover. Each entry is `{ value, label?, fmt?, color_by_sign?, down_is_good? }`. See the [tooltip fields guide](/components/tooltip-fields) for examples.
**Attributes:**
* color: `string`
* opacity: `number` - Between 0 and 1
Whether to stack the bars
## Allowed Children
* [reference\_line](/components/reference_line)
* [reference\_area](/components/reference_area)
* [reference\_point](/components/reference_point)
# Html
Source: https://docs.evidence.studio/components/html
Build custom, interactive visualizations with HTML and JavaScript — D3, Chart.js, Observable Plot, or any JS library. A fully supported way to create bespoke charts, diagrams, and widgets the built-in components don't cover.
````liquid theme={null}
```sql daily_orders
select 'Mon' as day, 120 as orders union all
select 'Tue', 180 union all
select 'Wed', 90
```
{% html %}
{% /html %}
````
## Examples
### Basic Usage
````liquid theme={null}
```sql daily_orders
select 'Mon' as day, 120 as orders union all
select 'Tue', 180 union all
select 'Wed', 90
```
{% html %}
{% /html %}
````
### Responsive D3 chart from a CDN
```liquid theme={null}
{% html %}
{% /html %}
```
## The evidence API
Every script inside the block can reach a single `evidence` object. It is the only bridge to the page — data, variables, theme, filters, and lifecycle all hang off it.
| Member | What it does |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| `evidence.query(name)` | Rows for a named query or `sql` block declared on the page. Returns a promise, and always returns the latest interpolated rows. |
| `evidence.variables` | Values passed on the tag via `variables=` (see below). Always current. |
| `evidence.onVariablesChange(cb)` | Fires when any `variables` value changes. Returns an unsubscribe fn. |
| `evidence.theme` | `{ mode, palette }` — the resolved light/dark mode and categorical color palette. |
| `evidence.onThemeChange(cb)` | Fires when the theme or mode changes. Returns an unsubscribe fn. |
| `evidence.onResize(cb)` | Fires when the block's width changes. Returns an unsubscribe fn (see Sizing). |
| `evidence.subscribe(cb)` | Fires on any state change — variables, filters, or theme. Returns an unsubscribe fn. |
| `evidence.filters` | `get()`, `set(id, value)`, `create(id, value, { column })`, `subscribe(cb)` — see Parameterizing Queries. |
| `evidence.modal.open({ title, html })` / `.close()` | Open a full-page modal the parent renders over the report, in a nested sandbox with the same `evidence` API. |
| `evidence.navigate(path)` | Navigate to another page in the app (a drill-through). Same-origin internal paths only. |
| `evidence.ready()` | Signal that the first render is done. Call it after async draws so PDF/PNG export captures a finished frame. |
The reliable pattern is to wrap your draw in `async function render() { … }`, then `evidence.subscribe(render); await render();` — `evidence.query` returns fresh rows each call, so the same function serves the first render and every reactive re-render.
## Passing Variables
The `{% html %}` block runs verbatim in an isolated iframe: the body is never interpolated, so the way a page-level value (frontmatter, a component attribute, a repeat-scoped value, a filter value, a literal) reaches your code is the `variables={…}` attribute. Nothing crosses into the sandbox that you didn't pass. Values are evaluated on the page, snapshotted into the iframe, and read as `evidence.variables`.
```
---
selected_country: France
---
{% dropdown name=region values="north,south,east,west" defaultValue="north" /%}
{% html variables={
greeting=$selected_country
region="{{ region.literal }}"
limit=10
} %}
{% /html %}
```
**Inside a repeat:** pass the iteration's value through with `{{ }}`, so each iteration gets a different `evidence.variables`.
```
{% repeat id="category_repeat" data="demo.daily_orders" column="category" %}
{% html variables={ category="{{ category_repeat }}" } %}
{% /html %}
{% /repeat %}
```
**Notes:**
* **`{{ $x }}` does not interpolate inside the block** — the body is verbatim. For plain text, write it in markdown outside the block (where `{{ $x }}` works normally); inside the block, pass the value via `variables=` and read `evidence.variables.x` from a script. Validation catches both mistakes with the exact fix.
* **Reading a value you didn't pass returns `undefined`** — only `variables=` entries exist inside the sandbox. Validation flags visible reads with no matching entry.
* **Reactivity:** `const speed = evidence.variables.speed` at the top of your script captures the value once — when the attribute or filter behind it changes, your constant does not. `evidence.variables` itself is always current, so either read it where you use it (e.g. inside your render/animation loop), or register `evidence.onVariablesChange((vars) => { /* re-render */ })` for structural changes. A change that arrives while nothing is listening logs a console warning explaining this.
* Values must be serializable primitives (string / number / boolean / null). Objects, arrays, and functions are dropped before the snapshot reaches the iframe — flatten them at the call site (`start=$period.start`), or query them through `evidence.query()` instead.
* `evidence.variables` is a snapshot; mutating the returned object doesn't change anything (each read returns a fresh shallow copy).
* For *row data*, prefer `evidence.query("query_name")` over packing rows into `variables=` — query results stream lazily and aren't limited to primitives.
## Parameterizing Queries from JS
`evidence.query()` takes no parameters. To re-run a query with different inputs, create a filter in your JS and reference it from the SQL: the query re-runs server-side, and the predicate is applied on the warehouse, so only matching rows enter the iframe. Prefer this over pulling a whole table and filtering client-side.
The loop has four steps:
1. **Declare** the filter in your script: `evidence.filters.create("region", "north")` (create it before anything `.set`s it).
2. **Reference** it from any sql fence with `{{ region }}` (quoted value) or `{{ region.literal }}` (raw, for numbers).
3. **Set** it from your interaction handler: `evidence.filters.set("region", picked)` — the query re-runs on the warehouse.
4. **React**: `evidence.subscribe(render)` fires when the fresh result lands; call `evidence.query()` again inside `render` to get the new rows.
````
```sql region_sales
select category, sum(total_sales) as total
from demo.daily_orders
where region = {{ region }}
group by category
order by total desc
```
{% html %}
{% /html %}
````
**When not to use this:** for high-frequency interaction over a dataset that fits in memory (scrubbing an animation slider, hover highlights), fetch once with `evidence.query()` and filter/redraw client-side — a warehouse round-trip per frame is the wrong tool. Use the filter loop when the table is too big to pull, or when other components on the page should react too (`evidence.filters.create(id, value, { column: "the_column" })` makes built-in charts with `filters="id"` follow your selection).
## Sizing and Responsiveness
By default the block **autosizes**: it grows and shrinks to fit its content height and fills the page width. Give your content a real height so it has something to size to:
* A fixed-pixel element, or a responsive SVG sized with `viewBox` + `width:100%` + `height:auto` (which takes its height from the aspect ratio).
* A `height:100%` element has nothing to fill in autosize mode. For a chart that fills a fixed box (canvas, ECharts, and Chart.js all read the container's size), pass `height=` in pixels on the tag — that pins the box and makes the mount area full-height, so `height:100%` works.
Width reflows with the page, but a chart only follows if you build for it: scale SVGs with `viewBox` + `width:100%` (no redraw needed), or redraw from `evidence.onResize(cb)` (call the library's resize method in the callback for canvas/ECharts/Chart.js). A hardcoded pixel width won't reflow.
The block is an isolated iframe, so its own width is the viewport width — CSS `@media (max-width: 480px)` queries fire at the *block's* width, which makes them behave like container queries. Use them to reflow at narrow widths (stack columns, shrink type).
Tooltips and popovers are **clipped at the block edges** — CSS `overflow` can't escape the frame. Position them relative to your own container and clamp into bounds (e.g. `left = Math.max(0, Math.min(x, mount.clientWidth - tip.offsetWidth))`), or flip them near an edge.
## Network Allowlist
Author code inside an `{% html %}` block runs in a sandboxed iframe with a content-security-policy that blocks all network traffic except to the curated hosts below. `fetch`, XHR, `d3.csv`, and `d3.json` work against these hosts; everything else is blocked at the browser level.
For data from the user's own report, always use `evidence.query("query_name")` instead — page rows live in the parent context and have no URL to fetch.
### Script CDNs
Used for loading JS libraries via `