svecosystem / formsnap

Functional, accessible, and powerful form components for Svelte. 🫰
https://formsnap.dev
MIT License
539 stars 28 forks source link

Add a docs section for common bits-ui form components #135

Closed wesharper closed 4 months ago

wesharper commented 8 months ago

I love what you're doing with the new v2 (I've been checking it out on the preview site). In addition to the new guides section you've added, you might consider adding a bits-ui/shadcn integration section with a quickstarts for some common form elements like:

In fact, it might also be a good idea to rebrand the bits-ui docsite with the same treatment as the new formsnap and cross-promote. Would be more than happy to help anywhere I can.

huntabyte commented 8 months ago

Bits UI docs won't change in that aspect but good idea on the integrations for Formsnap!

huntabyte commented 8 months ago

I added a guide for Bits UI select & multiple select. Once it merges I'll happily accept some guide contributions for whatever you see fit!

wesharper commented 8 months ago

I see that the shadcn-svelte docs have already been updated. Should be a pretty simple copy/paste/check.

Now that I'm thinking on it though, it seems like bits, shadcn, and formsnap could all benefit from cross-promotion, and while I know that bits and shadcn aren't 1:1 clones of each other, the bones are mostly the same when it comes to raw functionality. Additionally, maintaining similar or even identical examples on docs pages across all 3 seems like an unnecessary burden considering the tight integration.

Does it make sense to have one docs page be sort of a source of truth for integrating formsnap with the custom builders with the others linking out? I could see any/all of them referencing each other and could make an argument for any of them being the source of truth.

My initial thought would be having a section on formsnap and bits that just links out to shadcn, which is the most opinionated. Would like to know how others feel about this.

ambergristle commented 4 months ago

hey y'all! i'm new to svelte/kit, and i really appreciate all the contributions you've made to the ecosystem. i've had my eye on svelte for a while, but it was projects like melt and bits-ui that convinced me to give it a try.

i was hoping you could provide some guidance RE integrating bits-ui range fields with formsnap (or superforms directly). my first implementation used a proxy, but i wasn't able to figure out client-side validation. i've since enabled client-side validation by refactoring into a derived store that is shared by two date pickers (that also share a range calendar), allowing me to pass the constraints to distinct inputs, but that feels sort of off.

i've included a representation of my current implementation below. i've looked through the docs and discussions for all three libraries, but i don't have a really good sense of how constraints interplay with client-side validation, or how multi-part form values are meant to be handled.

<script lang="ts" context="module">
  function deriveFieldState(form: SuperForm<{ startOn: string; endOn: string; }>) {

    const {
      value: startFieldValue,
      errors: startFieldErrors,
      constraints: startFieldConstraints,
    } = formFieldProxy(form, 'startOn');

    const {
      value: endFieldValue,
      errors: endFieldErrors,
      constraints: endFieldConstraints,
    } = formFieldProxy(form, 'endOn');

    const value = derived([startFieldValue, endFieldValue], ([start, end]) => {
      return {
        start: start ? parseDate(start) : undefined,
        end: end ? parseDate(end) : undefined,
      };
    });

    const setStart = (value: DateValue | undefined) => {
      if (value) {
        startFieldValue.set(value.toString());
      }
    };

    const setEnd = (value: DateValue | undefined) => {
      if (value) {
        endFieldValue.set(value.toString());
      }
    };

    return {
      value,
      setStart,
      setEnd,
      setRange: (value: DateRange) => {
        if (value.start && value.end) {
          setStart(value.start);
          setEnd(value.end);
        }
      },
      errors: {
        startFieldErrors,
        endFieldErrors,
      },
      constraints: {
        startFieldConstraints,
        endFieldConstraints,
      },
    };

  }
</script>

<Popover.Root openFocus bind:open={$open}>
  <Popover.Trigger asChild let:builder>
    <Form.Field {form} name="startOn">
      <Form.Control let:attrs>
        <DateField.Root value={$value.start} onValueChange={setStart}>
          <DateField.Input {...$startFieldConstraints} let:segments>
            {#each segments as { part, value }}
              <DateFieldPrimitive.Segment {part}>
                {value}
              </DateFieldPrimitive.Segment>
            {/each}
            <Button builders={[builder]} {...attrs}>
              <CalendarIcon />
            </Button>
          </DateField.Input>
        </DateField.Root>
      </Form.Control>
    </Form.Field>
    <!-- repeat for endOn -->
  </Popover.Trigger>
  <Popover.Content>
    <RangeCalendar
      value={$value}
      onValueChange={(dateRange) => {
        if (dateRange.start && dateRange.end) {
          setRange(dateRange);
          close();
        }
      }}
      initialFocus
      numberOfMonths={2}
      minValue={today(getLocalTimeZone())}
    />
  </Popover.Content>
</Popover.Root>
wesharper commented 4 months ago

@ambergristle. I would recommend checking out the shadcn-svelte repo and some of the source-code examples using the "view component source" buttons. Personally, I think they are pretty well done and I've learned a lot about some of the patterns they employ. Also, I'd encourage you to join Huntabyte's discord (if you see this before the link expires), which is a good channel for general support-related questions like this one. I'd also recommend spinning up a minimal repro in something like stackblitz or codesandbox with your code so someone can jump in and help you more easily. I don't want to discourage your questions, but I think you'd have more luck and support on a different channel for queries like this one.

@huntabyte I think this could probably get closed unless there's wide-scale community confusion or a more specific set of goals for what needs to be added. When I had initially asked, I wasn't really using shad-cn. We've since migrated a lot of our stuff to shad and adopted a lot of those patterns. Adding additional docs feels like a maintenance burden unless for some reason the average bits consumer is hitting some particular snags.

I don't personally know who the average bits consumer is and I assume that a majority of folks are either reaching for shad or will be reaching out for more specific issues.