Skip to content

Commit b88f13a

Browse files
committed
feat(tools): added token generator
- Added Slider component to the UI library - Added Checkbox component to the UI library - Added Textarea component to the UI library
1 parent b221736 commit b88f13a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1665
-22
lines changed

packages/app/app.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1+
<script setup lang="ts">
2+
import CommandPalette from './src/modules/command-palette/components/command-palette.vue';
3+
</script>
4+
15
<template>
26
<NuxtLayout>
7+
<CommandPalette />
38
<NuxtPage />
49
</NuxtLayout>
510
</template>

packages/app/assets/css/tailwind.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
--popover: 0 0% 100%;
1515
--popover-foreground: 240 10% 3.9%;
1616

17-
--primary: 150 76% 38%;
17+
--primary: 149 79% 35%;
1818
--primary-foreground: 0 0% 98%;
1919

2020
--secondary: 240 4.8% 95.9%;
@@ -36,7 +36,7 @@
3636
}
3737

3838
.dark {
39-
--background:240 5% 6%;
39+
--background:240 4% 10%;
4040
--foreground:0 0% 98%;
4141

4242
--card: 240 5% 8%;

packages/app/nuxt.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,4 +53,8 @@ export default defineNuxtConfig({
5353
{ code: 'fr', file: 'fr.yaml', name: 'Français' },
5454
],
5555
},
56+
57+
experimental: {
58+
scanPageMeta: false, // Causes some issues with layouts and hook-registered pages
59+
},
5660
});

