Fork me on GitHub
#reagent
<
2023-06-27
>
Ovi Stoica18:06:35

I’m trying to have this effect, where if you have asChild the button will use the child element and apply all its styles to the child as opposed to using :button

// The final HTML will just be <a .. /> instead of `<button />`
export function ButtonAsChild() {
  return (
    <Button asChild>
      <a href="/login">Login</Link>
    </Button>
  )
}
Here’s the react implementation doing the exact thing
import { Slot } from "@radix-ui/react-slot"

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  ({ className, variant, size, asChild = false, ...props }, ref) => {
    const Comp = asChild ? Slot : "button"
    return (
      <Comp
        className={cn(buttonVariants({ variant, size, className }))}
        ref={ref}
        {...props}
      />
    )
  }
)
here’s my cljs equivalent (it does not render correctly):
(defn props-children
  []
  (let [this (r/current-component)
        props (r/props this)
        children (r/children this)]
    {:props props
     :children children}))

(defn render-children
  [children]
  (for [child children]
    child))

(def slot (r/adapt-react-class Slot)) ;; same as in JS example

(defn button
  [& _]
  (let [{:keys [props children]} (props-children)
        {:keys [as-child class]} props
        comp (if as-child slot :button)
        rest (dissoc props :class :variant :size :as-child)
        classes (u/get-classes
                 button-variants
                 (select-keys props [:variant :size]))
        component-props (merge {:class (u/tw class classes)} rest)]
    [comp component-props
     (render-children children)]))

;; Not rendering
[button {:as-child true}
     [:a {:href "login"} "Login"]]
I’m pretty sure it’s related to the Slot component and how that interracts with reagent but I can’t really put my finger on it. Any ideas?