🖌️ feat: add animation styles for popovers and tooltips (#8831)

* feat: Update client version to 0.2.2 and add animation styles for popovers and tooltips

* refactor: Remove focus outline styles from Dropdown component

* feat: Update client version to 0.2.3 and add Select component export

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Marco Beretta 2025-08-04 20:44:00 +02:00 committed by GitHub
parent 33834cd484
commit dfdafdbd09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 133 additions and 3 deletions

2
package-lock.json generated
View file

@ -51507,7 +51507,7 @@
},
"packages/client": {
"name": "@librechat/client",
"version": "0.2.1",
"version": "0.2.3",
"devDependencies": {
"@rollup/plugin-alias": "^5.1.0",
"@rollup/plugin-commonjs": "^25.0.2",

View file

@ -1,6 +1,6 @@
{
"name": "@librechat/client",
"version": "0.2.1",
"version": "0.2.3",
"description": "React components for LibreChat",
"main": "dist/index.js",
"module": "dist/index.es.js",

View file

@ -0,0 +1,27 @@
.animate-popover {
transform-origin: top;
opacity: 0;
transition:
opacity 150ms cubic-bezier(0.4, 0, 0.2, 1),
transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
transform: scale(0.95) translateY(-0.5rem);
}
.animate-popover[data-enter] {
opacity: 1;
transform: scale(1) translateY(0);
}
.animate-popover-left {
transform-origin: left;
opacity: 0;
transition:
opacity 150ms cubic-bezier(0.4, 0, 0.2, 1),
transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
transform: scale(0.95) translateX(-0.5rem);
}
.animate-popover-left[data-enter] {
opacity: 1;
transform: scale(1) translateX(0);
}

View file

@ -4,6 +4,7 @@ import { Search, ChevronDown } from 'lucide-react';
import { useMemo, useState, useRef, memo, useEffect } from 'react';
import { SelectRenderer } from '@ariakit/react-core/select/select-renderer';
import type { OptionWithIcon } from '~/common';
import './AnimatePopover.css';
import { cn } from '~/utils';
interface ControlComboboxProps {

View file

@ -0,0 +1,78 @@
.popover-ui {
display: flex;
max-height: min(var(--popover-available-height, 1700px), 1700px);
flex-direction: column;
overflow: auto;
overscroll-behavior: contain;
border-radius: 1rem;
border-width: 1px;
border-style: solid;
border-color: var(--border-light);
background-color: var(--surface-primary);
padding: 0.5rem;
color: var(--text-primary);
box-shadow:
0 10px 15px -3px rgb(0 0 0 / 0.1),
0 4px 6px -4px rgb(0 0 0 / 0.1);
transform-origin: top;
opacity: 0;
transition-property: opacity, scale, translate;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
scale: 0.95;
translate: 0 -0.5rem;
margin-top: 4px;
margin-right: -2px;
}
.popover-animate {
opacity: 0;
transform: scale(0.95) translateY(-0.5rem);
transition:
opacity 150ms cubic-bezier(0.4, 0, 0.2, 1),
transform 150ms cubic-bezier(0.4, 0, 0.2, 1);
}
.popover-animate[data-enter] {
opacity: 1;
transform: scale(1) translateY(0);
}
.popover-ui:focus-visible,
.popover-ui[data-focus-visible] {
outline: var(--bg-surface-hover);
outline-offset: -1px;
}
.popover-ui:where(.dark, .dark *) {
background-color: var(--surface-secondary);
color: var(--text-secondary);
box-shadow:
0 10px 15px -3px rgb(0 0 0 / 0.25),
0 4px 6px -4px rgb(0 0 0 / 0.1);
}
.select-item {
display: flex;
cursor: pointer;
scroll-margin: 0.5rem;
align-items: center;
gap: 0.5rem;
border-radius: 0.5rem;
padding: 0.5rem;
outline: none !important;
}
.select-item[aria-disabled='true'] {
opacity: 0.5;
}
.select-item[data-active-item] {
background-color: var(--surface-hover);
color: var(--text-primary);
}
.popover-ui[data-enter] {
opacity: 1;
scale: 1;
translate: 0;
}

View file

@ -2,6 +2,7 @@ import React from 'react';
import * as Select from '@ariakit/react/select';
import type { Option } from '~/common';
import { cn } from '~/utils/';
import './Dropdown.css';
interface DropdownProps {
value?: string;

View file

@ -2,6 +2,7 @@ import React from 'react';
import * as Ariakit from '@ariakit/react';
import type * as t from '~/common';
import { cn } from '~/utils';
import './Dropdown.css';
interface DropdownProps {
keyPrefix?: string;

View file

@ -8,6 +8,7 @@ import {
SelectPopover,
SelectProvider,
} from '@ariakit/react';
import './AnimatePopover.css';
import { cn } from '~/utils';
interface MultiSelectProps<T extends string> {

View file

@ -1,7 +1,6 @@
import * as React from 'react';
import * as SelectPrimitive from '@radix-ui/react-select';
import { CaretSortIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon } from '@radix-ui/react-icons';
import { cn } from '~/utils';
// @ts-ignore - Radix UI type conflicts with React types

View file

@ -0,0 +1,20 @@
.tooltip {
z-index: 50;
cursor: pointer;
border-radius: 0.275rem;
background-color: var(--surface-primary);
padding-top: 0.25rem;
padding-bottom: 0.25rem;
padding-left: 0.5rem;
padding-right: 0.5rem;
font-size: 1rem;
line-height: 1.5rem;
color: black;
box-shadow: 0 2px 4px 0 rgb(0 0 0 / 0.25);
}
.tooltip:where(.dark, .dark *) {
background-color: var(--surface-primary);
color: white;
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.35);
}

View file

@ -2,6 +2,7 @@ import * as Ariakit from '@ariakit/react';
import { AnimatePresence, motion } from 'framer-motion';
import { forwardRef, useMemo } from 'react';
import { cn } from '~/utils';
import './Tooltip.css';
interface TooltipAnchorProps extends Ariakit.TooltipAnchorProps {
description: string;

View file

@ -30,6 +30,7 @@ export * from './Progress';
export * from './InputOTP';
export * from './MultiSearch';
export * from './Resizable';
export * from './Select';
export { default as Radio } from './Radio';
export { default as Badge } from './Badge';
export { default as Combobox } from './Combobox';