pacocoursey / cmdk

Fast, unstyled command menu React component.
https://cmdk.paco.me
MIT License
9.17k stars 262 forks source link

Why is Command.Empty disabled on first render? #149

Closed CapitaineToinon closed 5 months ago

CapitaineToinon commented 1 year ago

After spending a good 30 minutes trying to debug why I couldn't get the Empty element to show up asap when the command opens, I ended up searching to code to find that it is explicitly disabled on first render.

https://github.com/pacocoursey/cmdk/blob/main/cmdk/src/index.tsx#L822-L832

I didn't find any documentation about this and this doesn't seems to be configurable. I would like to have the empty warning show up asap, how can I achieve this? Why is this disabled on first render?

CapitaineToinon commented 1 year ago

I was using cmdk with shadcn/ui, I just copied the Empty implementation and removed the ref logic

const CommandEmpty = React.forwardRef<
    HTMLDivElement,
    React.ComponentProps<typeof CommandPrimitive.Empty>
>(({ className, ...props }, forwardedRef) => {
    const render = useCommandState((state) => state.filtered.count === 0)

    if (!render) return null

    return (
        <div
            ref={forwardedRef}
            className={cn('py-6 text-center text-sm', className)}
            cmdk-empty=""
            role="presentation"
            {...props}
        />
    )
})
donfour commented 11 months ago

following, also interested

cody-ta commented 10 months ago

I need this feature.

soags commented 7 months ago

The recommended code in the README under "Use inside Popover" does not work with Empty. https://github.com/pacocoursey/cmdk#use-inside-popover

import * as Popover from '@radix-ui/react-popover'

return (
  <Popover.Root>
    <Popover.Trigger>Toggle popover</Popover.Trigger>    
    <Popover.Content>
      <Command>
        <Command.Input />
        <Command.Empty>Empty</Command.Empty>
        <Command.List></Command.List>
      </Command>
    </Popover.Content>
  </Popover.Root>
)

What is the reason for needing to skip the first render? If there is a reason, it would be nice to be able to change the behavior with an option.

import * as Popover from '@radix-ui/react-popover'

return (
  <Popover.Root>
    <Popover.Trigger>Toggle popover</Popover.Trigger>    
    <Popover.Content>
      <Command>
        <Command.Input />
        <Command.Empty firstRender={true}>Empty</Command.Empty>
        <Command.List></Command.List>
      </Command>
    </Popover.Content>
  </Popover.Root>
)

type EmptyProps = Children & DivProps & {
  firstRender?: boolean
}

const Empty = React.forwardRef<HTMLDivElement, EmptyProps>(({ firstRender= false, ...props}, forwardedRef) => {
  const isFirstRender = React.useRef(true)
  const render = useCmdk((state) => state.filtered.count === 0)

  React.useEffect(() => {
    isFirstRender.current = false
  }, [])

  if ((!firstRender && isFirstRender.current) || !render) return null
  return <div ref={forwardedRef} {...props} cmdk-empty="" role="presentation" />
})