1
1
'use client' ;
2
2
3
+ import { useEditorEngine } from '@/components/store/editor' ;
3
4
import { VARIANTS } from '@onlook/fonts' ;
5
+ import { BrandTabValue , LeftPanelTabValue } from '@onlook/models' ;
6
+ import type { Font } from '@onlook/models/assets' ;
4
7
import { Button } from '@onlook/ui/button' ;
5
8
import {
6
9
DropdownMenu ,
@@ -11,31 +14,26 @@ import {
11
14
import { Icons } from '@onlook/ui/icons' ;
12
15
import { Popover , PopoverContent , PopoverTrigger } from '@onlook/ui/popover' ;
13
16
import { Tooltip , TooltipContent , TooltipTrigger } from '@onlook/ui/tooltip' ;
14
- import { Color , convertFontWeight , toNormalCase } from '@onlook/utility' ;
15
- import { memo , useEffect , useState , useRef , useCallback } from 'react' ;
16
- import { useTextControl , type TextAlign } from './hooks/use-text-control' ;
17
- import { ColorPickerContent } from './inputs/color-picker' ;
18
- import { ViewButtons } from './panels/panel-bar/bar' ;
19
- import { InputSeparator } from './separator' ;
20
- import { useEditorEngine } from '@/components/store/editor' ;
21
- import type { Font } from '@onlook/models/assets' ;
22
- import { useColorUpdate } from './hooks/use-color-update' ;
17
+ import { convertFontWeight , toNormalCase } from '@onlook/utility' ;
18
+ import React , { memo , useCallback , useEffect , useRef , useState } from 'react' ;
19
+ import { FontFamily } from '../left-panel/brand-tab/font-panel/font-family' ;
20
+ import { Border } from './dropdowns/border' ;
21
+ import { ColorBackground } from './dropdowns/color-background' ;
22
+ import { Display } from './dropdowns/display' ;
23
23
import { Height } from './dropdowns/height' ;
24
- import { Width } from './dropdowns/width ' ;
24
+ import { Margin } from './dropdowns/margin ' ;
25
25
import { Opacity } from './dropdowns/opacity' ;
26
- import { Display } from './dropdowns/display' ;
27
26
import { Padding } from './dropdowns/padding' ;
28
- import { Margin } from './dropdowns/margin' ;
29
27
import { Radius } from './dropdowns/radius' ;
30
- import { Border } from './dropdowns/border' ;
31
- import { ColorBackground } from './dropdowns/color-background' ;
32
- import React from 'react' ;
33
- import { baseKeymap } from 'prosemirror-commands' ;
34
- import { FontFamily } from '../left-panel/brand-tab/font-panel/font-family' ;
35
- import { BrandTabValue , LeftPanelTabValue } from '@onlook/models' ;
28
+ import { Width } from './dropdowns/width' ;
29
+ import { useColorUpdate } from './hooks/use-color-update' ;
30
+ import { useTextControl , type TextAlign } from './hooks/use-text-control' ;
31
+ import { ColorPickerContent } from './inputs/color-picker' ;
32
+ import { InputColor } from './inputs/input-color' ;
36
33
import { InputIcon } from './inputs/input-icon' ;
37
34
import { InputRadio } from './inputs/input-radio' ;
38
- import { InputColor } from './inputs/input-color' ;
35
+ import { ViewButtons } from './panels/panel-bar/bar' ;
36
+ import { InputSeparator } from './separator' ;
39
37
40
38
const FONT_SIZES = [ 12 , 14 , 16 , 18 , 20 , 24 , 30 , 36 , 48 , 60 , 72 , 96 ] ;
41
39
@@ -240,8 +238,8 @@ const FontWeightSelector = memo(
240
238
key = { weight . value }
241
239
onClick = { ( ) => handleFontWeightChange ( weight . value ) }
242
240
className = { `text-muted-foreground data-[highlighted]:bg-background-tertiary/10 border-border/0 data-[highlighted]:border-border flex items-center justify-between rounded-md border px-2 py-1.5 text-sm data-[highlighted]:text-white cursor-pointer transition-colors duration-150 hover:bg-background-tertiary/20 hover:text-foreground ${ fontWeight === weight . value
243
- ? 'bg-background-tertiary/20 border-border border text-white'
244
- : ''
241
+ ? 'bg-background-tertiary/20 border-border border text-white'
242
+ : ''
245
243
} `}
246
244
>
247
245
{ weight . name }
@@ -265,12 +263,24 @@ const FontSizeSelector = memo(
265
263
fontSize : number ;
266
264
handleFontSizeChange : ( size : number ) => void ;
267
265
} ) => {
266
+ const [ open , setOpen ] = useState ( false ) ;
267
+ const inputRef = useRef < HTMLInputElement > ( null ) ;
268
+
268
269
const adjustFontSize = ( amount : number ) => {
269
270
handleFontSizeChange ( Math . max ( 1 , fontSize + amount ) ) ;
270
271
} ;
271
272
273
+ const handleInputClick = ( ) => {
274
+ setOpen ( true ) ;
275
+ // Use setTimeout to ensure the input is focused after the popover opens
276
+ setTimeout ( ( ) => {
277
+ inputRef . current ?. focus ( ) ;
278
+ inputRef . current ?. select ( ) ;
279
+ } , 0 ) ;
280
+ } ;
281
+
272
282
return (
273
- < DropdownMenu >
283
+ < Popover open = { open } onOpenChange = { setOpen } >
274
284
< Tooltip >
275
285
< div >
276
286
< TooltipTrigger asChild >
@@ -283,8 +293,9 @@ const FontSizeSelector = memo(
283
293
>
284
294
< Icons . Minus className = "h-4 w-4" />
285
295
</ Button >
286
- < DropdownMenuTrigger asChild >
296
+ < PopoverTrigger asChild >
287
297
< input
298
+ ref = { inputRef }
288
299
type = "number"
289
300
value = { fontSize }
290
301
onChange = { ( e ) => {
@@ -293,10 +304,10 @@ const FontSizeSelector = memo(
293
304
handleFontSizeChange ( value ) ;
294
305
}
295
306
} }
296
- onClick = { ( e ) => e . stopPropagation ( ) }
307
+ onClick = { handleInputClick }
297
308
className = "border-border/0 text-muted-foreground hover:bg-background-tertiary/20 hover:border-border data-[state=open]:bg-background-tertiary/20 data-[state=open]:border-border focus:bg-background-tertiary/20 focus:ring-border h-8 max-w-[40px] min-w-[40px] [appearance:textfield] rounded-lg border px-1 text-center text-sm hover:border hover:text-white focus:ring-1 focus:outline-none data-[state=open]:border data-[state=open]:text-white [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
298
309
/>
299
- </ DropdownMenuTrigger >
310
+ </ PopoverTrigger >
300
311
301
312
< Button
302
313
variant = "ghost"
@@ -313,24 +324,29 @@ const FontSizeSelector = memo(
313
324
</ TooltipContent >
314
325
</ div >
315
326
</ Tooltip >
316
- < DropdownMenuContent
327
+ < PopoverContent
317
328
align = "center"
318
329
className = "mt-1 w-[48px] min-w-[48px] rounded-lg p-1"
319
330
>
320
- { FONT_SIZES . map ( ( size ) => (
321
- < DropdownMenuItem
322
- key = { size }
323
- onClick = { ( ) => handleFontSizeChange ( size ) }
324
- className = { `cursor-pointer text-muted-foreground data-[highlighted]:bg-background-tertiary/10 border-border/0 data-[highlighted]:border-border justify-center rounded-md border px-2 py-1 text-sm data-[highlighted]:text-white ${ size === fontSize
331
+ < div className = "grid grid-cols-1 gap-1" >
332
+ { FONT_SIZES . map ( ( size ) => (
333
+ < button
334
+ key = { size }
335
+ onClick = { ( ) => {
336
+ handleFontSizeChange ( size ) ;
337
+ setOpen ( false ) ;
338
+ } }
339
+ className = { `cursor-pointer text-muted-foreground data-[highlighted]:bg-background-tertiary/10 border-border/0 data-[highlighted]:border-border justify-center rounded-md border px-2 py-1 text-sm data-[highlighted]:text-white ${ size === fontSize
325
340
? 'bg-background-tertiary/20 border-border border text-white'
326
341
: ''
327
- } `}
328
- >
329
- { size }
330
- </ DropdownMenuItem >
331
- ) ) }
332
- </ DropdownMenuContent >
333
- </ DropdownMenu >
342
+ } `}
343
+ >
344
+ { size }
345
+ </ button >
346
+ ) ) }
347
+ </ div >
348
+ </ PopoverContent >
349
+ </ Popover >
334
350
) ;
335
351
} ,
336
352
) ;
@@ -353,7 +369,7 @@ const TextAlignSelector = memo(
353
369
< Button
354
370
variant = "ghost"
355
371
size = "toolbar"
356
- className = "text-muted-foreground border-border/0 hover:bg-background-tertiary/20 hover:border-border data-[state=open]:bg-background-tertiary/20 data-[state=open]:border-border flex max-w-9 min-w-9 cursor-pointer items-center justify-center gap-2 rounded-lg border px-2 hover:border hover:text-white focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none active:border-0 data-[state=open]:border data-[state=open]:text-white"
372
+ className = "text-white border-border/0 hover:bg-background-tertiary/20 hover:border-border data-[state=open]:bg-background-tertiary/20 data-[state=open]:border-border flex max-w-9 min-w-9 cursor-pointer items-center justify-center gap-2 rounded-lg border px-2 hover:border hover:text-white focus:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:outline-none active:border-0 data-[state=open]:border data-[state=open]:text-white"
357
373
>
358
374
{ ( ( ) => {
359
375
switch ( textAlign ) {
@@ -389,10 +405,9 @@ const TextAlignSelector = memo(
389
405
< DropdownMenuItem
390
406
key = { value }
391
407
onClick = { ( ) => handleTextAlignChange ( value ) }
392
- className = { `text-muted-foreground data-[highlighted]:bg-background-tertiary/10 border-border/0 data-[highlighted]:border-border rounded-md border px-2 py-1.5 data-[highlighted]:text-foreground cursor-pointer transition-colors duration-150 hover:bg-background-tertiary/20 hover:text-foreground ${
393
- textAlign === value
408
+ className = { `text-muted-foreground data-[highlighted]:bg-background-tertiary/10 border-border/0 data-[highlighted]:border-border rounded-md border px-2 py-1.5 data-[highlighted]:text-foreground cursor-pointer transition-colors duration-150 hover:bg-background-tertiary/20 hover:text-foreground ${ textAlign === value
394
409
? 'bg-background-tertiary/20 border-border border text-white'
395
- : ''
410
+ : ''
396
411
} `}
397
412
>
398
413
< Icon className = "h-4 w-4" />
@@ -749,4 +764,5 @@ export const TextSelected = ({ availableWidth = 0 }: { availableWidth?: number }
749
764
) ;
750
765
} ;
751
766
752
- export { FontFamilySelector , FontWeightSelector , FontSizeSelector , TextColor , TextAlignSelector } ;
767
+ export { FontFamilySelector , FontSizeSelector , FontWeightSelector , TextAlignSelector , TextColor } ;
768
+
0 commit comments