Skip to content

Commit 70f9736

Browse files
committed
Add :robusta-url: inline role and migrate remaining inline-only docs
Introduces an inline counterpart to the .. robusta-url:: / .. robusta-code:: directives, so prose mentions of Robusta URLs get their own region picker without needing a block-level component: Sign up at :robusta-url:`https://platform.robusta.dev/signup` today. Or with custom link text: Visit :robusta-url:`our platform <https://platform.robusta.dev/signup>`. The role emits a span.robusta-region-inline wrapping the link; the client-side script appends a compact US/EU/AP picker that shares state with every other region selector on the page (boxes and inline alike). Migrated 15 docs whose only Robusta URL mention was an inline external link or inline literal — signup CTAs in install / architecture / playbook / pro-features / metric-providers / RobustaUI / oss-vs-saas / help / routing-with-scopes / _see_robusta_in_action-2 and the integration endpoint references in alertmanager-integration/{dynatrace, gcp-monitoring, launchdarkly, newrelic}.rst — all now use the role and display the region picker beside the link. The sphinx_design .. button-link:: on the docs index page is left as a plain URL; the page-wide JS still rewrites its href silently so the CTA points at the user's chosen region.
1 parent b9e918a commit 70f9736

17 files changed

Lines changed: 184 additions & 20 deletions

File tree

docs/_ext/region_box.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"""
2-
Directives for Robusta platform URL / code blocks with an embedded region selector.
2+
Directives and role for Robusta platform URL / code components with an
3+
embedded region selector.
34
45
Usage in .rst::
56
@@ -10,17 +11,28 @@
1011
curl --location --request POST 'https://api.robusta.dev/api/alerts' \
1112
--header 'Authorization: Bearer API-KEY'
1213
13-
The rendered HTML carries the ``robusta-region-box`` class; the
14-
client-side script in ``_static/region-selector.js`` injects the
15-
US/EU/AP selector and keeps every box on the page in sync.
14+
Sign up at :robusta-url:`https://platform.robusta.dev/signup` to get started.
15+
16+
Or with custom link text:
17+
18+
Visit :robusta-url:`our platform <https://platform.robusta.dev/signup>` today.
19+
20+
The rendered HTML carries ``robusta-region-box`` (block) or
21+
``robusta-region-inline`` (inline) classes; the client-side script in
22+
``_static/region-selector.js`` injects the US/EU/AP selector and keeps
23+
every region-aware component on the page in sync.
1624
"""
1725

26+
import re
1827
from html import escape
1928

2029
from docutils import nodes
2130
from sphinx.util.docutils import SphinxDirective
2231

2332

33+
_LABELLED_URL_RE = re.compile(r"^\s*(.+?)\s*<\s*([^<>\s]+)\s*>\s*$", re.DOTALL)
34+
35+
2436
class RobustaUrlDirective(SphinxDirective):
2537
has_content = True
2638
required_arguments = 0
@@ -75,11 +87,37 @@ def run(self):
7587
return [container]
7688

7789

90+
def robusta_url_role(name, rawtext, text, lineno, inliner, options=None, content=None):
91+
"""Inline ``:robusta-url:`URL``` or ``:robusta-url:`label <URL>```."""
92+
raw_text = nodes.unescape(text)
93+
match = _LABELLED_URL_RE.match(raw_text)
94+
if match:
95+
label = match.group(1).strip()
96+
url = match.group(2).strip()
97+
else:
98+
url = raw_text.strip()
99+
label = url
100+
if not url:
101+
msg = inliner.reporter.error(
102+
"robusta-url role requires a URL", line=lineno
103+
)
104+
return [inliner.problematic(rawtext, rawtext, msg)], [msg]
105+
106+
html = (
107+
f'<span class="robusta-region-inline">'
108+
f'<a class="robusta-region-inline__url" href="{escape(url, quote=True)}">'
109+
f"{escape(label)}</a>"
110+
f"</span>"
111+
)
112+
return [nodes.raw("", html, format="html")], []
113+
114+
78115
def setup(app):
79116
app.add_directive("robusta-url", RobustaUrlDirective)
80117
app.add_directive("robusta-code", RobustaCodeDirective)
118+
app.add_role("robusta-url", robusta_url_role)
81119
return {
82-
"version": "0.1",
120+
"version": "0.2",
83121
"parallel_read_safe": True,
84122
"parallel_write_safe": True,
85123
}

