fix: support widget peak and onboarding wizard responsivness

This commit is contained in:
Nathnael
2026-07-30 13:08:51 +00:00
parent 6790450bf2
commit bfb4991234
3 changed files with 48 additions and 33 deletions

View File

@@ -883,6 +883,9 @@ export function AppLayout({
<AppShell.Main
style={{
backgroundColor: "##f8fafc",
// Extra bottom clearance so the fixed support-chat FAB never
// overlaps page content, even at the bottom of a scrolled page.
paddingBottom: 112,
}}
>
{children}

View File

@@ -8,6 +8,7 @@ import {
Text,
Title,
} from "@mantine/core";
import { useMediaQuery } from "@mantine/hooks";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
ArrowRight,
@@ -127,6 +128,7 @@ export default function OnboardingWizardDialog({
}: OnboardingWizardDialogProps) {
const queryClient = useQueryClient();
const { user, company, onboardingStep, onboardingCompleted } = useAuth();
const isMobile = useMediaQuery("(max-width: 48em)");
const existingProfiles = company?.company?.companyProfiles ?? [];
const companyAlreadyStarted = Boolean(company?.company?.id);
@@ -409,7 +411,9 @@ export default function OnboardingWizardDialog({
ceiling = Math.min(ceiling, FORM_STEPS.indexOf("documents"));
if (poaIncomplete) ceiling = Math.min(ceiling, FORM_STEPS.indexOf("poa"));
const effectiveResumeStep: FormStep =
FORM_STEPS[Math.min(Math.max(FORM_STEPS.indexOf(resumeFormStep), 0), ceiling)];
FORM_STEPS[
Math.min(Math.max(FORM_STEPS.indexOf(resumeFormStep), 0), ceiling)
];
const formProps = {
documentSettingCode: resolvedDocumentSettingCode,
@@ -450,9 +454,10 @@ export default function OnboardingWizardDialog({
withCloseButton={!completed}
closeOnClickOutside={false}
closeOnEscape={!completed}
fullScreen={isMobile}
size={1440}
radius="lg"
padding="xl"
padding={isMobile ? "md" : "xl"}
centered
keepMounted
scrollAreaComponent={ScrollArea.Autosize}
@@ -464,6 +469,9 @@ export default function OnboardingWizardDialog({
title: {
flex: 1,
},
body: isMobile
? { paddingBottom: "calc(100px + env(safe-area-inset-bottom))" }
: undefined,
}}
title={
completed ? null : (

View File

@@ -41,7 +41,7 @@ export function SupportWidget() {
if (!isAuthenticated) return null;
return (
<Affix position={{ bottom: 24, right: 24 }} zIndex={300}>
<Affix position={{ bottom: 24, right: 24 }} zIndex={300} className="group">
<Transition mounted={open} transition="pop-bottom-right" duration={200}>
{(styles) => (
<div style={styles} className="mb-3">
@@ -53,40 +53,44 @@ export function SupportWidget() {
<Transition mounted={!open} transition="pop" duration={150}>
{(styles) => (
<div style={styles} className="flex justify-end">
<Indicator
label={unread > 9 ? "9+" : unread}
size={20}
offset={8}
color="red"
disabled={unread === 0}
processing
withBorder
>
<button
type="button"
aria-label="Open support chat"
onClick={() => setOpen(true)}
className="group relative flex cursor-pointer items-center gap-2.5 rounded-full bg-linear-135 from-edr-primary-dark to-edr-primary py-2 pr-2 pl-2 text-white shadow-[0_10px_28px_rgba(13,92,44,0.4)] transition-transform duration-150 hover:-translate-y-0.5 focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-edr-primary active:translate-y-0 motion-reduce:transition-none motion-reduce:hover:translate-y-0 sm:pr-5"
{/* Icon+label stay recognizable at rest, just tucked down a bit;
lifts fully into place on hover/focus. */}
<div className="translate-y-[60%] transition-transform duration-300 ease-out group-hover:translate-y-0 focus-within:translate-y-0 motion-reduce:translate-y-0">
<Indicator
label={unread > 9 ? "9+" : unread}
size={20}
offset={8}
color="red"
disabled={unread === 0}
processing
withBorder
>
{/* Faint breathing ring; the unread badge already pulses, so stand down then. */}
{unread === 0 && (
<span className="pointer-events-none absolute -inset-1 animate-pulse rounded-full ring-2 ring-edr-primary/50 motion-reduce:animate-none" />
)}
<button
type="button"
aria-label="Open support chat"
onClick={() => setOpen(true)}
className="group relative flex cursor-pointer items-center gap-2.5 rounded-full bg-linear-135 from-edr-primary-dark to-edr-primary py-2 pr-2 pl-2 text-white shadow-[0_10px_28px_rgba(13,92,44,0.4)] transition-transform duration-150 hover:-translate-y-0.5 focus-visible:outline-2 focus-visible:outline-offset-3 focus-visible:outline-edr-primary active:translate-y-0 motion-reduce:transition-none motion-reduce:hover:translate-y-0 sm:pr-5"
>
{/* Faint breathing ring; the unread badge already pulses, so stand down then. */}
{unread === 0 && (
<span className="pointer-events-none absolute -inset-1 animate-pulse rounded-full ring-2 ring-edr-primary/50 motion-reduce:animate-none" />
)}
<span className="relative grid size-[42px] shrink-0 place-items-center rounded-full bg-white/20">
<Headset size={22} />
</span>
<span className="relative grid size-[42px] shrink-0 place-items-center rounded-full bg-white/20">
<Headset size={22} />
</span>
<span className="relative hidden text-left leading-tight sm:block">
<span className="block text-sm font-semibold whitespace-nowrap">
👋 Need help?
<span className="relative hidden text-left leading-tight sm:block">
<span className="block text-sm font-semibold whitespace-nowrap">
👋 Need help?
</span>
<span className="block text-[11px] whitespace-nowrap opacity-85">
Chat with our team
</span>
</span>
<span className="block text-[11px] whitespace-nowrap opacity-85">
Chat with our team
</span>
</span>
</button>
</Indicator>
</button>
</Indicator>
</div>
</div>
)}
</Transition>