Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Fast, composable, unstyled command menu for Angular. Directly inspired from pacocoursey/cmdk

License

NotificationsYou must be signed in to change notification settings

ngxpert/cmdk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


MITcommitizenPRsstyled with prettierAll Contributorsngxpert-libspectatorsemantic-releasenpm

Fast, composable, unstyled command menu for Angular. Directly inspired frompacocoursey/cmdk

@ngxpert/cmdk

@ngxpert/cmdk is a command menu Angular component that can also be used as an accessible combobox. You render items, it filters and sorts them automatically. @ngxpert/cmdk supports a fully composable API, so you can wrap items in other components or even as static HTML.

Demo and examples:ngxpert.github.io/cmdk

Features

  • 🎨 Un-styled, so that you can provide your own styles easily
  • 🥙 Provides wrapper, so that you can pass your own template, component or static HTML
  • 🔍 Default filtering present
  • 🖼️Drop in stylesheet themes provided
  • ♿ Accessible

Compatibility with Angular Versions

@ngxpert/cmdkAngular
1.x>=16 <17
2.x>=17 <18
3.x>=18
For older versions

You can use@ngneat/cmdk package fromnpm.

Installation

NPM

## First, install dependencies## For Angular v16npm install @ngneat/overview@5 @ngneat/until-destroy@10 @angular/cdk@16## For Angular v17npm install @ngneat/overview@6 @ngneat/until-destroy@10 @angular/cdk@17## For Angular v18npm install @ngneat/overview@6 @ngneat/until-destroy@10 @angular/cdk@18## For Angular v19npm install @ngneat/overview@6 @ngneat/until-destroy@10 @angular/cdk@19## Then librarynpm install @ngxpert/cmdk

Yarn

Same asnpm, just instead ofnpm install, writeyarn add.

Usage

1. Setup

1.1 Module Setup

This is taken care with ng add @ngxpert/cmdk

import{CmdkModule}from'@ngxpert/cmdk';@NgModule({imports:[CmdkModule,],})exportclassAppModule{}

1.2 Standalone Setup

import{AppComponent}from'./src/app.component';import{CommandComponent,GroupComponent,InputDirective,ItemDirective,ListComponent,EmptyDirective,SeparatorComponent}from'@ngxpert/cmdk';@Component({selector:'app-root',standalone:true,imports:[CommandComponent,InputDirective,ListComponent,GroupComponent,ItemDirective,EmptyDirective,SeparatorComponent],})

2. Start using it

<cmdk-command><inputcmdkInput/><div*cmdkEmpty>No results found.</div><cmdk-list><cmdk-grouplabel="Letters"><buttoncmdkItem>a</button><buttoncmdkItem>b</button><cmdk-separator></cmdk-separator><buttoncmdkItem>c</button></cmdk-group></cmdk-list><buttoncmdkItem>Apple</button></cmdk-command>

Components

Each component has a specific class (starting withcmdk-) that can be used for styling.

Command

Render this to show the command menu.

SelectorClass
cmdk-command.cmdk-command

Properties

NameDescription
@Input() ariaLabel: stringAccessible Label for this command menu. Not shown visibly.
@Input() filter?: ((value: string, search: string) => boolean)Custom filter function for whether each command menu item should matches the given search query. It should return aboolean, false being hidden entirely. You can passnull to disable default filtering.
Default:(value, search) => value.toLowerCase().includes(search.toLowerCase())
@Input() value?: stringOptional controlled state of the selected command menu item.
@Input() loading?: booleanOptional indicator to show loader
@Input() loop?: booleanOptionally set totrue to turn on looping around when using the arrow keys.
@Output() valueChanged: EventEmitter<string>Event handler called when the selected item of the menu changes.

Input

Render this to show the command input.

SelectorClass
input[cmdkinput].cmdk-input

Properties

NameDescription
@Input() updateOn: 'blur' | 'change' | 'input'Optional indicator to provide event listener when filtering should happen.
Default:input

List

Contains items and groups.

SelectorClass
cmdk-list.cmdk-list

Animate height using the--cmdk-list-height CSS variable.

.cmdk-list {min-height:300px;height:var(--cmdk-list-height);max-height:500px;transition: height100ms ease;}

To scroll item into view earlier near the edges of the viewport, use scroll-padding:

.cmdk-list {scroll-padding-block-start:8px;scroll-padding-block-end:8px;}

Properties

NameDescription
@Input() ariaLabel?: stringAccessible Label for this command menu. Not shown visibly.

Item

Item that becomes active on pointer enter. You should provide a uniquevalue for each item, but it will be automatically inferred from the.textContent.

Items will not unmount from the DOM, rather thecmdk-hidden attribute is applied to hide it from view. This may be relevant in your styling.

StateSelectorClass
Default[cmdkItem].cmdk-item
Active[cmdkItem][aria-selected].cmdk-item-active
Filtered[cmdkItem].cmdk-item-filtered
Disabled[cmdkItem].cmdk-item-disabled
Hidden (not-filtered)[cmdkItem][cmdk-hidden]``

Properties

NameDescription
value: string | undefined;Contextual Value of the list-item
@Input() disabled: booleanContextually mark the item as disabled. Keyboard navigation will skip this item.
@Input() filtered: booleanContextually mark the item as filtered.
@Output() selected: EventEmitter<void>Event handler called when the item is selected

Group

Groups items together with the given label (.cmdk-group-label).

SelectorClass
cmdk-group.cmdk-group

Groups will not unmount from the DOM, rather thecmdk-hidden attribute is applied to hide it from view. This may be relevant in your styling.

