Skip to content

Commit

Permalink
Merge pull request #8 from sakihet/command-menu
Browse files Browse the repository at this point in the history
add command menu feature
  • Loading branch information
sakihet authored Mar 17, 2023
2 parents 0153ff1 + 514aeff commit 2de418e
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 2 deletions.
20 changes: 18 additions & 2 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { useRouter } from 'vue-router'
import TheCommandMenu from './components/TheCommandMenu.vue'
import TheFooter from './components/TheFooter.vue'
import TheNavBar from './components/TheNavBar.vue'
import { store } from './store'
import { commandMenuModifiler, store } from './store'
const router = useRouter()
const moveToIndex = () => router.push({ path: '/' })
onMounted(async () => {
Expand All @@ -17,13 +17,29 @@ onMounted(async () => {
store.actions.createOrUpdateNote(store)
moveToIndex()
}
if (e.key === commandMenuModifiler) {
store.pressingCommandMenuModifier = true
}
if (e.key === 'k' && store.pressingCommandMenuModifier) {
if (store.commandMenuOpen) {
store.commandMenuOpen = false
} else {
store.commandMenuOpen = true
}
}
}
}
document.onkeyup = (e: KeyboardEvent) => {
if (e.key === commandMenuModifiler) {
store.pressingCommandMenuModifier = false
}
}
})
</script>

