diff --git a/apps/sim/app/(landing)/components/auth-modal/auth-modal.tsx b/apps/sim/app/(landing)/components/auth-modal/auth-modal.tsx index da7f1e76324..6e182a8ef48 100644 --- a/apps/sim/app/(landing)/components/auth-modal/auth-modal.tsx +++ b/apps/sim/app/(landing)/components/auth-modal/auth-modal.tsx @@ -2,6 +2,7 @@ import { useEffect, useRef, useState } from 'react' import { + cn, Loader, Modal, ModalClose, @@ -22,6 +23,7 @@ import { getEnv, isFalsy } from '@/lib/core/config/env' import { isSsoEnabled } from '@/lib/core/config/env-flags' import { captureClientEvent } from '@/lib/posthog/client' import type { PostHogEventMap } from '@/lib/posthog/events' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import { getBrandConfig } from '@/ee/whitelabeling' const logger = createLogger('AuthModal') @@ -196,7 +198,12 @@ export function AuthModal({ children, defaultView = 'login', source }: AuthModal className='h-[22px] w-auto shrink-0 object-contain' />
-

+

Start building.

diff --git a/apps/sim/app/(landing)/components/hero/components/hero-visual/hero-visual.tsx b/apps/sim/app/(landing)/components/hero/components/hero-visual/hero-visual.tsx index e3f46d6790a..3e32f5e88a5 100644 --- a/apps/sim/app/(landing)/components/hero/components/hero-visual/hero-visual.tsx +++ b/apps/sim/app/(landing)/components/hero/components/hero-visual/hero-visual.tsx @@ -38,6 +38,7 @@ import { TYPE_MS_PER_ATOM, WORKFLOW_FOCUS_SCALE, } from '@/app/(landing)/components/hero/components/hero-visual/workflow-data' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' /** * Animated hero visual - the only client island in the hero, decorative and @@ -299,7 +300,7 @@ const SEND_BUTTON_INK = { */ const LANDING_LOADER_INK = { '--tl-grad-inner': 'var(--text-body)', - '--tl-grad-outer': 'color-mix(in srgb, var(--text-body) 76%, #fff)', + '--tl-grad-outer': 'var(--thinking-loader-outer)', '--tl-glow': 'transparent', } as CSSProperties @@ -1144,6 +1145,7 @@ export function HeroVisual() { // layer, so the slide + dock read as smooth sub-pixel motion instead of // jittering as the position pixel-snaps each frame. 'pointer-events-none absolute top-0 left-0 z-20 transform-gpu transition-opacity duration-300 will-change-transform [transition-timing-function:cubic-bezier(0.23,1,0.32,1)]', + colorMixFallbacks.loaderOuter, loaderFading ? 'opacity-0' : 'opacity-100' )} style={{ transformOrigin: '0 0' }} diff --git a/apps/sim/app/(landing)/components/navbar/components/logo-mark/logo-mark.tsx b/apps/sim/app/(landing)/components/navbar/components/logo-mark/logo-mark.tsx index 1d26c75dd5c..e8cdc62896d 100644 --- a/apps/sim/app/(landing)/components/navbar/components/logo-mark/logo-mark.tsx +++ b/apps/sim/app/(landing)/components/navbar/components/logo-mark/logo-mark.tsx @@ -3,6 +3,7 @@ import { type CSSProperties, type ReactNode, useState } from 'react' import { cn } from '@sim/emcn' import { ThinkingLoader } from '@/components/ui' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' interface LogoMarkProps { /** Server-rendered Sim wordmark, shown by default. */ @@ -18,7 +19,7 @@ interface LogoMarkProps { */ const LOADER_INK = { '--tl-grad-inner': 'var(--text-body)', - '--tl-grad-outer': 'color-mix(in srgb, var(--text-body) 76%, #fff)', + '--tl-grad-outer': 'var(--thinking-loader-outer)', '--tl-glow': 'transparent', } as CSSProperties @@ -35,7 +36,7 @@ export function LogoMark({ children }: LogoMarkProps) { return (

-
+
{lead ? : null}
diff --git a/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.test.ts b/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.test.ts new file mode 100644 index 00000000000..b8026754b15 --- /dev/null +++ b/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.test.ts @@ -0,0 +1,53 @@ +/** + * @vitest-environment jsdom + */ +import { describe, expect, it } from 'vitest' +import { applyLegacyInertFallback } from '@/app/(landing)/demo/components/legacy-inert-fallback' + +describe('applyLegacyInertFallback', () => { + it('removes descendants from interaction and restores their exact prior state', () => { + const panel = document.createElement('div') + panel.setAttribute('aria-hidden', 'false') + panel.style.pointerEvents = 'auto' + panel.innerHTML = ` + + Demo + + ` + + const button = panel.querySelector('button') + const link = panel.querySelector('a') + const disabledInput = panel.querySelector('input') + const restore = applyLegacyInertFallback(panel) + + expect(panel.getAttribute('aria-hidden')).toBe('true') + expect(panel.style.pointerEvents).toBe('none') + expect(button?.getAttribute('tabindex')).toBe('-1') + expect(link?.getAttribute('tabindex')).toBe('-1') + expect(disabledInput?.getAttribute('tabindex')).toBeNull() + + restore() + + expect(panel.getAttribute('aria-hidden')).toBe('false') + expect(panel.style.pointerEvents).toBe('auto') + expect(button?.getAttribute('tabindex')).toBeNull() + expect(link?.getAttribute('tabindex')).toBe('2') + }) + + it('moves focus out of a panel before hiding it', () => { + const panel = document.createElement('div') + const button = document.createElement('button') + panel.append(button) + document.body.append(panel) + button.focus() + + expect(document.activeElement).toBe(button) + + const restore = applyLegacyInertFallback(panel) + + expect(document.activeElement).not.toBe(button) + + restore() + panel.remove() + }) +}) diff --git a/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.ts b/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.ts new file mode 100644 index 00000000000..850f315fd95 --- /dev/null +++ b/apps/sim/app/(landing)/demo/components/legacy-inert-fallback.ts @@ -0,0 +1,46 @@ +const FOCUSABLE_SELECTOR = [ + 'a[href]', + 'area[href]', + 'button:not([disabled])', + 'input:not([disabled])', + 'select:not([disabled])', + 'textarea:not([disabled])', + 'iframe', + 'object', + 'embed', + '[contenteditable="true"]', + '[tabindex]', +].join(',') + +/** + * Mirrors the interaction-blocking parts of `inert` for Firefox 111, the only + * browser in Next's supported range without native support. Modern browsers + * never call this fallback. + */ +export function applyLegacyInertFallback(node: HTMLElement): () => void { + const previousAriaHidden = node.getAttribute('aria-hidden') + const previousPointerEvents = node.style.pointerEvents + const previousTabIndexes = new Map() + const activeElement = node.ownerDocument.activeElement + + if (activeElement instanceof HTMLElement && node.contains(activeElement)) activeElement.blur() + + node.setAttribute('aria-hidden', 'true') + node.style.pointerEvents = 'none' + + for (const element of node.querySelectorAll(FOCUSABLE_SELECTOR)) { + previousTabIndexes.set(element, element.getAttribute('tabindex')) + element.setAttribute('tabindex', '-1') + } + + return () => { + if (previousAriaHidden === null) node.removeAttribute('aria-hidden') + else node.setAttribute('aria-hidden', previousAriaHidden) + node.style.pointerEvents = previousPointerEvents + + for (const [element, tabIndex] of previousTabIndexes) { + if (tabIndex === null) element.removeAttribute('tabindex') + else element.setAttribute('tabindex', tabIndex) + } + } +} diff --git a/apps/sim/app/(landing)/enterprise/components/feature-graphics/access-control-graphic.tsx b/apps/sim/app/(landing)/enterprise/components/feature-graphics/access-control-graphic.tsx index a24147065c1..1e22d3e5ec8 100644 --- a/apps/sim/app/(landing)/enterprise/components/feature-graphics/access-control-graphic.tsx +++ b/apps/sim/app/(landing)/enterprise/components/feature-graphics/access-control-graphic.tsx @@ -1,5 +1,6 @@ import { ChipTag, cn } from '@sim/emcn' import Image from 'next/image' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import styles from '@/app/(landing)/enterprise/components/feature-graphics/access-control-graphic.module.css' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' @@ -123,13 +124,10 @@ export function AccessControlGraphic() { pathLength={1} className={cn( styles.edgeDraw, - edge.emphasized ? styles.edgeDrawEmphasized : EDGE_DRAW_CLASSES[index] + edge.emphasized ? styles.edgeDrawEmphasized : EDGE_DRAW_CLASSES[index], + !edge.emphasized && colorMixFallbacks.mutedStroke35 )} - stroke={ - edge.emphasized - ? 'var(--text-secondary)' - : 'color-mix(in srgb, var(--text-muted) 35%, transparent)' - } + stroke={edge.emphasized ? 'var(--text-secondary)' : undefined} strokeWidth='1' /> ))} diff --git a/apps/sim/app/(landing)/enterprise/components/feature-graphics/deploy-graphic.tsx b/apps/sim/app/(landing)/enterprise/components/feature-graphics/deploy-graphic.tsx index 69a26ab089a..3e8056e6e0f 100644 --- a/apps/sim/app/(landing)/enterprise/components/feature-graphics/deploy-graphic.tsx +++ b/apps/sim/app/(landing)/enterprise/components/feature-graphics/deploy-graphic.tsx @@ -2,6 +2,7 @@ import type { CSSProperties } from 'react' import { ChipTag, chipContentLabelClass, chipGeometryClass, cn } from '@sim/emcn' import { CircleCheck, Lock } from '@sim/emcn/icons' import { ThinkingLoader } from '@/components/ui' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import styles from '@/app/(landing)/enterprise/components/feature-graphics/deploy-graphic.module.css' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' @@ -100,7 +101,12 @@ export function DeployGraphic({ {versionTag} - + @@ -116,11 +122,21 @@ export function DeployGraphic({ - + -
+
- +
@@ -92,12 +93,17 @@ export function LifecycleGraphic() {
- +
- + {version.label} diff --git a/apps/sim/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.tsx b/apps/sim/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.tsx index 977bc56e017..b5bf65212ce 100644 --- a/apps/sim/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.tsx +++ b/apps/sim/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.tsx @@ -1,6 +1,7 @@ import type { CSSProperties } from 'react' import { cn } from '@sim/emcn' import { ThinkingLoader } from '@/components/ui' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' import styles from '@/app/(landing)/enterprise/components/feature-graphics/operations-teams-graphic.module.css' @@ -118,14 +119,11 @@ const OUT_PATHS = { jira: 'M 140 155 C 140 184 224 178 224 206', } as const -/** Faint-ink stroke for the resting wires (the deploy tile's guide-line grey, quieter). */ -const QUIET_STROKE = 'color-mix(in srgb, var(--text-muted-inverse) 28%, transparent)' - /** Shared 1px outline ink for the tags, port dots, and router hub ring. */ -const OUTLINE_INK = 'border-[color:color-mix(in_srgb,var(--text-muted-inverse)_45%,transparent)]' +const OUTLINE_INK = colorMixFallbacks.inverseBorder45 /** Shared SVG props for a resting wire. */ -const WIRE_PROPS = { stroke: QUIET_STROKE, strokeWidth: '1' } as const +const WIRE_PROPS = { className: colorMixFallbacks.inverseStroke28, strokeWidth: '1' } as const /** Shared SVG props for a traveling white request-pulse overlay on a wire. */ const PULSE_PROPS = { diff --git a/apps/sim/app/(landing)/enterprise/components/feature-graphics/rollback-graphic.tsx b/apps/sim/app/(landing)/enterprise/components/feature-graphics/rollback-graphic.tsx index 52276001e1b..78d0bf143d6 100644 --- a/apps/sim/app/(landing)/enterprise/components/feature-graphics/rollback-graphic.tsx +++ b/apps/sim/app/(landing)/enterprise/components/feature-graphics/rollback-graphic.tsx @@ -1,5 +1,6 @@ -import { Button, ChipTag } from '@sim/emcn' +import { Button, ChipTag, cn } from '@sim/emcn' import { Undo } from '@sim/emcn/icons' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' /** @@ -71,7 +72,12 @@ export function RollbackGraphic() {
- +
@@ -103,13 +109,23 @@ export function RollbackGraphic() {
- +
- + v2 diff --git a/apps/sim/app/(landing)/enterprise/components/feature-graphics/standards-graphic.tsx b/apps/sim/app/(landing)/enterprise/components/feature-graphics/standards-graphic.tsx index 627d2e2c7dd..bdf82aa8140 100644 --- a/apps/sim/app/(landing)/enterprise/components/feature-graphics/standards-graphic.tsx +++ b/apps/sim/app/(landing)/enterprise/components/feature-graphics/standards-graphic.tsx @@ -1,5 +1,6 @@ import { ChipTag, cn } from '@sim/emcn' import { ShieldCheck } from '@sim/emcn/icons' +import colorMixFallbacks from '@/app/(landing)/components/shared/color-mix-fallbacks/color-mix-fallbacks.module.css' import { FeatureGraphicShell } from '@/app/(landing)/enterprise/components/feature-graphics/feature-graphic-shell' import styles from '@/app/(landing)/enterprise/components/feature-graphics/standards-graphic.module.css' @@ -86,8 +87,18 @@ export function StandardsGraphic({