Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ public bool StagingElasticNavEnabled
set => _featureFlags["staging-elastic-nav"] = value;
}

public bool DiagnosticsPanelEnabled
{
get => IsEnabled("diagnostics-panel");
set => _featureFlags["diagnostics-panel"] = value;
}

private bool IsEnabled(string key)
{
var envKey = $"FEATURE_{key.ToUpperInvariant().Replace('-', '_')}";
Expand Down
48 changes: 36 additions & 12 deletions src/Elastic.Documentation.Site/Assets/isolated-header.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,41 @@
* Handles the dynamic resizing of the isolated header when scrolling.
* Expands only at scroll position 0, compacts after scrolling past threshold.
*/

const COMPACT_THRESHOLD = 80 // Scroll down past this to compact
const EXPANDED_OFFSET = '110px'
const COMPACT_OFFSET = '48px'

/**
* Set the CSS variable immediately based on scroll position.
* Called early (before DOMContentLoaded) to prevent layout shift.
* Adds no-transitions class that will be removed by initIsolatedHeader.
*/
export function setInitialHeaderOffset() {
// Check if isolated header exists in the DOM
// Use a simple check that works before full DOM is ready
if (!document.getElementById('isolated-header')) return

// Add class to disable all transitions during initial load
// This will be removed by initIsolatedHeader after layout is set
document.documentElement.classList.add('no-transitions')

const offset = window.scrollY > 0 ? COMPACT_OFFSET : EXPANDED_OFFSET
document.documentElement.style.setProperty('--offset-top', offset)
}

/**
* Full initialization - attaches scroll listener and updates header elements.
* Should be called on DOMContentLoaded.
*/
export function initIsolatedHeader() {
const header = document.getElementById('isolated-header')
if (!header) return

// Add class to body for CSS scoping
document.body.classList.add('has-isolated-header')

let isCompact = false

const COMPACT_THRESHOLD = 80 // Scroll down past this to compact
const EXPANDED_OFFSET = '110px'
const COMPACT_OFFSET = '48px'
let isCompact = window.scrollY > 0

const updateLayout = (compact: boolean) => {
const offset = compact ? COMPACT_OFFSET : EXPANDED_OFFSET
Expand Down Expand Up @@ -49,11 +72,12 @@ export function initIsolatedHeader() {
window.addEventListener('scroll', onScroll, { passive: true })

// Set initial state based on current scroll position
if (window.scrollY > 0) {
isCompact = true
updateLayout(true)
} else {
// Ensure initial expanded state is set
updateLayout(false)
}
updateLayout(isCompact)

// Re-enable transitions after layout is set
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove('no-transitions')
})
})
}
7 changes: 6 additions & 1 deletion src/Elastic.Documentation.Site/Assets/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { initAppliesSwitch } from './applies-switch'
import { initCopyButton } from './copybutton'
import { initHighlight } from './hljs'
import { initImageCarousel } from './image-carousel'
import { initIsolatedHeader } from './isolated-header'
import { initIsolatedHeader, setInitialHeaderOffset } from './isolated-header'
import { openDetailsWithAnchor } from './open-details-with-anchor'
import { initNav } from './pages-nav'
import { initSmoothScroll } from './smooth-scroll'
Expand All @@ -29,6 +29,10 @@ initializeOtel({
debug: false,
})

// Set header offset immediately to prevent layout shift on reload
// This runs before DOMContentLoaded to avoid visual jump
setInitialHeaderOffset()

// Dynamically import web components after telemetry is initialized
// This ensures telemetry is available when the components execute
// Parcel will automatically code-split this into a separate chunk
Expand All @@ -37,6 +41,7 @@ import('./web-components/AskAi/AskAi')
import('./web-components/VersionDropdown')
import('./web-components/AppliesToPopover')
import('./web-components/FullPageSearch/FullPageSearchComponent')
import('./web-components/Diagnostics/DiagnosticsComponent')

const { getOS } = new UAParser()

Expand Down
171 changes: 171 additions & 0 deletions src/Elastic.Documentation.Site/Assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ html {
@apply font-body;
}

/* Disable all transitions during initial page load to prevent layout shift */
.no-transitions,
.no-transitions * {
transition: none !important;
}

body {
/* This is still needed because of some usages of ch units and to maintain the previous behavior */
font-size: 16px;
Expand Down Expand Up @@ -208,6 +214,171 @@ body {
}
}

