feat: implement create new type feature
Core implementation: - CreateTypeDialog: simple dialog with name field for creating new types - handleCreateType in useNoteActions: creates Type documents in type/ folder - Dynamic sidebar sections: custom types (Recipe, Book, etc.) appear as new sidebar sections after built-in ones, each with a + button for instances - Updated CreateNoteDialog: accepts custom types, shows them with blue accent - handleCreateNote now supports custom types (folder = lowercased type name) Product decisions: - The + on Types section opens CreateTypeDialog (not CreateNoteDialog) - Custom type sections use FileText icon and blue accent color by default - Section labels are pluralized (e.g., "Recipes", "Books") Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@ import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const NOTE_TYPES = [
|
||||
const BUILT_IN_TYPES = [
|
||||
'Note',
|
||||
'Project',
|
||||
'Experiment',
|
||||
@@ -15,18 +15,20 @@ const NOTE_TYPES = [
|
||||
'Topic',
|
||||
] as const
|
||||
|
||||
export type NoteType = (typeof NOTE_TYPES)[number]
|
||||
export type NoteType = (typeof BUILT_IN_TYPES)[number]
|
||||
|
||||
interface CreateNoteDialogProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
onCreate: (title: string, type: NoteType) => void
|
||||
defaultType?: NoteType
|
||||
onCreate: (title: string, type: string) => void
|
||||
defaultType?: string
|
||||
/** Custom types from the vault (Type documents not in built-in list) */
|
||||
customTypes?: string[]
|
||||
}
|
||||
|
||||
export function CreateNoteDialog({ open, onClose, onCreate, defaultType }: CreateNoteDialogProps) {
|
||||
export function CreateNoteDialog({ open, onClose, onCreate, defaultType, customTypes = [] }: CreateNoteDialogProps) {
|
||||
const [title, setTitle] = useState('')
|
||||
const [type, setType] = useState<NoteType>('Note')
|
||||
const [type, setType] = useState<string>('Note')
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
@@ -68,7 +70,7 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType }: Creat
|
||||
Type
|
||||
</label>
|
||||
<div className="flex flex-wrap gap-1.5">
|
||||
{NOTE_TYPES.map((t) => (
|
||||
{BUILT_IN_TYPES.map((t) => (
|
||||
<Button
|
||||
key={t}
|
||||
type="button"
|
||||
@@ -83,6 +85,23 @@ export function CreateNoteDialog({ open, onClose, onCreate, defaultType }: Creat
|
||||
{t}
|
||||
</Button>
|
||||
))}
|
||||
{customTypes.map((t) => (
|
||||
<Button
|
||||
key={t}
|
||||
type="button"
|
||||
variant={type === t ? 'default' : 'outline'}
|
||||
size="sm"
|
||||
className={cn(
|
||||
"rounded-full text-xs",
|
||||
type === t
|
||||
? "bg-[var(--accent-blue)] text-white"
|
||||
: "border-[var(--accent-blue)] text-[var(--accent-blue)]"
|
||||
)}
|
||||
onClick={() => setType(t)}
|
||||
>
|
||||
{t}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<DialogFooter>
|
||||
|
||||
Reference in New Issue
Block a user