Git Product home page Git Product logo

kbar's Introduction

kbar's People

Contributors

anishde12020 avatar arisacoba avatar bigosvaap avatar bragur avatar brydar avatar caiotracera avatar dominicwhyte avatar drenther avatar driaug avatar dubzzz avatar eric-hc avatar fregante avatar imteekay avatar jacksonh avatar jpdenford avatar kevinhu avatar merlin04 avatar piofinn avatar rakakroma avatar relferreira avatar rihardsgravis avatar schickling avatar smhutch avatar steveoni avatar terabyte128 avatar tiagohermano avatar timc1 avatar tommoor avatar vinniciusgomes avatar yogen9 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kbar's Issues

Add automatic "Recent" tracking

It would be really nice for kbar to track which actions have been used recently and automatically group them at the top when the query is empty, thoughts?

image

Improving extensibility

KBar currently takes a static data structure and handles all of the parsing internally. The current component structure is as follows:

KBar
  KeyboardShortcuts
  KBarAnimator
    KBarSearch
  • KBar handles the primary cmd+k/esc listeners, and coordinates when to show, animate, and hide the content
  • KeyboardShortcuts attaches keydown listeners and matches the keystroke patterns with our actions object
  • KBarAnimator leverages ResizeObserver and the Web Animations API to coordinate the smooth transitions when the content updates
  • KBarSearch handles the search and rendering of results

Problem

Since all state management and rendering logic is within KBar itself, it is currently impossible for users to customize their command menu to fit their brand.

Although we can theoretically expose props which enable users to pass certain configurations, this would lead us to quite a restrictive API.

Let's take a look at an approach:

Solution

Provide a way to hook into the internal state; e.g. visualState, currentActionId, actions, and
a method to trigger internal state updates.

The component heirarchy would look something like this:

// app.tsx
<KBarProvider actions={actions}>
  <Breadcrumbs /> // custom user component
  <KBarAnimator>
    <KBarSearch />
    <KBarResults 
      // 
      onRender={(result) => (
        <div>
          // ...
        </div>
      )}
    />
  </KBarAnimator>
</KBarProvider>
// <MyApp />

User defined components within the KBarProvider can hook into the internal state through a useKBar hook.

// breadcrumbs.tsx
function Breadcrumbs() {
  const { actions, breadcrumbs } = useKBar((state) => ({
    breadcrumbs: getBreadcrumbs(state)
  }));

  return (
    <ul>
      {breadcrumbs.map(breadcrumb => (
        <li key={breadcrumb.id}>
          <Button onClick={() => actions.setCurrentRootActionId(breadcrumb.id)}>{breadcrumb.name}</Button>
        </li>
      ))}
    </ul>
  )
}

Can't run a local dev build

Getting multiple can't resolves like this

ERROR in ./example/src/index.tsx 2:0-35 Module not found: Error: Can't resolve 'react-dom' in '/.../kbar-main/example/src'

ERROR in ./example/src/index.tsx 4:0-59 Module not found: Error: Can't resolve 'react-router-dom' in '/.../kbar- main/example/src'

ERROR in ./src/InternalKeyboardEvents.tsx 1:0-31 Module not found: Error: Can't resolve 'react' in '/.../kbar-main/src' 
@ ./src/KBarContextProvider.tsx 3:0-62 9:41-63 
@ ./example/src/App.tsx 23:0-61 42:45-57 
@ ./example/src/index.tsx 3:0-24 5:153-156

Do you know what might be happening?

KBar doesn't work in final build

hey tim! Awsome work with the Kbar, i've been using it in my preact app - in dev mode it works fine but after production build it doesn't work. consider me a noob trying to solve things.

it shows something like this in console

vendor.822cbe4a.js:29 Uncaught TypeError: (0 , Zt.default) is not a function
    at Gf (vendor.822cbe4a.js:29)
    at Y.qf [as constructor] (vendor.822cbe4a.js:29)
    at Y.Ho [as render] (vendor.822cbe4a.js:1)
    at dr (vendor.822cbe4a.js:1)
    at ti (vendor.822cbe4a.js:1)
    at dr (vendor.822cbe4a.js:1)
    at ti (vendor.822cbe4a.js:1)
    at dr (vendor.822cbe4a.js:1)
    at ti (vendor.822cbe4a.js:1)
    at dr (vendor.822cbe4a.js:1)
Gf @ vendor.822cbe4a.js:29
qf @ vendor.822cbe4a.js:29
Ho @ vendor.822cbe4a.js:1
dr @ vendor.822cbe4a.js:1
ti @ vendor.822cbe4a.js:1
dr @ vendor.822cbe4a.js:1
ti @ vendor.822cbe4a.js:1
dr @ vendor.822cbe4a.js:1
ti @ vendor.822cbe4a.js:1
dr @ vendor.822cbe4a.js:1
Ie @ vendor.822cbe4a.js:1
(anonymous) @ index.dc5496f6.js:formatted:113

