fix(web): UI consistency — code tokens, label-qualifier, radio cards, Keboola edit-modal JS (#347)

* fix(web): UI consistency — code tokens, label-qualifier, radio card selected state

I-UI-01: Add .sync-option-card:has(input:checked) rule — border + background
feedback when a radio option card is selected. Add class sync-option-card to
all 14 radio label cards in admin_tables.html.

I-UI-02: Add .label-qualifier / .optional to style-custom.css. Remove the
duplicate local definition from admin_tables.html <style> block.

I-UI-03: Migrate inline code rule to design tokens (--font-mono, --text-sm,
--border-light, --border, --radius-sm). Add background + border so inline
code is visually distinct across all pages.

I-UI-05 (partial): Replace hardcoded #c4c4c4 / #fafafa in .btn-google:hover
with var(--border) / var(--background) so theme overrides apply.

* fix(web): expose entire Keboola edit-modal JS to all instance types

openEditKeboolaModal, closeEditKeboolaModal, saveKeboolaTabEdit,
onEditKbStrategyChange and helpers were still inside {% if keboola %}
but called from always-rendered HTML (openEditModal dispatcher,
Escape key handler, modal overlay click, Cancel/Save buttons).

Removed the Phase F2 if-guard entirely — only prefillFromKeboolaTable
stays conditional (its callers are inside {% if keboola %} HTML blocks).

* fix(ui): promote .form-textarea to global CSS with design tokens

Removes the local hardcoded .form-textarea definition from admin_tables.html
and adds it globally to style-custom.css using design tokens, making
description textareas visually consistent with other form fields.

* fix(ui): restore .form-textarea to local style block for visual consistency

Tokens --text-sm (12px) and --radius-md (6px) differ from the local override
values (13px, 8px) used by .form-input on this page, causing a visible mismatch.
.form-textarea rejoins the shared local selector so all three classes render
identically; global .form-textarea in style-custom.css remains as a baseline
for other pages.

* fix(ui): use textarea.form-textarea in global CSS to override .form-group textarea

.form-group textarea (specificity 0,1,1) was overriding .form-textarea (0,1,0)
with a legacy monospace font and different padding. Raising the selector to
textarea.form-textarea matches specificity and wins via source order, making
description textareas consistent with other form inputs. Local admin_tables.html
overrides for .form-textarea removed — styling now comes entirely from global CSS.

* fix(ui): add border:none to .code-block code + add CHANGELOG entries

Fixes light-gray border leaking into dark .code-block backgrounds.
Adds required CHANGELOG.md entries for all user-visible changes in this PR.

* fix(ui): add --border-dark token + reset border-radius in .code-block code

- Adds --border-dark: #C4C4C4 design token for hover border states
- Uses var(--border-dark) in both .btn-google:hover rules so hover border
  is visually distinct from the base border (was a no-op with var(--border))
- Adds border-radius: 0 to .code-block code override to fully reset the
  new global code border-radius on dark code-block backgrounds

* fix(ui): reset code border/bg inside .use-case-prompt dark container

Adds .plugin-detail .use-case-prompt code override to prevent the new
global code border and background from leaking into the dark #1e1e2e
pre block in marketplace_plugin_detail.html.

* fix(ui): reset code border in all dark-background containers

Global code { border } leaks into dark-themed containers across templates.
Adds border: none (+ border-radius: 0 where needed) to:
- marketplace_plugin_detail.html: lead-rendered pre code, sample-assistant-body code/pre code
- marketplace_item_detail.html: same three selectors
- home_onboarded.html, home_not_onboarded.html, admin_welcome.html: inline code on hero dark backgrounds

* fix(ui): uniform form typography — chip-input font, data-package desc textarea, orphan endif

- .chip-input container gets font-family/size tokens so inner input
  inherits correctly (inline `font: inherit` was pulling browser default)
- cdp-desc / edp-desc switched from form-input to form-textarea so
  description fields render Inter, not monospace
- Removed orphan {% endif %} left in admin_tables.html after rebase
  (caused TemplateSyntaxError breaking all admin-tables tests in CI)
- .item-detail .use-case-prompt code: border/bg reset for dark container

* fix: relax test_keboola_discover_buttons assertion + CHANGELOG bullet for #347

The test_keboola_discover_buttons_hidden_on_bigquery_instance test
asserted bare-string `prefillFromKeboolaTable` not in the rendered
HTML on a non-Keboola instance. That made sense when the function
DEFINITION lived behind the keboola Jinja guard. #347 moves
several Keboola edit-modal helpers out from under the guard so
they're now defined as dead code on every instance, but the actual
call sites (`onclick="prefillFromKeboolaTable(...)"` + the
Discover buttons themselves) still respect the guard — which is
what actually matters for runtime behavior.

Updated the assertions to match `onclick="<fn>(` so they pin the
call-site contract, not the function-definition substring.

---------

Co-authored-by: ZdenekSrotyr <zdenek.srotyr@keboola.com>
This commit is contained in:
Monika Feigler 2026-05-19 16:30:19 +02:00 committed by GitHub
parent 318802854c
commit caae12d02f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 113 additions and 53 deletions

View file

@ -11,6 +11,7 @@ CalVer image tags (`stable-YYYY.MM.N`, `dev-YYYY.MM.N`) are produced for every C
## [Unreleased]
### Fixed
- **UI consistency pass** (I-UI-01..05): radio-card selected state on `/admin/tables` (14 cards get blue border + light bg highlight via `.sync-option-card:has(input:checked)`); promoted `.label-qualifier` / `.optional` to global rule (drops local duplicate); inline `<code>` migrated to design tokens with bg + border; `.btn-google` hover hardcoded swatches replaced with vars; `.code-block code` border + radius reset for dark containers; `.form-textarea` promoted to global. Plus #340 follow-up: removed leftover Phase F2 `{% if data_source_type == 'keboola' %}` guard around edit-modal JS so handlers ship to every instance type (Discover button onclick call sites still respect the guard). Closes #347 (credit @MonikaFeigler).
- `agnes refresh-marketplace` (non-bootstrap path) now re-applies
`chmod +x` to every `.sh` under `~/.agnes/marketplace` after each
`git reset --hard FETCH_HEAD`, not just on the initial bootstrap

View file

@ -11,6 +11,7 @@
--surface: #FFFFFF;
--border: #E5E7EB;
--border-light: #F3F4F6;
--border-dark: #C4C4C4;
--success: #10B77F;
--warning: #F59F0A;
--error: #EA580C;
@ -254,8 +255,8 @@ nav {
.btn-google:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
border-color: #c4c4c4;
background-color: #fafafa;
border-color: var(--border-dark);
background-color: var(--background);
}
.btn-google:active {
@ -386,10 +387,28 @@ nav {
/* Code blocks */
code {
font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", monospace;
font-size: 0.875rem;
padding: 2px 6px;
border-radius: 4px;
font-family: var(--font-mono);
font-size: var(--text-sm);
background: var(--border-light);
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 1px var(--space-1);
color: var(--text-primary);
}
/* Label qualifiers — optional, default, hint text next to form labels */
.label-qualifier,
.optional {
font-size: var(--text-sm);
font-weight: var(--font-normal);
color: var(--text-secondary);
margin-left: var(--space-1);
}
/* Radio option cards — visual selected state */
.sync-option-card:has(input:checked) {
border-color: var(--primary) !important;
background: var(--primary-light) !important;
}
.code-block {
@ -405,6 +424,8 @@ code {
.code-block code,
.code-block pre {
background: transparent;
border: none;
border-radius: 0;
padding: 0;
font-size: 0.8125rem;
color: inherit;
@ -2885,8 +2906,8 @@ a.slack-badge:hover {
.login-page .btn-google:hover {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12);
border-color: #c4c4c4;
background-color: #fafafa;
border-color: var(--border-dark);
background-color: var(--background);
}
.login-page .btn-google:active {
@ -3970,6 +3991,29 @@ textarea.form-input {
line-height: 1.5;
}
textarea.form-textarea {
width: 100%;
min-height: 80px;
padding: var(--space-2) var(--space-3);
font-family: var(--font-primary);
font-size: var(--text-sm);
color: var(--text-primary);
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-md);
resize: vertical;
line-height: normal;
transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}
textarea.form-textarea:focus {
outline: none;
border-color: var(--primary);
box-shadow: var(--focus-ring);
}
textarea.form-textarea::placeholder { color: var(--text-muted); }
.form-input:focus {
outline: none;
border-color: var(--primary);
@ -3978,6 +4022,14 @@ textarea.form-input {
.form-input::placeholder { color: var(--text-muted); }
/* chip-input widget set font on the container so the inner input's
`font: inherit` inline style picks up the right value */
.chip-input {
font-family: var(--font-primary);
font-size: var(--text-sm);
color: var(--text-primary);
}
/* =====================================================
Page-header primitive (Task 6)
.page-header + __main / __title / __subtitle / __actions / __eyebrow

View file

@ -727,15 +727,8 @@
margin-bottom: 6px;
}
.form-label .optional {
font-weight: 400;
color: var(--text-secondary);
font-size: 12px;
}
.form-input,
.form-select,
.form-textarea {
.form-select {
width: 100%;
padding: 8px 12px;
border: 1px solid var(--border);
@ -748,8 +741,7 @@
}
.form-input:focus,
.form-select:focus,
.form-textarea:focus {
.form-select:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(0, 115, 209, 0.1);
@ -761,11 +753,6 @@
cursor: not-allowed;
}
.form-textarea {
min-height: 80px;
resize: vertical;
}
.form-select {
cursor: pointer;
appearance: none;
@ -1021,7 +1008,7 @@
<div class="form-group">
<label class="form-label">How should analysts access this data?</label>
<div class="bq-access-radio-group" style="display:flex; gap:12px; margin-top:6px;">
<label style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="bqAccessMode" value="live" checked onchange="onBqAccessModeChange()">
<strong>Live from BigQuery</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1031,7 +1018,7 @@
freshness matters.
</div>
</label>
<label style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="bqAccessMode" value="synced" onchange="onBqAccessModeChange()">
<strong>Synced locally</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1046,7 +1033,7 @@
<div class="form-group bq-access-synced" style="display:none;">
<label class="form-label">What to sync?</label>
<div class="bq-sync-radio-group" style="display:flex; gap:12px; margin-top:6px;">
<label style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="bqSyncMode" value="whole" checked onchange="onBqSyncModeChange()">
<strong>Whole table</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1054,7 +1041,7 @@
required. Disk + sync cost = full table size.
</div>
</label>
<label style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="bqSyncMode" value="custom" onchange="onBqSyncModeChange()">
<strong>Custom query</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1200,14 +1187,14 @@
<a href="docs/admin/query-modes.md" target="_blank" title="When to use which mode" style="margin-left: 6px; text-decoration: none; cursor: help;">?</a>
</label>
<div style="display:flex; gap:12px; margin-top:6px;">
<label style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editBqAccessMode" value="live" onchange="onEditBqAccessModeChange()">
<strong>Live from BigQuery</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
Each query goes to BQ. No local copy.
</div>
</label>
<label style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editBqAccessMode" value="synced" onchange="onEditBqAccessModeChange()">
<strong>Synced locally</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1225,14 +1212,14 @@
<div class="form-group bq-edit-access-synced" style="display:none;">
<label class="form-label">What to sync?</label>
<div style="display:flex; gap:12px; margin-top:6px;">
<label style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editBqSyncMode" value="whole" onchange="onEditBqSyncModeChange()">
<strong>Whole table</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
<code>SELECT *</code> on a schedule.
</div>
</label>
<label style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editBqSyncMode" value="custom" onchange="onEditBqSyncModeChange()">
<strong>Custom query</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1356,7 +1343,7 @@
<div class="form-group">
<label class="form-label">What to sync?</label>
<div class="bq-sync-radio-group" style="display:flex; gap:12px; margin-top:6px; flex-wrap:wrap;">
<label style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="kbSyncMode" value="whole" checked onchange="onKbSyncModeChange()">
<strong>Whole table (extension)</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1364,7 +1351,7 @@
each tick. Fastest path; full overwrite each run.
</div>
</label>
<label style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="kbSyncMode" value="direct" onchange="onKbSyncModeChange()">
<strong>Direct extract (Storage API)</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1373,7 +1360,7 @@
and server-side <code>where_filters</code>.
</div>
</label>
<label style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:12px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="kbSyncMode" value="custom" onchange="onKbSyncModeChange()">
<strong>Custom SQL</strong>
<div style="font-size:12px; color:var(--text-secondary); margin-top:4px;">
@ -1581,7 +1568,7 @@
<div class="form-group">
<label class="form-label">What to sync?</label>
<div class="bq-sync-radio-group" style="display:flex; gap:12px; margin-top:6px; flex-wrap:wrap;">
<label style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editKbSyncMode" value="whole"
onchange="onEditKbSyncModeChange()">
<strong>Whole table (extension)</strong>
@ -1589,7 +1576,7 @@
DuckDB Keboola extension; full overwrite each tick.
</div>
</label>
<label style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editKbSyncMode" value="direct"
onchange="onEditKbSyncModeChange()">
<strong>Direct extract (Storage API)</strong>
@ -1598,7 +1585,7 @@
<code>where_filters</code>.
</div>
</label>
<label style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<label class="sync-option-card" style="flex:1; min-width:200px; padding:10px; border:1px solid var(--border); border-radius:8px; cursor:pointer;">
<input type="radio" name="editKbSyncMode" value="custom"
onchange="onEditKbSyncModeChange()">
<strong>Custom SQL</strong>
@ -1884,7 +1871,7 @@
</div>
<div class="form-group">
<label class="form-label">Description <span class="optional">(optional)</span></label>
<textarea id="cdp-desc" class="form-input" rows="2"></textarea>
<textarea id="cdp-desc" class="form-textarea" rows="2"></textarea>
</div>
{# v51 lifecycle + classification — drive the hero filter
checkboxes on /catalog and the eyebrow line above the
@ -3176,7 +3163,7 @@
</div>
<div class="form-group">
<label class="form-label">Description</label>
<textarea id="edp-desc" class="form-input" rows="2"></textarea>
<textarea id="edp-desc" class="form-textarea" rows="2"></textarea>
</div>
<div class="form-group" style="display:flex; gap:12px;">
<div style="flex:1;">
@ -3901,7 +3888,6 @@
if (mode === 'direct') onEditKbStrategyChange();
}
{% if data_source_type == 'keboola' %}{# Phase F2 edit modal + prefill — keboola-only #}
function _getEditKbStrategy() {
var el = document.getElementById('editKbStrategy');
return el ? el.value : 'full_refresh';
@ -4153,7 +4139,6 @@
}
ta.value = 'SELECT *\nFROM kbc."' + bucket + '"."' + sourceTable + '"\nWHERE -- your filter here';
}
{% endif %}{# data_source_type == 'keboola' — Phase F2 edit modal + prefill #}
// C3: removed dead helper _buildKeboolaLegacyPayload — the Phase F
// _buildKeboolaPayload (above) replaced it.

View file

@ -208,7 +208,7 @@
<div>
{% set page_hero_eyebrow = "Agent Experience" %}
{% set page_hero_title = "Init Prompt" %}
{% set page_hero_subtitle = "Welcome shown to analysts at <code style=&quot;color:#fff;background:rgba(255,255,255,0.15);padding:1px 6px;border-radius:4px&quot;>agnes init</code>. Overrides the OSS default." %}
{% set page_hero_subtitle = "Welcome shown to analysts at <code style=&quot;color:#fff;background:rgba(255,255,255,0.15);border:none;padding:1px 6px;border-radius:4px&quot;>agnes init</code>. Overrides the OSS default." %}
{% include "_page_hero.html" %}
</div>
<div id="status-chip">

View file

@ -1055,7 +1055,7 @@
<div class="eyebrow">Welcome, {{ display_name }} — let's get you set up</div>
<h1>Connect Claude Code on your machine to your team's data</h1>
<p class="lead">
{{ instance_brand }} gives <strong>Claude Code</strong> on your computer access to your team's <strong>curated data, plugins, third-party tools (Asana, Google Workspace, Atlassian), and shared knowledge</strong> — so you can ask questions and get answers in plain language, right from your terminal. This page walks you through the <strong>one-time setup (~10 minutes)</strong>; the install script also connects your tools for you, so there's no extra page to visit. Everything it installs lives in your home folder (<code style="background: rgba(255,255,255,0.12); padding: 1px 6px; border-radius: 4px; font-family: var(--hp-font-mono); font-size: 12.5px;">~/{{ workspace_dir }}</code>) and can be removed in one command.
{{ instance_brand }} gives <strong>Claude Code</strong> on your computer access to your team's <strong>curated data, plugins, third-party tools (Asana, Google Workspace, Atlassian), and shared knowledge</strong> — so you can ask questions and get answers in plain language, right from your terminal. This page walks you through the <strong>one-time setup (~10 minutes)</strong>; the install script also connects your tools for you, so there's no extra page to visit. Everything it installs lives in your home folder (<code style="background: rgba(255,255,255,0.12); border: none; padding: 1px 6px; border-radius: 4px; font-family: var(--hp-font-mono); font-size: 12.5px;">~/{{ workspace_dir }}</code>) and can be removed in one command.
</p>
<p class="lead lead-privacy">
<strong>What leaves your machine.</strong> Session telemetry — prompts, tool calls, and tool responses — flows back to the central catalog so the team can analyse failure patterns. Raw data rows you query locally stay on your machine; only the prompt/response transcript travels. Need a session off the record? Toggle Private in Claude Code (by typing <code style="background: rgba(255,255,255,0.12); padding: 1px 6px; border-radius: 4px; font-family: var(--hp-font-mono); font-size: 12.5px;">/agnes-private</code>) to disable telemetry for that chat — nothing from that session reaches the catalog.

View file

@ -104,7 +104,7 @@
<div class="eyebrow">Welcome back, {{ display_name }}</div>
<h1>You're all set up</h1>
<p>
Open Claude Code in any project under <code style="background: rgba(255,255,255,0.12); padding: 1px 6px; border-radius: 4px; font-family: ui-monospace, 'SF Mono', Consolas, monospace; font-size: 12.5px;">~/{{ workspace_dir }}/Projects/</code>
Open Claude Code in any project under <code style="background: rgba(255,255,255,0.12); border: none; padding: 1px 6px; border-radius: 4px; font-family: ui-monospace, 'SF Mono', Consolas, monospace; font-size: 12.5px;">~/{{ workspace_dir }}/Projects/</code>
and start a session — your data and plugins are already synced. Use the cards below to jump into the parts of {{ instance_brand }} you need.
</p>
</div>

View file

@ -480,7 +480,7 @@
overflow-x: auto; margin: 8px 0 14px;
}
.item-detail .lead-rendered pre code {
background: transparent; padding: 0; color: inherit;
background: transparent; border: none; border-radius: 0; padding: 0; color: inherit;
}
.item-detail .lead-rendered a { color: var(--primary); text-decoration: none; }
.item-detail .lead-rendered a:hover { text-decoration: underline; }
@ -526,6 +526,13 @@
overflow-x: auto;
white-space: pre-wrap; word-break: break-word;
}
.item-detail .use-case-prompt code {
background: transparent;
border: none;
border-radius: 0;
padding: 0;
color: inherit;
}
/* Sample interaction — Claude Code Catppuccin Mocha dark transcript.
Identical visual treatment as plugin-detail's sample block: one dark
@ -575,6 +582,7 @@
.item-detail .sample-assistant-body em { color: #f9e2af; font-style: italic; }
.item-detail .sample-assistant-body code {
background: rgba(255,255,255,0.06);
border: none;
color: #f5c2e7;
border-radius: 4px; padding: 1px 5px;
font-size: 0.92em; font-family: var(--font-mono);
@ -590,7 +598,7 @@
margin: 8px 0;
}
.item-detail .sample-assistant-body pre code {
background: transparent; padding: 0; color: inherit;
background: transparent; border: none; border-radius: 0; padding: 0; color: inherit;
}
.item-detail .sample-assistant-body ul,
.item-detail .sample-assistant-body ol { margin: 0 0 10px 22px; padding: 0; }

View file

@ -402,7 +402,7 @@
overflow-x: auto; margin: 8px 0 14px;
}
.plugin-detail .lead-rendered pre code {
background: transparent; padding: 0; color: inherit;
background: transparent; border: none; border-radius: 0; padding: 0; color: inherit;
}
.plugin-detail .lead-rendered a { color: var(--primary); text-decoration: none; }
.plugin-detail .lead-rendered a:hover { text-decoration: underline; }
@ -446,6 +446,13 @@
overflow-x: auto;
white-space: pre-wrap; word-break: break-word;
}
.plugin-detail .use-case-prompt code {
background: transparent;
border: none;
border-radius: 0;
padding: 0;
color: inherit;
}
/* Sample interaction — Claude Code transcript styling. Single dark
Catppuccin Mocha panel splits the user prompt from Claude's response
@ -510,6 +517,7 @@
.plugin-detail .sample-assistant-body em { color: #f9e2af; font-style: italic; } /* mocha yellow */
.plugin-detail .sample-assistant-body code {
background: rgba(255,255,255,0.06);
border: none;
color: #f5c2e7; /* mocha pink */
border-radius: 4px;
padding: 1px 5px;
@ -527,8 +535,7 @@
margin: 8px 0;
}
.plugin-detail .sample-assistant-body pre code {
background: transparent; padding: 0;
color: inherit;
background: transparent; border: none; border-radius: 0; padding: 0; color: inherit;
}
.plugin-detail .sample-assistant-body ul,
.plugin-detail .sample-assistant-body ol {

View file

@ -327,10 +327,17 @@ def test_keboola_discover_buttons_hidden_on_bigquery_instance(seeded_app, monkey
# Inputs stay (manual entry works).
assert 'id="kbBucket"' in html
assert 'id="kbSourceTable"' in html
# Buttons hidden.
assert "discoverKeboolaBuckets" not in html
assert "discoverKeboolaTables" not in html
assert "prefillFromKeboolaTable" not in html
# Buttons hidden — match the actual CALL SITES, not the
# function definitions or JS comments that may reference the
# names verbatim. #347 moved several Keboola edit-modal
# helpers (incl. `prefillFromKeboolaTable`) out from under
# the keboola Jinja guard so they're now defined as dead code
# on every instance, but the `onclick="..."` call sites and
# the Discover buttons themselves still respect the guard,
# which is what actually matters for runtime behavior.
assert 'onclick="discoverKeboolaBuckets(' not in html
assert 'onclick="discoverKeboolaTables(' not in html
assert 'onclick="prefillFromKeboolaTable(' not in html
finally:
reset_cache()