packages/app/src/locales/en.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,13 @@ tools:
2929
description: >-
3030
Generate random string with the characters you want, uppercase, lowercase
3131
letters, numbers and/or symbols.
32+
placeholder: Generated token will appear here, please select at least one option.
33+
use-uppercase: Include uppercase letters
34+
use-lowercase: Include lowercase letters
35+
use-numbers: Include numbers
36+
use-symbols: Include symbols
37+
length: Length
38+
refresh: Refresh
39+
quantity: Quantity
40+
format: Format
41+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<script setup>
2+
import { Button } from '@/src/modules/ui/components/button';
3+
import { useToolsStore } from '../../tools/tools.store';
4+
5+
const { tools } = useToolsStore();
6+
const localePath = useLocalePath();
7+
</script>
8+
9+
<template>
10+
<div class="border-b h-[60px] flex items-center justify-between px-6">
11+
<NuxtLink variant="link" class="text-xl font-semibold border-b border-transparent hover:no-underline h-auto px-1 rounded-none !transition-border-color-250" :as="Button" :to="localePath('/')" aria-label="Home">
12+
<span class="font-bold text-foreground">IT</span>
13+
<span class="text-[80%] font-extrabold border-[2px] leading-none border-current rounded-md px-1 py-0.5 ml-1.5 text-primary">TOOLS</span>
14+
</NuxtLink>
15+
</div>
16+
17+
<div class="pt-4 px-3 flex flex-col gap-0.5">
18+
<NuxtLink to="/" class="py-1.5 px-3 flex items-center text-muted-foreground hover:text-foreground transition hover:bg-muted rounded-lg">
19+
<Icon name="i-tabler-home" class="mr-2 size-4" />
20+
Home
21+
</NuxtLink>
22+
23+
<NuxtLink v-for="tool in tools" :key="tool.key" class="py-1.5 px-3 flex items-center text-muted-foreground hover:text-foreground transition hover:bg-muted rounded-lg" :to="tool.path" exact-active-class="bg-secondary !text-foreground">
24+
<Icon :name="tool.icon" class="mr-2 size-4" />
25+
{{ tool.title }}
26+
</NuxtLink>
27+
</div>
28+
</template>
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<script setup>
2+
import { Button } from '@/src/modules/ui/components/button';
3+
import { useCommandPaletteStore } from '../../command-palette/command-palette.store';
4+
import { DropdownMenu } from '../../ui/components/dropdown-menu';
5+
import DropdownMenuContent from '../../ui/components/dropdown-menu/DropdownMenuContent.vue';
6+
import DropdownMenuItem from '../../ui/components/dropdown-menu/DropdownMenuItem.vue';
7+
import DropdownMenuTrigger from '../../ui/components/dropdown-menu/DropdownMenuTrigger.vue';
8+
import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger } from '../../ui/components/sheet';
9+
10+
const { openCommandPalette } = useCommandPaletteStore();
11+
const colorMode = useColorMode();
12+
</script>
13+
14+
<template>
15+
<div class="w-full min-h-screen text-sm relative font-sans flex flex-row">
16+
<div class="w-64 border-r bg-white dark:bg-background shrink-0 hidden sm:block">
17+
<sidenav-menu />
18+
</div>
19+
<div class="flex-1 flex flex-col">
20+
<div class="border-b h-[60px] flex items-center justify-between px-6 bg-white dark:bg-background">
21+
<div class="flex items-center gap-4">
22+
<div class="sm:hidden">
23+
<Sheet>
24+
<SheetTrigger>
25+
<Button variant="ghost" size="icon">
26+
<Icon name="i-tabler-menu-2" class="size-5" />
27+
</Button>
28+
</SheetTrigger>
29+
<SheetContent side="left" class="p-0 text-sm">
30+
<sidenav-menu />
31+
</SheetContent>
32+
</Sheet>
33+
</div>
34+
35+
<Button variant="outline" class="sm:pr-12 md:pr-24 text-muted-foreground" @click="openCommandPalette">
36+
<Icon name="i-tabler-search" class="mr-2 size-4" />
37+
{{ $t('home.search-tools') }}
38+
</Button>
39+
</div>
40+
41+
<div>
42+
<DropdownMenu>
43+
<DropdownMenuTrigger as-child>
44+
<Button variant="ghost" size="icon">
45+
<Icon name="i-tabler-moon" class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
46+
<Icon name="i-tabler-sun" class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
47+
<span class="sr-only">Toggle theme</span>
48+
</Button>
49+
</DropdownMenuTrigger>
50+
<DropdownMenuContent align="end">
51+
<DropdownMenuItem class="cursor-pointer" :class="{ 'font-bold': colorMode.preference === 'light' }" @click="colorMode.preference = 'light'">
52+
<Icon name="i-tabler-sun" class="mr-2 size-4" />
53+
Light
54+
</DropdownMenuItem>
55+
<DropdownMenuItem class="cursor-pointer" :class="{ 'font-bold': colorMode.preference === 'dark' }" @click="colorMode.preference = 'dark'">
56+
<Icon name="i-tabler-moon" class="mr-2 size-4" />
57+
Dark
58+
</DropdownMenuItem>
59+
<DropdownMenuItem class="cursor-pointer" :class="{ 'font-bold': colorMode.preference === 'system' }" @click="colorMode.preference = 'system'">
60+
<Icon name="i-tabler-device-laptop" class="mr-2 size-4" />
61+
System
62+
</DropdownMenuItem>
63+
</DropdownMenuContent>
64+
</DropdownMenu>
65+
</div>
66+
</div>
67+
68+
<div class="flex-1">
69+
<slot />
70+
</div>
71+
</div>
72+
</div>
73+
</template>

packages/app/src/modules/app/pages/index.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
<script setup>
22
import { Badge } from '@/src/modules/ui/components/badge';
33
import { Button, buttonVariants } from '@/src/modules/ui/components/button';
4+
import { useCommandPaletteStore } from '../../command-palette/command-palette.store';
45
import { cn } from '../../shared/style/cn';
56
import { useToolsStore } from '../../tools/tools.store';
67
import { CardContent } from '../../ui/components/card';
78
import Card from '../../ui/components/card/Card.vue';
89
910
const { tools } = useToolsStore();
11+
const { openCommandPalette } = useCommandPaletteStore();
1012
</script>
1113