<template>
<TheNavBar />
<TheCommandMenu />
<router-view />
<TheFooter />
</template>
Expand Down
4 changes: 4 additions & 0 deletions src/assets/css/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ p {

body {
--color-background: var(--color-white);
--color-background-command-menu: var(--color-gray-900);
--color-background-secondary: var(--color-gray-100);
--color-background-selected: var(--color-gray-300);
--color-background-selected-text: var(--color-gray-200);
--color-background-icon-selected: var(--color-gray-300);
--color-code-background: var(--color-blue-50);
--color-text-command-menu: var(--color-white);
--color-text-primary: var(--color-gray-900);
--color-text-secondary: var(--color-gray-600);
--color-text-tertiary: var(--color-gray-400);
Expand All @@ -63,11 +65,13 @@ body {
.dark > * {
color-scheme: dark;
--color-background: var(--color-gray-800);
--color-background-command-menu: var(--color-white);
--color-background-secondary: var(--color-gray-900);
--color-background-selected: var(--color-gray-700);
--color-background-selected-text: var(--color-gray-700);
--color-background-icon-selected: var(--color-gray-700);
--color-code-background: var(--color-blue-200);
--color-text-command-menu: var(--color-gray-900);
--color-text-primary: var(--color-white);
--color-text-secondary: var(--color-gray-300);
--color-text-tertiary: var(--color-gray-500);
Expand Down
9 changes: 9 additions & 0 deletions src/assets/css/utility.css
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,9 @@
.w-64 {
width: 16rem;
}
.w-96 {
width: 24rem;
}
.w-128 {
width: 32rem;
}
Expand Down Expand Up @@ -386,6 +389,9 @@
.text-tertiary {
color: var(--color-text-tertiary);
}
.text-command-menu {
color: var(--color-text-command-menu);
}
/* text weight */
.font-medium {
font-weight: 500;
Expand Down Expand Up @@ -500,6 +506,9 @@
border-bottom-width: 0;
}
/* background color */
.bg-command-menu {
background-color: var(--color-background-command-menu);
}
.bg-white {
background-color: var(--color-white);
}
Expand Down
126 changes: 126 additions & 0 deletions src/components/TheCommandMenu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<script setup lang="ts">
import { computed, onUpdated, ref, watch } from 'vue';
import router from '../router';
import { store } from '../store'
const refCommandMenuIndex = ref<number>(0)
const refCommandMenuInput = ref<HTMLElement | null>(null)
const refCommandMenuQuery = ref<string>("")
type Command = {
name: string,
to: {
path: string
}
}
const staticCommands: Command[] = [
{
name: 'Index',
to: { path: '/' }
},
{
name: 'Add',
to: { path: '/new' }
},
{
name: 'About',
to: { path: '/about' }
}
]
const commands = computed(() => {
return [
...staticCommands,
...store.notes.map(note => { return <Command>{ name: note.title, to: { path: `/?noteId=${note.id}` } } })
].filter(c => c.name.includes(refCommandMenuQuery.value))
})
watch (() => store.commandMenuOpen, async (after, before) => {
if (after) {
refCommandMenuQuery.value = ''
}
})
const handleInput = (e: Event) => {
refCommandMenuIndex.value = 0
}
const handleKeydown = (e: KeyboardEvent) => {
}
const handleKeydownEnter = (e: KeyboardEvent) => {
const command: Command = commands.value[refCommandMenuIndex.value]
router.push(command.to.path)
store.commandMenuOpen = false
}
const handleKeydownDown = (e: KeyboardEvent) => {
if (refCommandMenuIndex.value < (commands.value.length - 1)) {
refCommandMenuIndex.value++
} else if (refCommandMenuIndex.value === (commands.value.length - 1)) {
refCommandMenuIndex.value = 0
}
}
const handleKeydownUp = (e: KeyboardEvent) => {
if (0 < refCommandMenuIndex.value) {
refCommandMenuIndex.value--
} else if (0 === refCommandMenuIndex.value) {
refCommandMenuIndex.value = (commands.value.length - 1)
}
}
onUpdated(() => {
if (store.commandMenuOpen) {
refCommandMenuInput.value?.focus()
}
})
</script>

<template>
<div>
<div
class="pattern-mask"
v-if="store.commandMenuOpen"
@click="store.commandMenuOpen = false"
></div>
<dialog
class="rounded border-1 border-solid border-color-default"
:open="store.commandMenuOpen"
>
<div class="w-96 layout-stack-4">
<div>
<input
type="text"
class="h-8 w-full border-none"
ref="refCommandMenuInput"
v-model="refCommandMenuQuery"
@input="handleInput"
@keydown="handleKeydown"
@keydown.enter="handleKeydownEnter"
@keydown.down="handleKeydownDown"
@keydown.up="handleKeydownUp"
/>
</div>
<div class="">
<div
v-for="(command, index) in commands"
class="h-8"
>
<router-link
:to="command.to"
class="text-decoration-none text-secondary"
>
<div
class="h-8 p-2"
:class="{ 'bg-command-menu text-command-menu': index === refCommandMenuIndex}"
>
{{ command.name }}
</div>
</router-link>
</div>
</div>
<div class="text-secondary text-small h-4 text-center">
<pre>enter: select | ↑↓: navigate | ⌘+k: close</pre>
</div>
</div>
</dialog>
</div>
</template>
10 changes: 10 additions & 0 deletions src/components/TheNavBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ const handleChangeLayout = (layout: LayoutType) => {
</div>
</div>
<div class="f-1"></div>
<div class="flex-column mx-3">
<div class="m-auto">
<button
class="h-6 border-solid border-1 border-color-default bg-transparent px-2 py-1 rounded text-secondary font-mono cursor-pointer"
@click="store.commandMenuOpen = !store.commandMenuOpen"
>
⌘K
</button>
</div>
</div>
<div class="flex-column h-12 mx-3">
<div class="m-auto">
<div class="">
Expand Down
5 changes: 5 additions & 0 deletions src/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { LayoutType } from '../types/layoutType'
import { SortKey } from '../types/sortKey'

type Settings = { sidebarWidth: number }
export const commandMenuModifiler = 'Meta'
export const sidebarWidthDefault = 240
const settingsDefault: Settings = {
sidebarWidth: sidebarWidthDefault
Expand Down Expand Up @@ -45,6 +46,7 @@ const getTheme = () => {
}

interface Store {
commandMenuOpen: boolean,
composing: boolean,
editor: {
noteContent: string
Expand All @@ -58,6 +60,7 @@ interface Store {
isLoaded: boolean,
notes: Array<Note>,
notesLayout: LayoutType,
pressingCommandMenuModifier: boolean,
searchQuery: string,
settings: Settings,
sortKey: SortKey,
Expand All @@ -84,6 +87,7 @@ interface Store {
}

export const store: Store = reactive<Store>({
commandMenuOpen: false,
composing: false,
editor: {
noteContent: '',
Expand All @@ -97,6 +101,7 @@ export const store: Store = reactive<Store>({
isLoaded: false,
notes: [],
notesLayout: 'list',
pressingCommandMenuModifier: false,
searchQuery: '',
settings: settingsDefault,
sortKey : 'updated',
Expand Down

1 comment on commit 2de418e

@vercel
Copy link

@vercel vercel bot commented on 2de418e Mar 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

paperie – ./

paperie-git-main-sakihet.vercel.app
paperie.app
paperie-sakihet.vercel.app
paperie.vercel.app

Please sign in to comment.