/* Wobble animation for diagnostics button */
@keyframes wobble {
0%,
100% {
transform: rotate(0deg);
}
15% {
transform: rotate(-3deg);
}
30% {
transform: rotate(3deg);
}
45% {
transform: rotate(-2deg);
}
60% {
transform: rotate(2deg);
}
75% {
transform: rotate(-1deg);
}
}

.animate-wobble {
animation: wobble 0.8s ease-in-out;
animation-delay: 2s;
animation-iteration-count: 3;
}

/* Animated gradient for diagnostics pill */
@keyframes gradient-shift {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}

/* Diagnostics pill base styling */
.diagnostics-pill {
box-shadow:
inset 0 1px 2px rgba(0, 0, 0, 0.3),
0 1px 0 rgba(255, 255, 255, 0.1);
background-size: 200% 200%;
animation: gradient-shift 3s ease infinite;
cursor: pointer !important;
}

.diagnostics-pill-error {
background: linear-gradient(
135deg,
#dc2626,
#b91c1c,
#991b1b,
#b91c1c,
#dc2626
);
}

.diagnostics-pill-warning {
background: linear-gradient(
135deg,
#d97706,
#b45309,
#92400e,
#b45309,
#d97706
);
}

.diagnostics-pill-hint {
background: linear-gradient(
135deg,
#0077cc,
#005fa3,
#004d85,
#005fa3,
#0077cc
);
}

.diagnostics-pill-success {
background: linear-gradient(
135deg,
#16a34a,
#15803d,
#166534,
#15803d,
#16a34a
);
}

.diagnostics-pill-building {
background: linear-gradient(
135deg,
#3b82f6,
#2563eb,
#1d4ed8,
#2563eb,
#3b82f6
);
}

/* Segmented diagnostics pill */
.diagnostics-segmented-pill {
box-shadow:
inset 0 1px 2px rgba(0, 0, 0, 0.2),
0 2px 4px rgba(0, 0, 0, 0.3);
cursor: pointer !important;
}

.diagnostics-segment {
background-size: 200% 200%;
animation: gradient-shift 3s ease infinite;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
}

.diagnostics-segment-error {
background: linear-gradient(
135deg,
#dc2626,
#b91c1c,
#991b1b,
#b91c1c,
#dc2626
);
}

.diagnostics-segment-warning {
background: linear-gradient(
135deg,
#d97706,
#b45309,
#92400e,
#b45309,
#d97706
);
}

.diagnostics-segment-hint {
background: linear-gradient(
135deg,
#0077cc,
#005fa3,
#004d85,
#005fa3,
#0077cc
);
}

.diagnostics-segment-building {
background: linear-gradient(
135deg,
#3b82f6,
#2563eb,
#1d4ed8,
#2563eb,
#3b82f6
);
}

#pages-nav .current {
@apply text-blue-elastic! font-semibold;
}
Expand Down
14 changes: 9 additions & 5 deletions src/Elastic.Documentation.Site/Assets/telemetry/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
*/
import { logs, SeverityNumber, type AnyValueMap } from '@opentelemetry/api-logs'

const logger = logs.getLogger('docs-frontend-logger')
// Lazy-initialize the logger to avoid errors when this module is imported
// before the OpenTelemetry LoggerProvider is set up
function getLogger() {
return logs.getLogger('docs-frontend-logger')
}

/**
* Log an informational message.
Expand All @@ -23,7 +27,7 @@ const logger = logs.getLogger('docs-frontend-logger')
* ```
*/
export function logInfo(body: string, attrs: AnyValueMap = {}) {
logger.emit({
getLogger().emit({
body,
severityNumber: SeverityNumber.INFO,
severityText: 'INFO',
Expand All @@ -46,7 +50,7 @@ export function logInfo(body: string, attrs: AnyValueMap = {}) {
* ```
*/
export function logWarn(body: string, attrs: AnyValueMap = {}) {
logger.emit({
getLogger().emit({
body,
severityNumber: SeverityNumber.WARN,
severityText: 'WARN',
Expand All @@ -70,7 +74,7 @@ export function logWarn(body: string, attrs: AnyValueMap = {}) {
* ```
*/
export function logError(body: string, attrs: AnyValueMap = {}) {
logger.emit({
getLogger().emit({
body,
severityNumber: SeverityNumber.ERROR,
severityText: 'ERROR',
Expand All @@ -93,7 +97,7 @@ export function logError(body: string, attrs: AnyValueMap = {}) {
* ```
*/
export function logDebug(body: string, attrs: AnyValueMap = {}) {
logger.emit({
getLogger().emit({
body,
severityNumber: SeverityNumber.DEBUG,
severityText: 'DEBUG',
Expand Down
Loading
Loading