1214
<template>
1315
<grid-background>
1416
<div class="flex gap-24 mx-auto justify-center pb-8 mt-8 items-center px-6">
1517
<div class="max-w-xl">
1618
<div class="flex gap-2">
17-
<Badge class="text-primary bg-primary/10 hover:bg-primary/10">
19+
<Badge class="text-primary bg-primary/10 hover:bg-primary/10 shadow-none">
1820
{{ $t('home.open-source') }}
1921
</Badge>
20-
<Badge class="text-primary bg-primary/10 hover:bg-primary/10">
22+
<Badge class="text-primary bg-primary/10 hover:bg-primary/10 shadow-none">
2123
{{ $t('home.free') }}
2224
</Badge>
23-
<Badge class="text-primary bg-primary/10 hover:bg-primary/10">
25+
<Badge class="text-primary bg-primary/10 hover:bg-primary/10 shadow-none">
2426
{{ $t('home.self-hostable') }}
2527
</Badge>
2628
</div>
@@ -40,7 +42,7 @@ const { tools } = useToolsStore();
4042
<Icon name="i-tabler-arrow-right" class="ml-2 size-4" />
4143
</Button>
4244

43-
<Button variant="outline">
45+
<Button variant="outline" @click="openCommandPalette">
4446
<Icon name="i-tabler-search" class="mr-2 size-4" />
4547
{{ $t('home.search-tools') }}
4648
</Button>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export const useCommandPaletteStore = defineStore('command-palette', () => {
2+
const isCommandPaletteOpen = ref(false);
3+
4+
return {
5+
isCommandPaletteOpen,
6+
toggleCommandPalette() {
7+
isCommandPaletteOpen.value = !isCommandPaletteOpen.value;
8+
},
9+
closeCommandPalette() {
10+
isCommandPaletteOpen.value = false;
11+
},
12+
openCommandPalette() {
13+
isCommandPaletteOpen.value = true;
14+
},
15+
};
16+
});
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<script setup lang="ts">
2+
import { useMagicKeys } from '@vueuse/core';
3+
import { useToolsStore } from '../../tools/tools.store';
4+
import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator } from '../../ui/components/command';
5+
import { useCommandPaletteStore } from '../command-palette.store';
6+
7+
const commandPaletteStore = useCommandPaletteStore();
8+
const { tools } = useToolsStore();
9+
10+
onKeyStroke('k', (e) => {
11+
e.preventDefault();
12+
13+
if (!e.ctrlKey && !e.metaKey) {
14+
return;
15+
}
16+
17+
commandPaletteStore.toggleCommandPalette();
18+
});
19+
20+
const commandSections = computed(() => [
21+
{
22+
title: 'Tools',
23+
items: [
24+
...tools.map(tool => ({
25+
label: tool.title,
26+
icon: tool.icon,
27+
action: () => navigateTo(tool.path),
28+
})),
29+
],
30+
},
31+
]);
32+
33+
function handleSelectCommand({ item }: { item: { label: string; action: () => void; keepOpen?: boolean } }) {
34+
item.action();
35+
36+
if (!item.keepOpen) {
37+
commandPaletteStore.closeCommandPalette();
38+
}
39+
}
40+
</script>
41+
42+
<template>
43+
<CommandDialog v-model:open="commandPaletteStore.isCommandPaletteOpen">
44+
<CommandInput placeholder="Type a command or search..." />
45+
<CommandList>
46+
<CommandEmpty>{{ $t('command-palette.no-result') }}</CommandEmpty>
47+
<!-- <CommandGroup heading="Suggestions">
48+
<CommandItem value="calendar">
49+
Calendar
50+
</CommandItem>
51+
<CommandItem value="search-emoji">
52+
Search Emoji
53+
</CommandItem>
54+
<CommandItem value="calculator">
55+
Calculator
56+
</CommandItem>
57+
</CommandGroup>
58+
<CommandSeparator />
59+
<CommandGroup heading="Settings">
60+
<CommandItem value="profile">
61+
Profile
62+
</CommandItem>
63+
<CommandItem value="billing">
64+
Billing
65+
</CommandItem>
66+
<CommandItem value="settings">
67+
Settings
68+
</CommandItem>
69+
</CommandGroup> -->
70+
<CommandGroup v-for="section in commandSections" :key="section.title" :heading="section.title">
71+
<CommandItem v-for="item in section.items" :key="item.label" :value="item.label" @select="handleSelectCommand({ item })">
72+
<Icon :name="item.icon" class="mr-2 size-4" />
73+
{{ item.label }}
74+
</CommandItem>
75+
</CommandGroup>
76+
</CommandList>
77+
</CommandDialog>
78+
</template>

0 commit comments

Comments
 (0)