feat(shared-ui): add QuickInputBar and PillToolbar components

- Add QuickInputBar component with natural language parsing, syntax
  highlighting, search, and quick-create functionality
- Add PillToolbar, PillToolbarButton, PillToolbarDivider components
  for app-specific toolbar controls
- Add PillTimeRangeSelector for hour range selection
- Add PillViewSwitcher for view mode switching with sliding indicator
- Integrate QuickInputBar into Calendar, Contacts, and Todo apps
- Add app-specific toolbars: CalendarToolbar, ContactsToolbar, TodoToolbar
- Add DateStrip component for Calendar date navigation
- Fix type exports: export QuickAction and CreatePreview from quick-input
  module, remove duplicate exports from deprecated command-bar

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-12 02:17:17 +01:00
parent c6f8b9f87c
commit 0f10a38cc0
17 changed files with 3697 additions and 121 deletions

View file

@ -0,0 +1,91 @@
<script lang="ts">
import type { Snippet } from 'svelte';
interface Props {
/** Click handler */
onclick: () => void;
/** Whether the button is in active state */
active?: boolean;
/** Tooltip title */
title?: string;
/** Whether to render as icon-only (smaller padding) */
iconOnly?: boolean;
/** Disabled state */
disabled?: boolean;
/** Button content (icon and/or text) */
children: Snippet;
}
let {
onclick,
active = false,
title,
iconOnly = false,
disabled = false,
children,
}: Props = $props();
</script>
<button
type="button"
class="toolbar-btn"
class:active
class:icon-only={iconOnly}
{title}
{disabled}
{onclick}
>
{@render children()}
</button>
<style>
.toolbar-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.375rem;
padding: 0.5rem 0.75rem;
background: transparent;
border: none;
border-radius: 9999px;
cursor: pointer;
color: #374151;
font-size: 0.875rem;
font-weight: 500;
white-space: nowrap;
transition: all 0.15s ease;
}
:global(.dark) .toolbar-btn {
color: #f3f4f6;
}
.toolbar-btn:hover:not(:disabled) {
background: rgba(0, 0, 0, 0.05);
}
:global(.dark) .toolbar-btn:hover:not(:disabled) {
background: rgba(255, 255, 255, 0.1);
}
.toolbar-btn.active {
background: color-mix(in srgb, #3b82f6 15%, transparent 85%);
color: #3b82f6;
}
.toolbar-btn.icon-only {
padding: 0.5rem;
}
.toolbar-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
/* Icon styling */
.toolbar-btn :global(svg) {
width: 1rem;
height: 1rem;
flex-shrink: 0;
}
</style>