Properties

NameDescription
@Input() label: ContentLabel for this command group. Can be HTML string
@Input() ariaLabel?: stringAccessible Label for this command menu. Not shown visibly.

Empty

Automatically renders when there are no results for the search query.

SelectorClass
*cmdkEmpty.cmdk-empty

Loader

This will be conditionally renderer when you passloading=true withcmdk-command

SelectorClass
*cmdkLoader.cmdk-loader

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:

<cmdk-command(keydown)="onKeyDown($event)"><inputcmdkInput(input)="setSearch($event)"/><ng-container*ngIf="!page"><buttoncmdkItem(selected)="setPages('projects')">Search projects...</button><buttoncmdkItem(selected)="setPages('teams')">Join a team...</button></ng-container><ng-container*ngIf="page === 'projects'"><buttoncmdkItem>Project A</button><buttoncmdkItem>Project B</button></ng-container><ng-container*ngIf="page === 'teams'"><buttoncmdkItem>Team 1</button><buttoncmdkItem>Team 2</button></ng-container></cmdk-command>
pages:Array<string>=[];search='';getpage(){returnthis.pages[this.pages.length-1];}onKeyDown(e:KeyboardEvent){// Escape goes to previous page// Backspace goes to previous page when search is emptyif(e.key==='Escape'||(e.key==='Backspace'&&!this.search)){e.preventDefault();this.pages=this.pages.slice(0,-1);}}setSearch(ev:Event){this.search=(ev.targetasHTMLInputElement)?.value;}setPages(page:string){this.pages.push(page);}

Asynchronous results

Render the items as they become available. Filtering and sorting will happen automatically.

<cmdk-command[loading]="loading"><inputcmdkInput/><div*cmdkLoader>Fetching words...</div><buttoncmdkItem*ngFor="let item of items"[value]="item">    {{item}}</button></cmdk-command>
loading=false;getItems(){this.loading=true;setTimeout(()=>{this.items=['A','B','C','D'];this.loading=false;},3000);}

Use inside Popover

We recommend using theAngular CDK Overlay. @ngxpert/cdk relies on the Angular CDK, so this will reduce your bundle size a bit due to shared dependencies.

First, configure the trigger component:

<button(click)="isDialogOpen = !isDialogOpen"cdkOverlayOrigin#trigger="cdkOverlayOrigin"[attr.aria-expanded]="isDialogOpen">  Actions<kbd></kbd><kbd>K</kbd></button><ng-templatecdkConnectedOverlay[cdkConnectedOverlayOrigin]="trigger"[cdkConnectedOverlayOpen]="isDialogOpen"><app-sub-command-dialog[value]="value"></app-sub-command-dialog></ng-template>
isDialogOpen=false;listener(e:KeyboardEvent){if(e.key==='k'&&(e.metaKey||e.altKey)){e.preventDefault();if(this.isDialogOpen){this.isDialogOpen=false;}else{this.isDialogOpen=true;}}}ngOnInit(){document.addEventListener('keydown',(ev)=>this.listener(ev));}ngOnDestroy(){document.removeEventListener('keydown',(ev)=>this.listener(ev));}

Then, render thecmdk-command inside CDK Overlay content:

<divclass="cmdk-submenu"><cmdk-command><cmdk-list><cmdk-group[label]="value"><buttoncmdkItem*ngFor="let item of items"[value]="item.label">          {{ item.label }}</button></cmdk-group></cmdk-list><inputcmdkInput#inputplaceholder="Search for actions..."/></cmdk-command></div>
readonlyitems:Array<{label:string}>=[{label:'Open Application',},{label:'Show in Finder',},{label:'Show Info in Finder',},{label:'Add to Favorites',},];ngAfterViewInit(){this.input.nativeElement.focus();}

Drop in stylesheets

You can find global stylesheets to drop in as a starting point for styling. Seesrc/app/themes for examples.

You can include theSCSS stylesheet in your application's style file:

// Global is needed for any theme@use"~@ngxpert/cmdk/styles/scss/globals";// Then add theme@use"~@ngxpert/cmdk/styles/scss/framer";// @use "~@ngxpert/cmdk/styles/scss/vercel";// @use "~@ngxpert/cmdk/styles/scss/linear";// @use "~@ngxpert/cmdk/styles/scss/raycast";

or, use pre-builtCSS file inangular.json

// ..."styles": ["...","node_modules/@ngxpert/cmdk/styles/globals.css""node_modules/@ngxpert/cmdk/styles/framer.css"],// ...

FAQ

Accessible? Yes. Labeling, aria attributes, and DOM ordering tested with Voice Over and Chrome DevTools.

Virtualization? No. Good performance up to 2,000-3,000 items, though. Read below to bring your own.

Filter/sort items manually? Yes. Passfilter={yourFilter} toCommand. Better memory usage and performance. Bring your own virtualization this way.

Unstyled? Yes, use the listed CSS selectors.

Weird/wrong behavior? Make sure your[cdkItem] has a uniquevalue.

Listen for ⌘K automatically? No, do it yourself to have full control over keybind context.

Contributors ✨

Thanks goes to these wonderful people (emoji key):


Dharmen Shah

️️️️♿️💻🖋🎨📖💡🤔🚧📦📆🔬

Netanel Basal

💬💼🔍🤔🚧🧑‍🏫📆🔬👀

Paco

🎨📖🤔🔬

This project follows theall-contributors specification. Contributions of any kind welcome!


[8]ページ先頭

©2009-2025 Movatter.jp