docs/_static/custom.css

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,3 +479,92 @@ h3 {
479479
border: 0 !important;
480480
border-radius: 0 !important;
481481
}
482+
483+
/* Inline region-aware URL: small picker beside the link */
484+
.md-typeset .robusta-region-inline,
485+
.robusta-region-inline {
486+
display: inline-flex;
487+
align-items: baseline;
488+
gap: 0.3rem;
489+
white-space: nowrap;
490+
max-width: 100%;
491+
}
492+
493+
.md-typeset .robusta-region-inline__url,
494+
.robusta-region-inline__url {
495+
word-break: break-all;
496+
white-space: normal;
497+
}
498+
499+
.md-typeset .robusta-region-inline__picker,
500+
.robusta-region-inline__picker {
501+
display: inline-flex !important;
502+
align-items: center;
503+
vertical-align: baseline;
504+
border-radius: 3px;
505+
overflow: hidden;
506+
line-height: 1;
507+
font-size: 0.62rem;
508+
font-weight: 600;
509+
white-space: nowrap;
510+
}
511+
512+
.md-typeset .robusta-region-inline__btn,
513+
.robusta-region-inline__btn {
514+
-webkit-appearance: none;
515+
appearance: none;
516+
display: inline-block !important;
517+
border: 1px solid var(--md-default-fg-color--lighter, rgba(0, 0, 0, 0.26)) !important;
518+
background: var(--md-default-bg-color, #fff) !important;
519+
color: var(--md-default-fg-color--light, rgba(0, 0, 0, 0.6)) !important;
520+
padding: 0.05rem 0.35rem !important;
521+
margin: 0 !important;
522+
cursor: pointer;
523+
font: inherit;
524+
font-size: 0.62rem !important;
525+
font-weight: 600;
526+
line-height: 1.2;
527+
text-align: center;
528+
box-shadow: none;
529+
border-radius: 0 !important;
530+
transition: background-color 0.15s ease, color 0.15s ease, border-color 0.15s ease;
531+
}
532+
533+
.md-typeset .robusta-region-inline__btn + .robusta-region-inline__btn,
534+
.robusta-region-inline__btn + .robusta-region-inline__btn {
535+
border-left-width: 0 !important;
536+
}
537+
538+
.md-typeset .robusta-region-inline__btn:first-child,
539+
.robusta-region-inline__btn:first-child {
540+
border-top-left-radius: 3px !important;
541+
border-bottom-left-radius: 3px !important;
542+
}
543+
544+
.md-typeset .robusta-region-inline__btn:last-child,
545+
.robusta-region-inline__btn:last-child {
546+
border-top-right-radius: 3px !important;
547+
border-bottom-right-radius: 3px !important;
548+
}
549+
550+
.md-typeset .robusta-region-inline__btn:hover,
551+
.robusta-region-inline__btn:hover {
552+
color: var(--md-primary-fg-color, #1976d2) !important;
553+
}
554+
555+
.md-typeset .robusta-region-inline__btn.is-active,
556+
.robusta-region-inline__btn.is-active {
557+
background: var(--md-primary-fg-color, #1976d2) !important;
558+
border-color: var(--md-primary-fg-color, #1976d2) !important;
559+
color: var(--md-primary-bg-color, #fff) !important;
560+
z-index: 1;
561+
position: relative;
562+
}
563+
564+
.md-typeset .robusta-region-inline__btn:focus-visible,
565+
.robusta-region-inline__btn:focus-visible {
566+
outline: 2px solid var(--md-accent-fg-color, #1976d2);
567+
outline-offset: 2px;
568+
z-index: 1;
569+
position: relative;
570+
}

docs/_static/region-selector.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
const DETECT_PATTERN = /\b(?:platform|api)(?:\.(?:eu|ap))?\.robusta\.dev\b/;
1212
const BAR_CLASS = "robusta-region-box__bar";
1313
const BTN_CLASS = "robusta-region-box__region-btn";
14+
const INLINE_PICKER_CLASS = "robusta-region-inline__picker";
15+
const INLINE_BTN_CLASS = "robusta-region-inline__btn";
1416

1517
function getRegion() {
1618
try {
@@ -95,6 +97,33 @@
9597
applyRegion(regionKey);
9698
}
9799

100+
function buildInlinePicker(currentRegion) {
101+
const picker = document.createElement("span");
102+
picker.className = INLINE_PICKER_CLASS;
103+
picker.setAttribute("role", "radiogroup");
104+
picker.setAttribute("aria-label", "Select your Robusta region");
105+
106+
const buttons = [];
107+
Object.keys(REGIONS).forEach(function (key) {
108+
const btn = document.createElement("button");
109+
btn.type = "button";
110+
btn.setAttribute("role", "radio");
111+
btn.setAttribute("data-region", key);
112+
btn.className = INLINE_BTN_CLASS;
113+
btn.textContent = REGIONS[key].label;
114+
const active = key === currentRegion;
115+
btn.setAttribute("aria-checked", String(active));
116+
if (active) btn.classList.add("is-active");
117+
btn.addEventListener("click", function (e) {
118+
e.preventDefault();
119+
syncAll(key);
120+
});
121+
picker.appendChild(btn);
122+
buttons.push(btn);
123+
});
124+
return { picker: picker, buttons: buttons };
125+
}
126+
98127
function buildBar(currentRegion) {
99128
const bar = document.createElement("div");
100129
bar.className = BAR_CLASS;
@@ -152,6 +181,14 @@
152181
boxes.push({ buttons: built.buttons });
153182
});
154183

184+
content.querySelectorAll(".robusta-region-inline").forEach(function (el) {
185+
const existingPicker = el.querySelector(":scope > ." + INLINE_PICKER_CLASS);
186+
if (existingPicker) existingPicker.remove();
187+
const built = buildInlinePicker(region);
188+
el.appendChild(built.picker);
189+
boxes.push({ buttons: built.buttons });
190+
});
191+
155192
collectTargets(content);
156193

157194
if (targets.length === 0 && boxes.length === 0) return;

docs/configuration/alertmanager-integration/dynatrace.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Step 2: Create a Dynatrace Problems Webhook
3333
3. Click **Add notification** and choose **Webhook**.
3434
4. Configure the **URL**:
3535

36-
``https://api.robusta.dev/integrations/generic/dynatrace``
36+
:robusta-url:`https://api.robusta.dev/integrations/generic/dynatrace`
3737

3838
5. Set the **Custom payload** to the Dynatrace macro:
3939

docs/configuration/alertmanager-integration/gcp-monitoring.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Step 2: Create a Webhook Notification Channel in GCP
3737
3. Configure the webhook with the following settings:
3838

3939
- **Display Name**: ``RobustaWebhook``
40-
- **Endpoint URL**: ``https://api.robusta.dev/integrations/generic/gcp``
40+
- **Endpoint URL**: :robusta-url:`https://api.robusta.dev/integrations/generic/gcp`
4141
- **Authentication**: Select **Basic Authentication**
4242
- **Username**: Your Robusta ``account_id`` from Step 1
4343
- **Password**: Your Robusta API key from Step 1

docs/configuration/alertmanager-integration/launchdarkly.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ In LaunchDarkly:
4343
3. Configure:
4444

4545
- **Name**: ``Robusta``
46-
- **URL**: ``https://api.robusta.dev/integrations/generic/launchdarkly?api_key=YOUR_API_KEY_HERE&account_id=YOUR_ACCOUNT_ID_HERE``
46+
- **URL**: :robusta-url:`https://api.robusta.dev/integrations/generic/launchdarkly?api_key=YOUR_API_KEY_HERE&account_id=YOUR_ACCOUNT_ID_HERE`
4747
- Replace ``YOUR_API_KEY_HERE`` with the API key from Step 1.
4848
- Replace ``YOUR_ACCOUNT_ID_HERE`` with your account ID from Step 1.
4949

@@ -64,7 +64,7 @@ Including API keys in URLs can expose them in logs, browser history, and monitor
6464

6565
If you’re using a third-party service that supports custom headers, configure the webhook like this:
6666

67-
- **URL**: ``https://api.robusta.dev/integrations/generic/launchdarkly?account_id=YOUR_ACCOUNT_ID_HERE``
67+
- **URL**: :robusta-url:`https://api.robusta.dev/integrations/generic/launchdarkly?account_id=YOUR_ACCOUNT_ID_HERE`
6868
- **Headers**:
6969

7070
.. code-block:: text

docs/configuration/alertmanager-integration/newrelic.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ In New Relic:
4444
2. Click **New destination** → choose **Webhook**.
4545
3. Configure:
4646

47-
- **URL**: ``https://api.robusta.dev/integrations/generic/newrelic``
47+
- **URL**: :robusta-url:`https://api.robusta.dev/integrations/generic/newrelic`
4848
- **Authentication**: **Bearer token**
4949
- **Token**: paste the **Robusta API key** from Step 1.
5050

docs/configuration/exporting/robusta-pro-features.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ Getting Started
2525

2626
To access these APIs:
2727

28-
1. `Sign up <https://platform.robusta.dev/signup>`_ for Robusta SaaS or contact support@robusta.dev for self-hosted plans
28+
1. :robusta-url:`Sign up <https://platform.robusta.dev/signup>` for Robusta SaaS or contact support@robusta.dev for self-hosted plans
2929
2. Generate API keys in the Robusta Platform under **Settings** → **API Keys**

docs/configuration/metric-providers-external.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,5 +185,5 @@ Next Steps
185185
----------
186186

187187
- Configure :doc:`alert routing </notification-routing/index>`
188-
- `Set up AI-powered insights <https://platform.robusta.dev/signup>`_
188+
- :robusta-url:`Set up AI-powered insights <https://platform.robusta.dev/signup>`
189189
- Learn about :doc:`common configuration options <metric-providers>`

docs/configuration/sinks/RobustaUI.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ Configuring the Robusta UI Sink
2020
------------------------------------------------
2121

2222
.. tip::
23-
This guide is for users who have already installed Robusta on their cluster. If you haven't installed Robusta yet, we recommend starting by `creating a free Robusta UI account ↗ <https://platform.robusta.dev/signup?utm_source=docs&utm_content=robusta-ui-sink-page>`_ instead.
23+
This guide is for users who have already installed Robusta on their cluster. If you haven't installed Robusta yet, we recommend starting by :robusta-url:`creating a free Robusta UI account ↗ <https://platform.robusta.dev/signup?utm_source=docs&utm_content=robusta-ui-sink-page>` instead.
2424

2525
Use the ``robusta`` CLI to generate a token:
2626

0 commit comments

Comments
 (0)