in index.js (pretty-printed) it highlights this portion

y(i(r.KBarProvider, {
    actions: S,
    children: [o(r.KBarPortal, {
        children: o(r.KBarPositioner, {
            children: i(r.KBarAnimator, {
                style: B,
                children: [o(r.KBarSearch, {
                    style: k,
                    placeholder: "Type a command or search\u2026"
                }), o(r.KBarResults, {})]
            })
        })
    }), o(g, {
        children: o(v, {})
    })]
}), document.getElementById("app"));

it'd be really great if you can help me with this. thanks in advance

Add ability to register actions dynamically

Currently actions must be registered up front – though this works well for static actions; e.g. navigating pages, triggering DOM events, it falls short of easily enabling users to generate actions on the fly.

Perhaps an API like so:

const { registerActions } = useKBar(() => {...});

React.useEffect(() => {
  registerActions([
    // ...
  ])
}, [])

Improve styling

Currently, styles can be applied via props; e.g. contentStyle, backgroundStyle for KBarContent, and directly as style for KBarSearch. There should be a simpler way to customize styles which enable full flexibility for:

  • Customizing Web Animations (Maybe not necessary? Kinda nice to have built in support for basic show/hide and height animations)
  • Dialog background transitions
  • Content transitions
  • Search input
  • Results
  • *Support for styled components
  • *Support for classNames

Add action priority / ordering

When using useRegisterActions to dynamically add actions while components are mounted it's difficult to predict which order items will appear in, adding an optional priority attribute to actions would put control of this in the developers hands while handling the boilerplate of sorting internally.

Usage with storybook

Hi @timc1 !

Really love this project, it's great.

I have been checking out the component in a pretty barebones project and noticed that storybook stops working with a pretty plain build config when I added this package.

Specifically I'm getting a bunch of loader issues like:

ERROR in ./node_modules/kbar/lib/useStore.js 104:12
Module parse failed: Unexpected token (104:12)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| exports.default = useStore;
| class Publisher {
>     getState;
|     subscribers = [];
|     constructor(getState) {
@ ./node_modules/kbar/lib/KBarContextProvider.js 26:35-56
 @ ./node_modules/kbar/lib/index.js
 @ ./packages/common/src/ui/layout/tables/columns/CheckboxSelectionColumn.tsx
 @ ./packages/common/src/ui/layout/tables/columns/index.ts
 @ ./packages/common/src/ui/layout/tables/index.ts
 @ ./packages/common/src/utils/testing.tsx
 @ ./.storybook/preview.js
 @ ./.storybook/preview.js-generated-config-entry.js
 @ multi ./node_modules/@storybook/react/node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ReactRefreshEntry.js ./node_modules/@storybook/core-client/dist/esm/globals/polyfills.js ./node_modules/@storybook/core-client/dist/esm/globals/globals.js ./.storybook/storybook-init-framework-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/common/config.js-generated-other-entry.js ./node_modules/@storybook/addon-docs/dist/esm/frameworks/react/config.js-generated-other-entry.js ./node_modules/@storybook/addon-links/dist/esm/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-actions/dist/esm/preset/addArgs.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addDecorator.js-generated-other-entry.js ./node_modules/@storybook/addon-backgrounds/dist/esm/preset/addParameter.js-generated-other-entry.js ./node_modules/@storybook/addon-measure/dist/esm/preset/preview.js-generated-other-entry.js ./node_modules/storybook-addon-outline/dist/esm/preset/addDecorator.js-generated-other-entry.js ./.storybook/preview.js-generated-config-entry.js ./.storybook/generated-stories-entry.js (webpack)-hot-middleware/client.js?reload=true&quiet=false&noInfo=undefined ./node_modules/@storybook/react/node_modules/@pmmmwh/react-refresh-webpack-plugin/client/ErrorOverlayEntry.js

Everything works fine if I alter the tsconfig.json in this project to be es5 rather than ESNext and rebuild - was curious if making this change would be something you'd think about doing (Or, if you can recommend a different change I can make that is easier?)

Selecting a field value from the browser suggestion gives error

I have a field on a form ( @mui Input, not that it matters, I think ) and when click on the empty field, Chrome helpfully gives me a list of values which have been entered previously. Clicking on one of them populates the field and raises an error with kbar:

TypeError
Cannot read properties of undefined (reading 'toLowerCase')
Call Stack
 handleKeyDown
  @openmsupply-client/host/../../node_modules/kbar/lib/InternalEvents.js:132:33

checking for null on the event.key property works around it for me:
internalEvents.tsx:124

const key = event.key?.toLowerCase();

Shouldn't cause any issues setting key to null like this afaik - it just helps the early return a few lines later 🤷‍♂️

Error when searched action does not exists

Hi,

First, thank you for this awesome component.

When I search for an invalid action and press enter, the component KBarresults returns the following error

image

A simple check on the matches should resolve this issue.

Why wrap our entire app with KBarProvider?

Hi there! First of all, thanks for this :)

I it really necessary to wrap our app with your context provider?
From what I can tell, only KBar components actually need to access that context. There are no other exports (like custom hooks) that we can use anywhere else in our app (that would require the provider) – and, honestly, I don't see a use-case where that would be necessary.

If I'm not completely mistaken, this would just require an update to the docs.

Typing character within animation time gets cleared from input

Probably easiest to reproduce by temporarily increasing the enter animation, but I have repeatedly done it on my installation.

  • Type cmd+k
  • Type first character of search within animation time (200ms)
  • Character appears in input but it subsequently cleared

Custom Icons for Actions

224571E0-4466-4C7D-B34E-91812487AB96

It would be great if I could select an icons that would display to the right of the action option like the picture above.

A simple solution would be to allow for an icon key in the actions array that will take an icon component

comet BlogIcon = () => <AiNewspaperOutline />;

const actions = [
  {
    id: "blog",
    name: "Blog",
    shortcut: ["b"],
    keywords: "writing words",
    perform: () => (window.location.pathname = "blog"),
    icon: BlogIcon
  }
];

[suggestion] - Split code to make a monorepo project

Hi 👋🏻
I discovered the project today and I am a big fan! The problem is that it uses React, and it's not a framework I use :/

So I was wondering if it would be better to make the project monorepo in order to add a lot of integrations, like @kbar/react, @kbar/vue.... and @kbar/core which contains the vanilla part.

What do you think about it?

Babel wants an additional loader (React 18)

Hi, I'm trying kbar in my app (created with create-react-app where I use React 18 (18.0.0-alpha-cb8a50619-20210909) and I get this error when starting the app:

Failed to compile.

./node_modules/kbar/lib/useStore.js 120:10
Module parse failed: Unexpected token (120:10)
File was processed with these loaders:
 * ./node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|
| class Publisher {
>   getState;
|   subscribers = [];
|

In my App.js I have:

const actions = [
  {
    id: "blog",
    name: "Blog",
    shortcut: ["b"],
    keywords: "writing words",
    perform: () => (window.location.pathname = "blog"),
  },
  {
    id: "contact",
    name: "Contact",
    shortcut: ["c"],
    keywords: "email",
    perform: () => (window.location.pathname = "contact"),
  },
];

export default function App() {
  return (
    <KBarProvider actions={actions}>
        <App />
    </KBarProvider>
  );
}

EDIT: Seem like the importing of anything from import { ... } from "kbar"; is crashing the app.

Great Work! But some interesting improvements

Hi Tim! Nice to contribute with you again.

I've been exploring your solution with a Next.js with Tailwind + TypeScript and I see some improvements.

  • <KBarContent accepts contentStyle, but not contentClassname, using Tailwind classes with style is not possible (at least as far as I know)
  • KBarResults component onRender function uses three types action, handlers, state, could you export them for creating custom components with this fully typed?
  • KBarProvider context provider .. options prop is required, why not auto-configure some default animations? Also actions prop is required, when they could be loaded dynamically.

Tell me what do you think :)

Shortcut added to action without `perform` does nothing

Ideally if you have a shortcut on an action with no perform attribute, but a children attribute it should open the kbar with the correct active root action. eg,

  • you have a "Theme" action with the shortcut "t"
  • Hitting "t" should open kbar with the dark/light/system options visible
  • Today, nothing happens

Add ability to search for nested content

Currently, searching "dark" will only display the "Theme…" action. Clicking the "Theme…" action will then expose the "Light" and "Dark" actions.

It would be neat to displaying search results for nested actions by displaying a breadcrumb-like UI. Searching "dark" would then display a result like:

Theme… > Dark

Windows support

Hey,
I really like this component, but macOS have less than 10% of market share.
It would be nice to add alternative shortcuts for Windows (and probably Linux).

CTRL + K works well, menu could be opened and closed, but the shortcuts like "h for home" are not working, just nothing happens.

Load Asynchronous Actions

We could have some actions immediately available and additional actions would be appended after a promise is resolved (or several promises for that matter). A dev defined loading indicator could optionally be displayed in the interim.

Move state out of context provider

Currently state is managed directly in KBarContextProvider. This breaks our usage of the publisher/subscriber as changes directly within the provider re render children.

Instead, we can move the state management to a separate hook, e.g. useStore, which would return the memoized state.

Any plans to offer a framework-agnostic version?

I love this concept, and I actually use a custom cmd+k implementation for a project of mine. I'd love to swap that out with kbar, but my app does not use React. Do you have any plans to make a framework-agnostic (only typescript) version of kbar?

Mouse hover overrides keyboard navigation

When the cursor stays hovered on top of, say the third result, keyboard navigating will jump between the first result and the third.

In the video below, we expect that each time the search query changes, the active result should be the first:

Kapture.2021-10-17.at.22.27.13.mp4

Sectioned actions

Similar to spotlight, it may be nice to be able to place our actions in different sections for more complex applications. For example lets say I wanted a "Navigation" section for all of my navigation items, then a "Contacts" section to search contacts, a "Posts" section to search posts, etc.

spotlight secondary text

I am building an application that I'd like the user to be able to search the navigation, various commands, along with about 4 or 5 different entities at the same time in this universal search.

Missing Modules & TS Issues

Cool idea, but the implementation seems pretty lacking at the moment. I installed it, added it to my app, and received these errors:

honeybadger.js?e9d7:1057 ./node_modules/kbar/lib/KBarContent.js:26:0
Module not found: Can't resolve '@reach/portal'

Import trace for requested module:
./node_modules/kbar/lib/index.js
./components/GlobalProviders/index.tsx
./pages/_app.tsx

https://nextjs.org/docs/messages/module-not-found
eval @ honeybadger.js?e9d7:1057
r @ fs.js:3
handleErrors @ hot-dev-client.js?5345:120
processMessage @ hot-dev-client.js?5345:170
eval @ hot-dev-client.js?5345:32
eval @ eventsource.js?a343:38
handleMessage @ eventsource.js?a343:36
honeybadger.js?e9d7:1057 ./node_modules/kbar/lib/KBarResults.js:25:0
Module not found: Can't resolve 'match-sorter'

Import trace for requested module:
./node_modules/kbar/lib/index.js
./components/GlobalProviders/index.tsx
./pages/_app.tsx

https://nextjs.org/docs/messages/module-not-found
eval @ honeybadger.js?e9d7:1057
r @ fs.js:3
handleErrors @ hot-dev-client.js?5345:120
processMessage @ hot-dev-client.js?5345:170
eval @ hot-dev-client.js?5345:32
eval @ eventsource.js?a343:38
handleMessage @ eventsource.js?a343:36
honeybadger.js?e9d7:1057 ./node_modules/kbar/lib/useStore.js:22:0
Module not found: Can't resolve 'fast-equals'

Import trace for requested module:
./node_modules/kbar/lib/KBarContextProvider.js
./node_modules/kbar/lib/index.js
./components/GlobalProviders/index.tsx
./pages/_app.tsx

https://nextjs.org/docs/messages/module-not-found

We already have a portal, so I'm not keen to install reach portal, or any of the other reach components. But also, shouldn't this thing just handle its own dependencies?

Also, seems not to be TypeScript ready. I get this error from TS:

Property 'options' is missing in type '{ children: ReactNode; actions: { id: string; name: string; shortcut: string[]; keywords: string; perform: () => Promise<boolean>; }[]; }' but required in type 'KBarProviderProps'.ts(2741)

... though I've seen no indication that "options" should be a required property.

I hope this might be worth a second look later on, when it's more fully baked.

Add result windowing / virtualization

It's possible (in the case of search for example) to have hundreds of results, currently all matching results are displayed even those outside of the scrollable area which slows down on large result sets.

Display subtitle along with name for actions

Kbar should allow developers the option to provide more context to users by displaying a subtitle along with the name. In my specific use-case I'd like to expose my complex navigation to kbar. Because things are nested, it may be helpful to users to see a navigation path under the name.

This would look something like this.

Gizmo
Products Electronics

To display the subtitle as shown above, we may do something like this in our actions array.

const actions = [
  ...
  {
    name: "Gizmo", 
    subtitle: "Products ▶ Electronics", 
    perform: () => window.location.pathname = "/products/electronics/gizmo" 
  },
  ...
];

If the search string contained words in subtitle, kbar would return that given item.

Pre launch checklist

  • Register actions dynamically #7
  • Single page docs/landing page
  • Update demo actions to actually work :-)
  • Release package

Remove `KBarResults`

Now that we have the new Results API, it's probably good to get rid of the deprecated KBarResults component completely.

Command palette

Nice project! I recommend adding the keywords "command palette" in package.json, README.md and so on, because that's how most people refer to this kind of functionality.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.