@@ -7,13 +7,12 @@ import {
77 useState ,
88 type JSX ,
99} from 'react' ;
10- import { css , styled } from 'styled-components' ;
10+ import { styled , useTheme } from 'styled-components' ;
1111import { removeCachedSearchResults , useResource , useStore } from '@tomic/react' ;
1212import { DropdownPortalContext } from '../../Dropdown/dropdownContext' ;
1313import * as RadixPopover from '@radix-ui/react-popover' ;
1414import { SearchBoxWindow } from './SearchBoxWindow' ;
1515import { FaExternalLinkAlt , FaSearch , FaTimes } from 'react-icons/fa' ;
16- import { ErrorChip } from '../ErrorChip' ;
1716import { constructOpenURL } from '../../../helpers/navigation' ;
1817import { useNavigateWithTransition } from '../../../hooks/useNavigateWithTransition' ;
1918import { SearchBoxButton } from './SearchBoxButton' ;
@@ -25,6 +24,8 @@ import {
2524} from './searchboxVars' ;
2625import { useDialogTreeContext } from '../../Dialog/dialogContext' ;
2726import { useResourceFormContext } from '../ResourceFormContext' ;
27+ import clsx from 'clsx' ;
28+ import { FaTriangleExclamation } from 'react-icons/fa6' ;
2829
2930export type OnResourceError = ( hasError : boolean ) => void ;
3031
@@ -68,6 +69,7 @@ export function SearchBox({
6869 onResourceError,
6970} : React . PropsWithChildren < SearchBoxProps > ) : JSX . Element {
7071 const store = useStore ( ) ;
72+ const theme = useTheme ( ) ;
7173 const navigate = useNavigateWithTransition ( ) ;
7274 const selectedResource = useResource ( value ) ;
7375 const triggerRef = useRef < HTMLButtonElement > ( null ) ;
@@ -163,9 +165,11 @@ export function SearchBox({
163165 < RadixPopover . Anchor >
164166 < TriggerButtonWrapper
165167 disabled = { ! ! disabled }
166- className = { className }
167- open = { open }
168- invalid = { ! ! visualError }
168+ className = { clsx ( {
169+ [ className ?? '' ] : className ,
170+ invalid : ! ! visualError ,
171+ open : open ,
172+ } ) }
169173 >
170174 { prefix }
171175 < TriggerButton
@@ -174,14 +178,21 @@ export function SearchBox({
174178 disabled = { disabled }
175179 ref = { triggerRef }
176180 tabIndex = { 0 }
177- $empty = { inputValue . length === 0 }
181+ className = { clsx ( { empty : inputValue . length === 0 } ) }
178182 onFocus = { handleTriggerFocus }
179183 onClick = { ( ) => {
180184 setOpen ( true ) ;
181185 setJustFocussed ( true ) ;
182186 } }
183187 id = { id }
184188 >
189+ { ! ! visualError && (
190+ < FaTriangleExclamation
191+ title = 'Error'
192+ size = '0.8rem'
193+ color = { theme . colors . alert }
194+ />
195+ ) }
185196 { value ? (
186197 < ResourceTitle > { title } </ ResourceTitle >
187198 ) : (
@@ -215,9 +226,6 @@ export function SearchBox({
215226 </ >
216227 ) }
217228 { children }
218- { visualError && (
219- < PositionedErrorChip noMovement > { visualError } </ PositionedErrorChip >
220- ) }
221229 </ TriggerButtonWrapper >
222230 </ RadixPopover . Anchor >
223231 < RadixPopover . Portal container = { containerRef . current } >
@@ -242,7 +250,7 @@ export function SearchBox({
242250 ) ;
243251}
244252
245- const TriggerButton = styled . button < { $empty : boolean } > `
253+ const TriggerButton = styled . button `
246254 display: flex;
247255 align-items: center;
248256 padding: 0.5rem;
@@ -255,18 +263,18 @@ const TriggerButton = styled.button<{ $empty: boolean }>`
255263 width: 100%;
256264 overflow: hidden;
257265 cursor: text;
258- color: ${ p => ( p . $empty ? p . theme . colors . textLight : p . theme . colors . text ) } ;
266+ color: ${ p => p . theme . colors . text } ;
267+ &.empty {
268+ color: ${ p => p . theme . colors . textLight } ;
269+ }
259270` ;
260271
261- const TriggerButtonWrapper = styled . div < {
262- invalid : boolean ;
263- disabled : boolean ;
264- open : boolean ;
265- } > `
266- ${ SB_HIGHLIGHT . define ( p =>
267- p . invalid ? p . theme . colors . alert : p . theme . colors . main ,
268- ) }
272+ const TriggerButtonWrapper = styled . div < { disabled : boolean } > `
273+ ${ SB_HIGHLIGHT . define ( p => p . theme . colors . main ) }
269274
275+ &.invalid {
276+ ${ SB_HIGHLIGHT . define ( p => p . theme . colors . alert ) }
277+ }
270278 max-width: 100cqw;
271279
272280 display: flex;
@@ -279,7 +287,8 @@ const TriggerButtonWrapper = styled.div<{
279287 border-bottom-right-radius: ${ p => SB_BOTTOM_RADIUS . var ( p . theme . radius ) } ;
280288
281289 background-color: ${ p => SB_BACKGROUND . var ( p . theme . colors . bg ) } ;
282-
290+ content-visibility: auto;
291+ contain-intrinsic-size: auto 2rem;
283292 &:has(:disabled) {
284293 background-color: ${ props => props . theme . colors . bg1 } ;
285294 opacity: 0.7;
@@ -288,14 +297,13 @@ const TriggerButtonWrapper = styled.div<{
288297 &:has(${ TriggerButton } :hover(), ${ TriggerButton } :focus-visible) {
289298 }
290299
291- &:not(:has(:disabled)):where(:hover, :focus-visible ) {
300+ &:not(:has(:disabled)):where(:hover, :focus-within ) {
292301 border-color: transparent;
293302 box-shadow: 0 0 0 2px ${ SB_HIGHLIGHT . var ( ) } ;
294- ${ p =>
295- ! p . open &&
296- css `
297- z-index: 1000;
298- ` }
303+ z-index: 1000;
304+ &.open {
305+ z-index: 1000;
306+ }
299307 }
300308` ;
301309
@@ -309,9 +317,3 @@ const ResourceTitle = styled.span`
309317const PlaceholderText = styled . span `
310318 color: ${ p => p . theme . colors . textLight } ;
311319` ;
312-
313- const PositionedErrorChip = styled ( ErrorChip ) `
314- position: absolute;
315- top: 2rem;
316- z-index: 1001;
317- ` ;
0 commit comments