<p align="center">
<img src="./website/public/og.png" />
</p>
# ⌘K ![cmdk minzip package size](https://img.shields.io/bundlephobia/minzip/cmdk) ![cmdk package version](https://img.shields.io/npm/v/cmdk.svg?colorB=green)
⌘K is a command menu React component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically. ⌘K supports a fully composable API <sup>[How?](/ARCHITECTURE.md)</sup>, so you can wrap items in other components or even as static JSX.
Demo and examples: [cmdk.paco.me](https://cmdk.paco.me)
## Install
```bash
npm install cmdk
```
## Use
```tsx
import { Command } from 'cmdk'
const CommandMenu = () => {
return (
<Command label="Command Menu">
<Command.Input />
<Command.List>
<Command.Empty>No results found.</Command.Empty>
<Command.Group heading="Letters">
<Command.Item>a</Command.Item>
<Command.Item>b</Command.Item>
<Command.Separator />
<Command.Item>c</Command.Item>
</Command.Group>
<Command.Item>Apple</Command.Item>
</Command.List>
</Command>
)
}
```
Or in a dialog:
```tsx
import { Command } from 'cmdk'
const CommandMenu = () => {
const [open, setOpen] = React.useState(false)
// Toggle the menu when ⌘K is pressed
React.useEffect(() => {
const down = (e) => {
if (e.key === 'k' && e.metaKey) {
setOpen((open) => !open)
}
}
document.addEventListener('keydown', down)
return () => document.removeEventListener('keydown', down)
}, [])
return (
<Command.Dialog open={open} onOpenChange={setOpen} label="Global Command Menu">
<Command.Input />
<Command.List>
<Command.Empty>No results found.</Command.Empty>
<Command.Group heading="Letters">
<Command.Item>a</Command.Item>
<Command.Item>b</Command.Item>
<Command.Separator />
<Command.Item>c</Command.Item>
</Command.Group>
<Command.Item>Apple</Command.Item>
</Command.List>
</Command.Dialog>
)
}
```
## Parts and styling
All parts forward props, including `ref`, to an appropriate element. Each part has a specific data-attribute (starting with `cmdk-`) that can be used for styling.
### Command `[cmdk-root]`
Render this to show the command menu inline, or use [Dialog](#dialog-cmdk-dialog-cmdk-overlay) to render in a elevated context. Can be controlled with the `value` and `onValueChange` props.
> **Note**
>
> Values are always converted to lowercase and trimmed. Use `apple`, not `Apple`.
```tsx
const [value, setValue] = React.useState('apple')
return (
<Command value={value} onValueChange={setValue}>
<Command.Input />
<Command.List>
<Command.Item>Orange</Command.Item>
<Command.Item>Apple</Command.Item>
</Command.List>
</Command>
)
```
You can provide a custom `filter` function that is called to rank each item. Both strings are normalized as lowercase and trimmed.
```tsx
<Command
filter={(value, search) => {
if (value.includes(search)) return 1
return 0
}}
/>
```
Or disable filtering and sorting entirely:
```tsx
<Command shouldFilter={false}>
<Command.List>
{filteredItems.map((item) => {
return (
<Command.Item key={item} value={item}>
{item}
</Command.Item>
)
})}
</Command.List>
</Command>
```
You can make the arrow keys wrap around the list (when you reach the end, it goes back to the first item) by setting the `loop` prop:
<Command loop />
### Dialog `[cmdk-dialog]` `[cmdk-overlay]`
Props are forwarded to [Command](#command-cmdk-root). Composes Radix UI's Dialog component. The overlay is always rendered. See the [Radix Documentation](https://www.radix-ui.com/docs/primitives/components/dialog) for more information. Can be controlled with the `open` and `onOpenChange` props.
```tsx
const [open, setOpen] = React.useState(false)
return (
<Command.Dialog open={open} onOpenChange={setOpen}>
...
</Command.Dialog>
)
```
You can provide a `container` prop that accepts an HTML element that is forwarded to Radix UI's Dialog Portal component to specify which element the Dialog should portal into (defaults to `body`). See the [Radix Documentation](https://www.radix-ui.com/docs/primitives/components/dialog#portal) for more information.
```tsx
const containerElement = React.useRef(null)
return (
<>
<Command.Dialog container={containerElement.current} />
<div ref={containerElement} />
</>
)
```
### Input `[cmdk-input]`
All props are forwarded to the underlying `input` element. Can be controlled with the `value` and `onValueChange` props.
```tsx
const [search, setSearch] = React.useState('')
return <Command.Input value={search} onValueChange={setSearch} />
```
### List `[cmdk-list]`
Contains items and groups. Animate height using the `--cmdk-list-height` CSS variable.
```css
[cmdk-list] {
min-height: 300px;
height: var(--cmdk-list-height);
max-height: 500px;
transition: height 100ms ease;
}
```
To scroll item into view earlier near the edges of the viewport, use scroll-padding:
```css
[cmdk-list] {
scroll-padding-block-start: 8px;
scroll-padding-block-end: 8px;
}
```
### Item `[cmdk-item]` `[data-disabled?]` `[data-selected?]`
Item that becomes active on pointer enter. You should provide a unique `value` for each item, but it will be automatically inferred from the `.textContent`.
```tsx
<Command.Item
onSelect={(value) => console.log('Selected', value)}
// Value is implicity "apple" because of the provided text content
>
Apple
</Command.Item>
```
### Group `[cmdk-group]` `[hidden?]`
Groups items together with the given `heading` (`[cmdk-group-heading]`).
```tsx
<Command.Group heading="Fruit">
<Command.Item>Apple</Command.Item>
</Command.Group>
```
Groups will not unmount from the DOM, rather the `hidden` attribute is applied to hide it from view. This may be relevant in your styling.
### Separator `[cmdk-separator]`
Visible when the search query is empty or `alwaysRender` is true, hidden otherwise.
### Empty `[cmdk-empty]`
Automatically renders when there are no results for the search query.
### Loading `[cmdk-loading]`
You should conditionally render this with `progress` while loading asynchronous items.
```tsx
const [loading, setLoading] = React.useState(false)
return <Command.List>{loading && <Command.Loading>Hang on…</Command.Loading>}</Command.List>
```
### `useCommandState(state => state.selectedField)`
Hook that composes [`useSyncExternalStore`](https://reactjs.org/docs/hooks-reference.html#usesyncexternalstore). Pass a function that returns a slice of the command menu state to re-render when that slice changes. This hook is provided for advanced use cases and should not be commonly used.
A good use case would be to render a more detailed empty state, like so:
```tsx
const search = useCommandState((state) => state.search)
return <Command.Empty>No results found for "{search}".</Command.Empty>
```
## Examples
Code snippets for common use cases.
### Nested items
Often selecting one item should navigate deeper, with a more refined set of items. For example selecting "Change theme…" should show new items "Dark theme" and "Light theme". We call these sets of items "pages", and they can be implemented with simple state:
```tsx
const ref = React.useRef(null)
const [open, setOpen] = React.useState(false)
const [search, setSearch] = React.useState('')
const [pages, setPages] = React.useState([])
const page = pages[pages.length - 1]
return (
<Command
onKeyDown={(e) => {
// Escape goes to previous page
// Backspace goes to previous page when search is empty
if (e.key === 'Escape' || (e.key === 'Backspace' && !search)) {
e.preventDefault()
setPages((pages) => pages.slice(0, -1))
}
}}
>
<Command.Input value={search} onValueChange={setSearch} />
<Command.List>
{
没有合适的资源?快使用搜索试试~ 我知道了~
快速、无样式的命令菜单React组件。_TypeScript_SCSS_下载.zip
共69个文件
tsx:19个
ts:11个
json:9个
1.该资源内容由用户上传,如若侵权请联系客服进行举报
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
2.虚拟产品一经售出概不退款(资源遇到问题,请及时私信上传者)
版权申诉
0 下载量 123 浏览量
2023-04-21
11:02:53
上传
评论
收藏 523KB ZIP 举报
温馨提示
快速、无样式的命令菜单React组件。_TypeScript_SCSS_下载.zip
资源推荐
资源详情
资源评论
收起资源包目录
快速、无样式的命令菜单React组件。_TypeScript_SCSS_下载.zip (69个子文件)
cmdk-main
website
pages
_app.tsx 1KB
index.tsx 14KB
_document.tsx 499B
vercel.json 215B
next-env.d.ts 201B
next.config.js 137B
styles
index.module.scss 9KB
globals.scss 4KB
cmdk
framer.scss 5KB
linear.scss 3KB
raycast.scss 10KB
vercel.scss 3KB
components
icons
index.tsx 7KB
icons.module.scss 953B
cmdk
vercel.tsx 7KB
raycast.tsx 11KB
linear.tsx 6KB
framer.tsx 12KB
code
index.tsx 2KB
code.module.scss 1KB
index.ts 168B
package.json 1KB
public
vercel.svg 1KB
inter-var-latin.woff2 36KB
paco.png 6KB
grid.svg 2KB
robots.txt 24B
rauno.jpeg 30KB
og.png 336KB
line.svg 2KB
favicon.svg 4KB
.eslintrc.json 40B
.gitignore 371B
tsconfig.json 529B
README.md 2KB
LICENSE.md 1KB
.github
workflows
test.yml 675B
.prettierrc.js 115B
pnpm-workspace.yaml 46B
.prettierignore 38B
package.json 644B
pnpm-lock.yaml 135KB
playwright.config.ts 678B
test
style.css 52B
pages
_app.tsx 119B
dialog.tsx 625B
keybinds.tsx 1KB
index.tsx 594B
item.tsx 1KB
props.tsx 2KB
item-advanced.tsx 652B
huge.tsx 786B
group.tsx 1KB
next-env.d.ts 201B
dialog.test.ts 356B
basic.test.ts 2KB
props.test.ts 2KB
package.json 331B
group.test.ts 1KB
tsconfig.json 531B
keybind.test.ts 6KB
item.test.ts 3KB
cmdk
src
index.tsx 28KB
package.json 607B
tsup.config.ts 180B
.gitignore 155B
tsconfig.json 534B
README.md 12KB
ARCHITECTURE.md 4KB
共 69 条
- 1
资源评论
快撑死的鱼
- 粉丝: 1w+
- 资源: 9156
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功