diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5500729..c151ee8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,7 +8,7 @@ and this project adheres to
## [Unreleased]
-- 🐛(fix) broken staging css
+- ✨(ui) fix retour global ui
### Changed
diff --git a/src/frontend/apps/conversations/src/components/ToastProvider.tsx b/src/frontend/apps/conversations/src/components/ToastProvider.tsx
index b4eddf9..8412b4c 100644
--- a/src/frontend/apps/conversations/src/components/ToastProvider.tsx
+++ b/src/frontend/apps/conversations/src/components/ToastProvider.tsx
@@ -71,7 +71,7 @@ export const ToastProvider = ({ children }: ToastProviderProps) => {
{showInput && (
void;
placeholder?: string;
@@ -19,7 +17,6 @@ type Props = {
onClear?: () => void;
};
export const QuickSearchInput = ({
- loading,
inputValue,
onFilter,
placeholder,
@@ -30,6 +27,37 @@ export const QuickSearchInput = ({
const { t } = useTranslation();
const { spacingsTokens } = useCunninghamTheme();
+ const [localValue, setLocalValue] = useState(inputValue || '');
+
+ const debouncedFilter = useCallback(
+ (value: string) => {
+ let timeoutId: NodeJS.Timeout;
+
+ const debounce = () => {
+ clearTimeout(timeoutId);
+ timeoutId = setTimeout(() => {
+ onFilter?.(value);
+ }, 150);
+ };
+
+ debounce();
+ },
+ [onFilter],
+ );
+
+ const handleChange = useCallback(
+ (value: string) => {
+ setLocalValue(value);
+ debouncedFilter(value);
+ },
+ [debouncedFilter],
+ );
+
+ const handleClear = useCallback(() => {
+ setLocalValue('');
+ onClear?.();
+ }, [onClear]);
+
if (children) {
return (
<>
@@ -47,12 +75,13 @@ export const QuickSearchInput = ({
$gap={spacingsTokens['2xs']}
$css={`
position: relative;
+ justify-content: space-between;
border-radius: 4px;
margin: 12px 12px 0 12px;
border: 1px solid #CFD5DE;
- background-color: #EEF1F4;
+ background-color: #eff1f5;
padding: 6px 8px;
- &:focus-within {
+ &:focus-within, &:hover {
border: 2px solid #3E5DE7;
padding: 5px 7px;
}
@@ -69,29 +98,42 @@ export const QuickSearchInput = ({
}
`}
>
- {!loading && }
- {loading && }
-
- 0 && onClear ? 1 : 0};
- transition: opacity 0.3s cubic-bezier(1, 0, 0, 1);
- top: 10px;
- right: 10px;
- z-index: 1000;`}
- onClick={onClear}
+
+
+
+
+ {
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ handleClear();
+ }
+ }}
+ role="button"
+ tabIndex={0}
aria-label={t('Clear search')}
- />
+ $css={`cursor: pointer;
+ opacity: ${localValue && localValue.length > 0 && onClear ? 1 : 0};
+ transition: opacity 0.3s cubic-bezier(1, 0, 0, 1);
+ right: 10px;
+ border-radius: 4px;
+ padding: 7px;
+ background-color: #e4e6ea;
+ z-index: 1000;
+ &:focus {
+ outline: 2px solid #3E5DE7;
+ outline-offset: 2px;
+ }`}
+ >
+
+
>
);
diff --git a/src/frontend/apps/conversations/src/features/auth/components/ButtonLogin.tsx b/src/frontend/apps/conversations/src/features/auth/components/ButtonLogin.tsx
index 8f94633..ad46b09 100644
--- a/src/frontend/apps/conversations/src/features/auth/components/ButtonLogin.tsx
+++ b/src/frontend/apps/conversations/src/features/auth/components/ButtonLogin.tsx
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import { css } from 'styled-components';
import { BoxButton, Icon } from '@/components';
+import { useResponsiveStore } from '@/stores';
import ProConnectImg from '../assets/button-proconnect.svg';
import { useAuth } from '../hooks';
@@ -11,6 +12,7 @@ import { gotoLogin, gotoLogout } from '../utils';
export const ButtonLogin = () => {
const { t } = useTranslation();
const { authenticated } = useAuth();
+ const { isDesktop } = useResponsiveStore();
if (!authenticated) {
return (
@@ -29,7 +31,7 @@ export const ButtonLogin = () => {
}
+ icon={!isDesktop ? : ''}
aria-label={t('Logout')}
className="--docs--button-logout"
>
diff --git a/src/frontend/apps/conversations/src/features/chat/components/Chat.tsx b/src/frontend/apps/conversations/src/features/chat/components/Chat.tsx
index 3058e77..5465050 100644
--- a/src/frontend/apps/conversations/src/features/chat/components/Chat.tsx
+++ b/src/frontend/apps/conversations/src/features/chat/components/Chat.tsx
@@ -564,7 +564,7 @@ export const Chat = ({
$direction="row"
$align="center"
$gap="4px"
- className="c__button--neutral"
+ className="c__button--neutral action-chat-button"
onClick={() => copyToClipboard(message.content)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -594,7 +594,7 @@ export const Chat = ({
$direction="row"
$align="center"
$gap="4px"
- className="c__button--neutral"
+ className="c__button--neutral action-chat-button"
onClick={() => openSources(message.id)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
@@ -660,7 +660,7 @@ export const Chat = ({
{
const { t } = useTranslation();
const fileInputRef = useRef(null);
+ const textareaRef = useRef(null);
const [isDragActive, setIsDragActive] = useState(false);
const { isDesktop, isMobile } = useResponsiveStore();
const [currentSuggestionIndex, setCurrentSuggestionIndex] = useState(0);
+ const [isResetting, setIsResetting] = useState(false);
const suggestions = [
- 'Ask a question',
- 'Turn this list into bullet points',
- 'Write a short product description',
- 'Find recent news about...',
+ t('Ask a question'),
+ t('Turn this list into bullet points'),
+ t('Write a short product description'),
+ t('Find recent news about...'),
];
useEffect(() => {
if (messagesLength === 0) {
const interval = setInterval(() => {
- setCurrentSuggestionIndex((prev) => (prev + 1) % suggestions.length);
+ setCurrentSuggestionIndex((prev) => {
+ if (prev === suggestions.length - 1) {
+ return suggestions.length;
+ }
+ return prev + 1;
+ });
}, 3000);
return () => clearInterval(interval);
}
}, [messagesLength, suggestions.length]);
+ useEffect(() => {
+ if (currentSuggestionIndex === suggestions.length) {
+ const timeout = setTimeout(() => {
+ setIsResetting(true);
+ setCurrentSuggestionIndex(0);
+ setTimeout(() => setIsResetting(false), 50);
+ }, 500);
+ return () => clearTimeout(timeout);
+ }
+ }, [currentSuggestionIndex, suggestions.length]);
+
+ useEffect(() => {
+ if (textareaRef.current && messagesLength === 0 && status === 'ready') {
+ textareaRef.current.focus();
+ }
+ }, [messagesLength, status]);
+
+ useEffect(() => {
+ if (textareaRef.current && status === 'ready' && !input) {
+ textareaRef.current.focus();
+ }
+ }, [status, input]);
+
return (
)}
@@ -295,13 +339,13 @@ export const InputChat = ({
type="button"
onClick={() => fileInputRef.current?.click()}
aria-label={t('Add attach file')}
- className="c__button--neutral"
+ className="c__button--neutral attach-file-button"
icon={
}
>
@@ -349,7 +393,6 @@ export const InputChat = ({
$css={`
color: ${forceWebSearch ? 'var(--c--theme--colors--primary-600) !important' : 'var(--c--theme--colors--greyscale-600)'}
`}
- $size="24px"
/>
}
>
@@ -384,7 +427,7 @@ export const InputChat = ({
{
aria-label={t('Open the header menu')}
color="primary-text"
icon={}
+ className="mobile-no-focus"
/>
);
};
diff --git a/src/frontend/apps/conversations/src/features/header/components/Header.tsx b/src/frontend/apps/conversations/src/features/header/components/Header.tsx
index 4c9c61f..93f9891 100644
--- a/src/frontend/apps/conversations/src/features/header/components/Header.tsx
+++ b/src/frontend/apps/conversations/src/features/header/components/Header.tsx
@@ -67,7 +67,7 @@ export const Header = () => {
color={colorsTokens['primary-text']}
/>
- {isDesktop && }
+ {isDesktop && }
{!isDesktop ? (
@@ -77,6 +77,7 @@ export const Header = () => {
router.push('/');
togglePanel(false);
}}
+ className="mobile-no-focus"
aria-label={t('New chat')}
color="primary-text"
icon={}
diff --git a/src/frontend/apps/conversations/src/features/home/components/HomeHeader.tsx b/src/frontend/apps/conversations/src/features/home/components/HomeHeader.tsx
index 71a3c87..65b9f83 100644
--- a/src/frontend/apps/conversations/src/features/home/components/HomeHeader.tsx
+++ b/src/frontend/apps/conversations/src/features/home/components/HomeHeader.tsx
@@ -22,7 +22,7 @@ export const HomeHeader = () => {
const { t } = useTranslation();
const { themeTokens, spacingsTokens, colorsTokens } = useCunninghamTheme();
const logo = themeTokens.logo;
- const { isSmallMobile } = useResponsiveStore();
+ const { isSmallMobile, isDesktop } = useResponsiveStore();
return (
{
color={colorsTokens['primary-text']}
/>
- {!isSmallMobile && }
+ {isDesktop && }
{!isSmallMobile && (
diff --git a/src/frontend/apps/conversations/src/features/left-panel/components/ConversationItemActions.tsx b/src/frontend/apps/conversations/src/features/left-panel/components/ConversationItemActions.tsx
index 6e06f29..b2d1c41 100644
--- a/src/frontend/apps/conversations/src/features/left-panel/components/ConversationItemActions.tsx
+++ b/src/frontend/apps/conversations/src/features/left-panel/components/ConversationItemActions.tsx
@@ -32,15 +32,31 @@ export const ConversationItemActions = ({
<>
{
+ if (e.key === 'Enter' || e.key === ' ') {
+ e.preventDefault();
+ // Le DropdownMenu gère l'ouverture
+ }
+ }}
$css={css`
display: block;
width: 24px;
height: 24px;
padding: 4px;
border-radius: 4px;
+ cursor: pointer;
&:hover {
background-color: #e1e3e7 !important;
}
+ &:focus {
+ outline: 2px solid #3e5de7;
+ outline-offset: 2px;
+ }
`}
>
diff --git a/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelContent.tsx b/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelContent.tsx
index 21048aa..b2341ff 100644
--- a/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelContent.tsx
+++ b/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelContent.tsx
@@ -24,7 +24,21 @@ export const LeftPanelContent = () => {
)}
-
+
+
+
{!hasSearch && }
);
diff --git a/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelSearch.tsx b/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelSearch.tsx
index 0690e15..c47c553 100644
--- a/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelSearch.tsx
+++ b/src/frontend/apps/conversations/src/features/left-panel/components/LeftPanelSearch.tsx
@@ -28,19 +28,11 @@ export const LeftPanelSearch = ({ onSearchChange }: LeftPanelSearchProps) => {
const currentConversationId = params?.id as string;
- const {
- data,
- isFetching,
- isRefetching,
- isLoading,
- fetchNextPage,
- hasNextPage,
- } = useInfiniteConversations({
+ const { data, fetchNextPage, hasNextPage } = useInfiniteConversations({
page: 1,
title: search,
});
- const loading = isFetching || isRefetching || isLoading;
const handleInputSearch = useDebouncedCallback((value: string) => {
setSearch(value);
onSearchChange?.(value.length > 0);
@@ -71,7 +63,6 @@ export const LeftPanelSearch = ({ onSearchChange }: LeftPanelSearchProps) => {
return (
{conversation.title || t('Untitled conversation')}
diff --git a/src/frontend/apps/conversations/src/pages/globals.css b/src/frontend/apps/conversations/src/pages/globals.css
index 0919171..22c1a9e 100644
--- a/src/frontend/apps/conversations/src/pages/globals.css
+++ b/src/frontend/apps/conversations/src/pages/globals.css
@@ -69,6 +69,11 @@ nextjs-portal {
border: 1px solid rgb(0 0 0 / 16%) !important;
}
+.c__button--primary:active,
+.c__button--primary.c__button--active {
+ border: none;
+}
+
.c__button--neutral {
transition: background-color 0.4s !important;
color: var(--c--theme--colors--greyscale-550) !important;
@@ -80,11 +85,26 @@ nextjs-portal {
padding: 4px !important;
padding-right: 9px !important;
border-radius: 4px !important;
+
+ @media (width <= 768px) {
+ padding-right: 4px !important;
+ }
}
-.c__button--neutral:hover,
-.c__button--neutral:active,
-.c__button--neutral:focus {
+.c__button--neutral.research-web-button,
+.c__button--neutral.attach-file-button {
+ padding: 9px !important;
+}
+
+.c__button--neutral.action-chat-button span,
+.c__button--neutral.research-web-button .c__button__icon span,
+.c__button--neutral.attach-file-button .c__button__icon span {
+ @media (width <= 768px) {
+ font-size: 19px !important;
+ }
+}
+
+.c__button--neutral:hover {
background-color: #f2f5f4 !important;
}
@@ -139,3 +159,15 @@ ul a:hover {
background-color: var(--c--theme--colors--greyscale-550) !important;
color: var(--c--theme--colors--greyscale-050) !important;
}
+
+@media (width <= 768px) {
+ .mobile-no-focus:hover {
+ background-color: transparent !important;
+ }
+}
+
+.c__button--feedback {
+ @media (width <= 1150px) {
+ display: none !important;
+ }
+}