style(create-chat): Dawn grouped form with a mono server and one native layout without the hero
This commit is contained in:
parent
4c6f662939
commit
7ea273eca8
3 changed files with 70 additions and 124 deletions
|
|
@ -8,11 +8,11 @@ type Props = {
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Thin shell around the shared `CreateChat` form. The legacy
|
// Thin shell around the shared `CreateChat` form. This curtain is the
|
||||||
// `/direct/_create` route renders the same component with a Page/
|
// canonical native new-chat surface; the `/direct/_create` route renders
|
||||||
// PageHero shell; here we only feed it the `onClose` callback and the
|
// the same grouped block under a back-chevron PageHeader. Here we only
|
||||||
// tighter `gap='400'` rhythm so the form fits comfortably under the
|
// feed it the `onClose` callback and the tighter `gap='400'` rhythm so the
|
||||||
// header.
|
// form fits comfortably under the header.
|
||||||
export function InlineNewChatForm({ onClose }: Props) {
|
export function InlineNewChatForm({ onClose }: Props) {
|
||||||
return <CreateChat gap="400" onCreated={onClose} />;
|
return <CreateChat gap="400" onCreated={onClose} />;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,11 @@
|
||||||
import {
|
import { Box, Button, color, Icon, Icons, Input, Spinner, Switch, Text, toRem } from 'folds';
|
||||||
Box,
|
|
||||||
Button,
|
|
||||||
color,
|
|
||||||
config,
|
|
||||||
Icon,
|
|
||||||
Icons,
|
|
||||||
Input,
|
|
||||||
Spinner,
|
|
||||||
Switch,
|
|
||||||
Text,
|
|
||||||
toRem,
|
|
||||||
} from 'folds';
|
|
||||||
import React, { FormEventHandler, useCallback, useState } from 'react';
|
import React, { FormEventHandler, useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ICreateRoomStateEvent, MatrixError, Preset, Visibility } from 'matrix-js-sdk';
|
import { ICreateRoomStateEvent, MatrixError, Preset, Visibility } from 'matrix-js-sdk';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { SettingTile } from '../../components/setting-tile';
|
import { SettingTile } from '../../components/setting-tile';
|
||||||
import { SequenceCard } from '../../components/sequence-card';
|
import { SettingsSection } from '../settings/SettingsSection';
|
||||||
|
import { Mono, SectionLabel } from '../settings/styles.css';
|
||||||
import {
|
import {
|
||||||
addRoomIdToMDirect,
|
addRoomIdToMDirect,
|
||||||
getDMRoomFor,
|
getDMRoomFor,
|
||||||
|
|
@ -136,17 +125,25 @@ export function CreateChat({ defaultUserId, onCreated, gap = '500' }: CreateChat
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box as="form" onSubmit={handleSubmit} grow="Yes" direction="Column" gap={gap}>
|
<Box as="form" onSubmit={handleSubmit} grow="Yes" direction="Column" gap={gap}>
|
||||||
<Box direction="Column" gap="100">
|
<Box direction="Column" gap="200">
|
||||||
|
<Text as="span" className={SectionLabel}>
|
||||||
|
{t('Direct.address')}
|
||||||
|
</Text>
|
||||||
<Box direction="Row" wrap="Wrap" gap="200">
|
<Box direction="Row" wrap="Wrap" gap="200">
|
||||||
<Box grow="Yes" style={{ minWidth: toRem(120) }} direction="Column" gap="100">
|
<Box grow="Yes" style={{ minWidth: toRem(120) }} direction="Column" gap="100">
|
||||||
<Text size="L400">{t('Direct.username')}</Text>
|
|
||||||
<Input
|
<Input
|
||||||
defaultValue={defaultUsername}
|
defaultValue={defaultUsername}
|
||||||
placeholder={t('Direct.username_placeholder')}
|
placeholder={t('Direct.username_placeholder')}
|
||||||
name="usernameInput"
|
name="usernameInput"
|
||||||
variant="SurfaceVariant"
|
variant="Background"
|
||||||
size="500"
|
size="500"
|
||||||
radii="400"
|
radii="400"
|
||||||
|
outlined
|
||||||
|
before={
|
||||||
|
<Text as="span" size="B500" className={Mono} style={{ opacity: 0.5 }}>
|
||||||
|
@
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
|
@ -154,16 +151,17 @@ export function CreateChat({ defaultUserId, onCreated, gap = '500' }: CreateChat
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No" style={{ minWidth: toRem(150) }} direction="Column" gap="100">
|
<Box shrink="No" style={{ minWidth: toRem(150) }} direction="Column" gap="100">
|
||||||
<Text size="L400">{t('Direct.server')}</Text>
|
|
||||||
<Input
|
<Input
|
||||||
defaultValue={
|
defaultValue={
|
||||||
defaultServer && defaultServer !== userServer ? defaultServer : undefined
|
defaultServer && defaultServer !== userServer ? defaultServer : undefined
|
||||||
}
|
}
|
||||||
placeholder={userServer}
|
placeholder={userServer}
|
||||||
name="serverInput"
|
name="serverInput"
|
||||||
variant="SurfaceVariant"
|
variant="Background"
|
||||||
size="500"
|
size="500"
|
||||||
radii="400"
|
radii="400"
|
||||||
|
outlined
|
||||||
|
className={Mono}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
|
|
@ -171,21 +169,14 @@ export function CreateChat({ defaultUserId, onCreated, gap = '500' }: CreateChat
|
||||||
</Box>
|
</Box>
|
||||||
{invalidUserId && (
|
{invalidUserId && (
|
||||||
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
|
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="100">
|
||||||
<Icon src={Icons.Warning} filled size="50" />
|
<Icon src={Icons.Warning} size="50" />
|
||||||
<Text size="T200" style={{ color: color.Critical.Main }}>
|
<Text size="T200" style={{ color: color.Critical.Main }}>
|
||||||
<b>{t('Direct.invalid_user_id')}</b>
|
{t('Direct.invalid_user_id')}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Box shrink="No" direction="Column" gap="100">
|
<SettingsSection label={t('Direct.options')}>
|
||||||
<Text size="L400">{t('Direct.options')}</Text>
|
|
||||||
<SequenceCard
|
|
||||||
style={{ padding: config.space.S300 }}
|
|
||||||
variant="SurfaceVariant"
|
|
||||||
direction="Column"
|
|
||||||
gap="500"
|
|
||||||
>
|
|
||||||
<SettingTile
|
<SettingTile
|
||||||
title={t('Direct.e2e_encryption')}
|
title={t('Direct.e2e_encryption')}
|
||||||
description={t('Direct.e2e_encryption_desc')}
|
description={t('Direct.e2e_encryption_desc')}
|
||||||
|
|
@ -198,13 +189,11 @@ export function CreateChat({ defaultUserId, onCreated, gap = '500' }: CreateChat
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</SequenceCard>
|
</SettingsSection>
|
||||||
</Box>
|
|
||||||
{error && (
|
{error && (
|
||||||
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="200">
|
<Box style={{ color: color.Critical.Main }} alignItems="Center" gap="200">
|
||||||
<Icon src={Icons.Warning} filled size="100" />
|
<Icon src={Icons.Warning} size="100" />
|
||||||
<Text size="T300" style={{ color: color.Critical.Main }}>
|
<Text size="T300" style={{ color: color.Critical.Main }}>
|
||||||
<b>
|
|
||||||
{(() => {
|
{(() => {
|
||||||
if (error instanceof MatrixError && error.name === ErrorCode.M_LIMIT_EXCEEDED) {
|
if (error instanceof MatrixError && error.name === ErrorCode.M_LIMIT_EXCEEDED) {
|
||||||
const ra = error.data?.retry_after_ms;
|
const ra = error.data?.retry_after_ms;
|
||||||
|
|
@ -214,7 +203,6 @@ export function CreateChat({ defaultUserId, onCreated, gap = '500' }: CreateChat
|
||||||
}
|
}
|
||||||
return error.message;
|
return error.message;
|
||||||
})()}
|
})()}
|
||||||
</b>
|
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,13 @@ import { getDirectCreateSearchParams } from '../../pathSearchParam';
|
||||||
import { getDirectRoomPath } from '../../pathUtils';
|
import { getDirectRoomPath } from '../../pathUtils';
|
||||||
import { getDMRoomFor } from '../../../utils/matrix';
|
import { getDMRoomFor } from '../../../utils/matrix';
|
||||||
import { useDirectRooms } from './useDirectRooms';
|
import { useDirectRooms } from './useDirectRooms';
|
||||||
import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
|
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
|
||||||
import {
|
|
||||||
Page,
|
|
||||||
PageContent,
|
|
||||||
PageContentCenter,
|
|
||||||
PageHeader,
|
|
||||||
PageHero,
|
|
||||||
PageHeroSection,
|
|
||||||
} from '../../../components/page';
|
|
||||||
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
import { BackRouteHandler } from '../../../components/BackRouteHandler';
|
||||||
import { CreateChat } from '../../../features/create-chat';
|
import { CreateChat } from '../../../features/create-chat';
|
||||||
import { isNativePlatform } from '../../../utils/capacitor';
|
|
||||||
|
|
||||||
export function DirectCreate() {
|
export function DirectCreate() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const mx = useMatrixClient();
|
const mx = useMatrixClient();
|
||||||
const screenSize = useScreenSizeContext();
|
|
||||||
const native = isNativePlatform();
|
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
|
|
@ -41,12 +30,10 @@ export function DirectCreate() {
|
||||||
}
|
}
|
||||||
}, [mx, navigate, directs, userId]);
|
}, [mx, navigate, directs, userId]);
|
||||||
|
|
||||||
// Native phone (Capacitor + Mobile screen): compact layout — title goes into
|
// One Dawn layout for every size: a left-aligned back-chevron header over the
|
||||||
// the back-arrow header, form sits directly below with light padding, no
|
// grouped CreateChat block in a padded Scroll. No centered hero — the curtain
|
||||||
// oversized hero whitespace. The on-screen keyboard otherwise pushed the
|
// (InlineNewChatForm) is the canonical native new-chat surface, and the
|
||||||
// centered hero layout into a visibly long scrollable area. Native tablets,
|
// keyboard no longer fights an oversized hero on short native viewports.
|
||||||
// desktop, and web (any size) keep the original hero-section layout.
|
|
||||||
if (native && screenSize === ScreenSize.Mobile) {
|
|
||||||
return (
|
return (
|
||||||
<Page>
|
<Page>
|
||||||
<PageHeader balance outlined={false}>
|
<PageHeader balance outlined={false}>
|
||||||
|
|
@ -63,42 +50,13 @@ export function DirectCreate() {
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
<Box grow="Yes">
|
|
||||||
<Scroll size="0" hideTrack visibility="Hover">
|
|
||||||
<Box style={{ padding: config.space.S400 }}>
|
|
||||||
<CreateChat defaultUserId={userId} />
|
|
||||||
</Box>
|
|
||||||
</Scroll>
|
|
||||||
</Box>
|
|
||||||
</Page>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Page>
|
|
||||||
{screenSize === ScreenSize.Mobile && (
|
|
||||||
<PageHeader balance outlined={false}>
|
|
||||||
<Box grow="Yes" alignItems="Center" gap="200">
|
|
||||||
<BackRouteHandler>
|
|
||||||
{(onBack) => (
|
|
||||||
<IconButton onClick={onBack}>
|
|
||||||
<Icon src={Icons.ArrowLeft} />
|
|
||||||
</IconButton>
|
|
||||||
)}
|
|
||||||
</BackRouteHandler>
|
|
||||||
</Box>
|
|
||||||
</PageHeader>
|
|
||||||
)}
|
|
||||||
<Box grow="Yes">
|
<Box grow="Yes">
|
||||||
<Scroll hideTrack visibility="Hover">
|
<Scroll hideTrack visibility="Hover">
|
||||||
<PageContent>
|
<PageContent>
|
||||||
<PageContentCenter>
|
<PageContentCenter>
|
||||||
<PageHeroSection>
|
<Box style={{ paddingTop: config.space.S200 }}>
|
||||||
<Box direction="Column" gap="700">
|
|
||||||
<PageHero title={t('Direct.create_chat')} />
|
|
||||||
<CreateChat defaultUserId={userId} />
|
<CreateChat defaultUserId={userId} />
|
||||||
</Box>
|
</Box>
|
||||||
</PageHeroSection>
|
|
||||||
</PageContentCenter>
|
</PageContentCenter>
|
||||||
</PageContent>
|
</PageContent>
|
||||||
</Scroll>
|
</Scroll>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue