obsidianmd / obsidian-api

Type definitions for the latest Obsidian API.
https://docs.obsidian.md
MIT License
1.65k stars 192 forks source link

Request: built-in React components for modal settings #162

Closed donaldzhu closed 3 months ago

donaldzhu commented 3 months ago

It would be great to have React components for modal settings. At the moment, I can add setting rows to a modal like such:

import { Setting } from 'obsidian'
import { useEffect, useRef } from 'react'

const ModalComponent = () => {
  const settingRef1 = useRef<HTMLDivElement>(null)
  const settingRef2 = useRef<HTMLDivElement>(null)

  useEffect(() => {
    const settingContainer1 = settingRef1.current
    const settingContainer2 = settingRef2.current
    if (
      !settingContainer1 ||
      !settingContainer2
    ) return () => { }

    settingContainer1.empty()
    settingContainer2.empty()

    new Setting(settingContainer1)
      .setName('My Setting')
      .setDesc('My Description.')
      .addText(text => {
        text
          .setValue('My Text')
          .onChange(newText => console.log(newText))
      })

    new Setting(settingContainer2)
      .addButton(button => {
        button
          .setButtonText('My Button')
          .onClick(() => console.log('Button pressed.'))
      })
  }, [])

  return (
    <>
      <div ref={settingRef1} />
      <div ref={settingRef2} />
    </>
  )
}

But it gets a bit messy. It mixes up multiple DOM logics which makes me wonder if it could cause unintended side effects with React. It would be great if there were built-in React components for this purpose, and allow us to write code like this:

const ModalComponent = () => {
  return (
    <>
      <Setting 
        name='My Setting'
        desc='My Description'>
          <Text onChange={newText => console.log(newText)}>My Text</Text>
      </Setting>
      <Setting>
          <Button onClick={() => console.log('Button pressed')}>My Button</Button>
      </Setting>
    </>
  )
}

I attempted to create my own version of built-in React modal settings by copying classNames from the inspector. But it would be harder to replicate all the features and eventListeners, and to have it be future-proof. It would be amazing if there were built-in React components for this purpose!

joethei commented 3 months ago

Obsidian does not use React (or anything like it) internally, so it makes no sense for us to include React components in the API.