Files
openchamber/packages/ui/src/styles/mobile.css
T

501 lines
16 KiB
CSS

/* Mobile Adaptations - All Devices */
/* Set global device type variables */
:root {
--is-mobile: 0;
--device-type: 'desktop';
--font-scale: 1;
}
@media (max-width: 1024px) {
:root.mobile-pointer:not(.desktop-runtime) {
--is-mobile: 1;
--device-type: 'mobile';
--font-scale: 0.9;
}
}
/* Utility classes for device-specific styling */
.desktop-only {
display: block;
}
.mobile-only {
display: none;
}
@media (max-width: 1024px) {
:root.mobile-pointer:not(.desktop-runtime) .desktop-only {
display: none !important;
}
:root.desktop-runtime .mobile-only {
display: none !important;
}
:root.mobile-pointer:not(.desktop-runtime) .mobile-only {
display: block !important;
}
}
/* General mobile improvements for all mobile devices */
@media (max-width: 1024px) {
/* Override CSS custom properties for mobile */
:root.mobile-pointer:not(.desktop-runtime) {
--text-markdown: 1rem;
--text-code: 0.875rem;
--text-ui-header: 0.9375rem;
--text-ui-label: 0.875rem;
--text-meta: 0.875rem;
--text-micro: 0.8125rem;
}
/* Force override with higher specificity */
:root.mobile-pointer:not(.desktop-runtime) * {
--text-markdown: 1rem !important;
--text-code: 0.875rem !important;
--text-ui-header: 0.9375rem !important;
--text-ui-label: 0.875rem !important;
--text-meta: 0.875rem !important;
--text-micro: 0.8125rem !important;
}
/* Additional override for elements using typography classes */
:root.mobile-pointer:not(.desktop-runtime) .typography-markdown,
:root.mobile-pointer:not(.desktop-runtime) .typography-code,
:root.mobile-pointer:not(.desktop-runtime) .typography-ui-header,
:root.mobile-pointer:not(.desktop-runtime) .typography-ui-label,
:root.mobile-pointer:not(.desktop-runtime) .typography-meta,
:root.mobile-pointer:not(.desktop-runtime) .typography-micro {
font-size: unset !important;
}
/* Fix font size for tool displays */
:root.mobile-pointer:not(.desktop-runtime) [class*="tool"],
:root.mobile-pointer:not(.desktop-runtime) [class*="code"] {
--text-code: 0.875rem !important;
font-size: var(--text-code) !important;
}
/* Improve touch targets for mobile */
:root.mobile-pointer:not(.desktop-runtime) button:not([role="radio"]):not([role="checkbox"]):not([role="switch"]),
:root.mobile-pointer:not(.desktop-runtime) .btn,
:root.mobile-pointer:not(.desktop-runtime) [role="button"] {
min-height: 36px;
min-width: 36px;
}
/* Improve input field touch targets */
:root.mobile-pointer:not(.desktop-runtime) input,
:root.mobile-pointer:not(.desktop-runtime) textarea,
:root.mobile-pointer:not(.desktop-runtime) select {
min-height: 36px;
}
/* Fix mobile text inputs */
:root.mobile-pointer:not(.desktop-runtime) input[type="text"],
:root.mobile-pointer:not(.desktop-runtime) input[type="search"],
:root.mobile-pointer:not(.desktop-runtime) input[type="email"],
:root.mobile-pointer:not(.desktop-runtime) input[type="password"],
:root.mobile-pointer:not(.desktop-runtime) textarea {
font-size: 16px !important; /* Prevents iOS zoom */
}
/* Prevent keyboard on non-input elements */
:root.mobile-pointer:not(.desktop-runtime)
button:not([type="submit"]):not([type="button"]):not([type="reset"]),
:root.mobile-pointer:not(.desktop-runtime) .btn,
:root.mobile-pointer:not(.desktop-runtime) [role="button"] {
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
}
/* Specific fix for session buttons */
:root.mobile-pointer:not(.desktop-runtime) button[inputmode="none"] {
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
pointer-events: auto;
}
/* Prevent system context menu on message content when using custom selection menu */
:root.mobile-pointer:not(.desktop-runtime) .message-content-text {
-webkit-touch-callout: none;
-webkit-user-select: text;
user-select: text;
}
/* Allow system context menu only when explicitly requested via the "More" button */
:root.mobile-pointer:not(.desktop-runtime) .message-content-text.show-system-menu {
-webkit-touch-callout: default;
}
/* Improve mobile spacing */
:root.mobile-pointer:not(.desktop-runtime) .px-4 {
padding-left: 1rem !important;
padding-right: 1rem !important;
}
:root.mobile-pointer:not(.desktop-runtime) .py-2 {
padding-top: 0.75rem !important;
padding-bottom: 0.75rem !important;
}
/* Fix mobile scroll containers */
:root.mobile-pointer:not(.desktop-runtime) .overflow-hidden {
overflow-x: hidden !important;
overflow-y: auto !important;
-webkit-overflow-scrolling: touch;
}
:root.mobile-pointer:not(.desktop-runtime) [data-page-scroll-lock="true"] {
overflow: hidden !important;
overscroll-behavior: none;
}
/* Keep markdown code blocks horizontally scrollable on mobile. */
:root.mobile-pointer:not(.desktop-runtime) .markdown-content [data-markdown="code-block-body"] {
overflow-x: auto !important;
overflow-y: hidden !important;
-webkit-overflow-scrolling: touch;
}
/* Fix mobile viewport height */
:root.mobile-pointer:not(.desktop-runtime) {
height: 100%;
height: -webkit-fill-available;
overflow: hidden;
}
/* Fix main layout container */
:root.mobile-pointer:not(.desktop-runtime) .flex.flex-col.h-screen {
height: 100vh;
height: -webkit-fill-available;
min-height: 0;
}
/* Fix main content area */
:root.mobile-pointer:not(.desktop-runtime) .flex-1.overflow-hidden {
min-height: 0;
flex: 1;
}
/* Fix chat container */
:root.mobile-pointer:not(.desktop-runtime) .flex.flex-col.h-full {
height: 100%;
min-height: 0;
}
/* Ensure proper flex behavior */
:root.mobile-pointer:not(.desktop-runtime) .flex.flex-col {
min-height: 0;
}
/* Mobile sidebar positioning */
:root.mobile-pointer:not(.desktop-runtime) .mobile-sidebar-top {
top: var(--header-height, 3rem);
height: calc(100vh - var(--header-height, 3rem));
}
/* Set header height variable */
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
--header-height: 3rem;
}
/* For mobile devices with larger header */
@media (max-width: 768px) {
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
--header-height: 3.5rem;
}
}
/* For tablet devices */
@media (min-width: 769px) and (max-width: 1024px) {
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
--header-height: 3.25rem;
}
}
}
/* iOS PWA Adaptations */
/* iOS safe area defaults (applies to PWA + Safari) */
@supports (-webkit-touch-callout: none) {
:root.device-mobile:not(.desktop-runtime),
:root.device-tablet:not(.desktop-runtime),
:root.mobile-pointer:not(.desktop-runtime) {
--oc-safe-area-top: env(safe-area-inset-top, 0);
--oc-safe-area-right: env(safe-area-inset-right, 0);
--oc-safe-area-bottom: env(safe-area-inset-bottom, 0);
--oc-safe-area-bottom-visual: clamp(0px, calc(var(--oc-safe-area-bottom) * 0.05), 4px);
--oc-safe-area-left: env(safe-area-inset-left, 0);
}
:root.device-mobile:not(.desktop-runtime) .header-safe-area,
:root.device-tablet:not(.desktop-runtime) .header-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
padding-top: var(--oc-safe-area-top);
}
}
/* Phase 1: iOS PWA safe area handling - Enhanced positioning approach */
@media (display-mode: standalone) {
/* iOS-specific safe area handling with CSS variable support */
@supports (-webkit-touch-callout: none) {
/* Safe area handling for fixed positioned elements */
:root.device-mobile:not(.desktop-runtime),
:root.device-tablet:not(.desktop-runtime),
:root.mobile-pointer:not(.desktop-runtime) {
--oc-safe-area-top: env(safe-area-inset-top, 0);
--oc-safe-area-right: env(safe-area-inset-right, 0);
--oc-safe-area-bottom: env(safe-area-inset-bottom, 0);
--oc-safe-area-bottom-visual: clamp(0px, calc(var(--oc-safe-area-bottom) * 0.05), 4px);
--oc-safe-area-left: env(safe-area-inset-left, 0);
}
:root.device-mobile:not(.desktop-runtime) .header-safe-area,
:root.device-tablet:not(.desktop-runtime) .header-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
padding-top: var(--oc-safe-area-top);
}
:root.device-mobile:not(.desktop-runtime) .main-content-safe-area,
:root.device-tablet:not(.desktop-runtime) .main-content-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .main-content-safe-area {
padding-top: 0;
padding-bottom: 0;
padding-left: var(--oc-safe-area-left);
padding-right: var(--oc-safe-area-right);
}
/* Safe area for bottom fixed/bottom-0 elements */
:root.device-mobile:not(.desktop-runtime) .bottom-safe-area,
:root.device-tablet:not(.desktop-runtime) .bottom-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .bottom-safe-area {
padding-bottom: var(--oc-safe-area-bottom-visual) !important;
}
/* Drawer safe area - top already offset by header height */
:root.device-mobile:not(.desktop-runtime) .drawer-safe-area,
:root.device-tablet:not(.desktop-runtime) .drawer-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .drawer-safe-area {
padding-top: 0;
padding-bottom: var(--oc-safe-area-bottom-visual);
}
/* Fix iOS viewport issues */
:root.device-mobile:not(.desktop-runtime) .flex.flex-col.h-screen,
:root.device-tablet:not(.desktop-runtime) .flex.flex-col.h-screen,
:root.mobile-pointer:not(.desktop-runtime) .flex.flex-col.h-screen {
min-height: 100vh;
min-height: -webkit-fill-available;
}
/* Prevent content overlap in iOS */
:root.device-mobile:not(.desktop-runtime) .flex-1.overflow-hidden,
:root.device-tablet:not(.desktop-runtime) .flex-1.overflow-hidden,
:root.mobile-pointer:not(.desktop-runtime) .flex-1.overflow-hidden {
position: relative;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
}
/* Update header height for iOS */
:root.device-mobile:not(.desktop-runtime) .header-safe-area,
:root.device-tablet:not(.desktop-runtime) .header-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
--header-height: 4.5rem;
}
:root.device-mobile:not(.desktop-runtime) .mobile-sidebar-top,
:root.device-tablet:not(.desktop-runtime) .mobile-sidebar-top,
:root.mobile-pointer:not(.desktop-runtime) .mobile-sidebar-top {
--header-height: 4.5rem;
}
/* Mobile typography improvements */
.typography-markdown {
font-size: 1rem !important;
}
.typography-code {
font-size: 0.875rem !important;
}
.typography-ui-header {
font-size: 0.9375rem !important;
}
.typography-ui-label {
font-size: 0.875rem !important;
}
.typography-meta {
font-size: 0.875rem !important;
}
.typography-micro {
font-size: 0.8125rem !important;
}
/* Fix font size for tool displays */
[class*="tool"], [class*="code"] {
font-size: 0.875rem !important;
}
}
/* Fallback for non-iOS standalone mode */
@supports not (-webkit-touch-callout: none) {
:root.device-mobile:not(.desktop-runtime),
:root.device-tablet:not(.desktop-runtime),
:root.mobile-pointer:not(.desktop-runtime) {
--oc-safe-area-top: env(safe-area-inset-top, 0);
--oc-safe-area-right: env(safe-area-inset-right, 0);
--oc-safe-area-bottom: env(safe-area-inset-bottom, 0);
--oc-safe-area-bottom-visual: clamp(0px, calc(var(--oc-safe-area-bottom) * 0.05), 4px);
--oc-safe-area-left: env(safe-area-inset-left, 0);
}
:root.device-mobile:not(.desktop-runtime) .header-safe-area,
:root.device-tablet:not(.desktop-runtime) .header-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .header-safe-area {
padding-top: var(--oc-safe-area-top);
}
:root.device-mobile:not(.desktop-runtime) .main-content-safe-area,
:root.device-tablet:not(.desktop-runtime) .main-content-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .main-content-safe-area {
padding-top: 0;
padding-bottom: 0;
padding-left: var(--oc-safe-area-left);
padding-right: var(--oc-safe-area-right);
}
:root.device-mobile:not(.desktop-runtime) .bottom-safe-area,
:root.device-tablet:not(.desktop-runtime) .bottom-safe-area,
:root.mobile-pointer:not(.desktop-runtime) .bottom-safe-area {
padding-bottom: var(--oc-safe-area-bottom-visual) !important;
}
}
}
/* Phase 6: Home indicator blur gradient fix */
@media (display-mode: standalone) and (max-width: 768px) {
.pwa-dialog-content {
--pwa-dialog-padding: clamp(0.75rem, 3vw, 1.25rem);
top: auto;
/* Browsers that don't understand dvh ignore the second declaration and
keep the vh-based fallback. Newer browsers use 100dvh so Android
Chrome's collapsible URL bar doesn't push the dialog footer off-screen. */
max-height: calc(
100vh
- var(--oc-safe-area-top, 0px)
- var(--oc-safe-area-bottom-visual, 0px)
- 20px
);
max-height: calc(
100dvh
- var(--oc-safe-area-top, 0px)
- var(--oc-safe-area-bottom-visual, 0px)
- 20px
);
padding: var(--pwa-dialog-padding);
padding-top: calc(var(--pwa-dialog-padding) + (var(--oc-safe-area-top, 0px) * 0.35));
row-gap: clamp(0.75rem, 2vw, 1.25rem);
}
.pwa-dialog-content.pwa-compact {
--pwa-dialog-padding: clamp(0.5rem, 2vw, 0.85rem);
row-gap: clamp(0.45rem, 1.5vw, 0.8rem);
}
.pwa-dialog-content [data-slot="dialog-close"] {
top: calc(0.25rem + (var(--oc-safe-area-top, 0px) * 0.35));
right: var(--pwa-dialog-padding);
}
.pwa-dialog-content.pwa-compact [data-slot="dialog-close"] {
top: calc(0.2rem + (var(--oc-safe-area-top, 0px) * 0.3));
}
.pwa-dialog-content .settings-page-body {
max-width: 100%;
padding: 0.75rem 1rem;
row-gap: 0;
}
.pwa-dialog-content .settings-page-body > :not([hidden]) ~ :not([hidden]) {
margin-top: 0.85rem;
}
.pwa-dialog-content .directory-dialog-body {
padding: 0.5rem 0.75rem;
}
.pwa-dialog-content .directory-dialog-body .directory-grid {
gap: 0.6rem;
}
.pwa-overlay-panel {
margin-bottom: 0;
}
.pwa-overlay-panel .pwa-overlay-scroll {
padding-bottom: calc(var(--oc-safe-area-bottom-visual, 0px) + 12px);
}
}
@media (display-mode: standalone) {
/* Home indicator overlay */
:root.device-mobile:not(.desktop-runtime) body::after,
:root.device-tablet:not(.desktop-runtime) body::after,
:root.mobile-pointer:not(.desktop-runtime) body::after {
content: '';
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: var(--oc-safe-area-bottom-visual, var(--oc-safe-area-bottom, env(safe-area-inset-bottom, 0)));
background: linear-gradient(
to top,
var(--background) 0%,
var(--background) 30%,
rgba(from var(--background) r g b / 0.8) 60%,
rgba(from var(--background) r g b / 0.3) 85%,
transparent 100%
);
z-index: 1000;
pointer-events: none;
}
/* Fallback for browsers without rgba(from ...) support */
@supports not (color: rgba(from white r g b / 0.5)) {
:root.device-mobile:not(.desktop-runtime) body::after,
:root.device-tablet:not(.desktop-runtime) body::after,
:root.mobile-pointer:not(.desktop-runtime) body::after {
background: linear-gradient(
to top,
var(--background) 0%,
var(--background) 30%,
rgba(21, 19, 19, 0.8) 60%, /* Dark theme fallback */
rgba(21, 19, 19, 0.3) 85%,
transparent 100%
);
}
/* Light theme fallback */
:root body::after {
background: linear-gradient(
to top,
var(--background) 0%,
var(--background) 30%,
rgba(248, 247, 243, 0.8) 60%, /* Light theme fallback */
rgba(248, 247, 243, 0.3) 85%,
transparent 100%
);
}
}
}