https://discord.gg/botpress logo
b
HELLO! I miss having a single choice with greater control. I've tried using CSS to emulate a menu, that is, taking the links generated by a single choice and styling them so that they are a flex in a column with a similar width, and it works and looks great. I have a sample photo there. However, I lose all of this when it becomes a Select, since there are several options and some have more characters than others. Is there any way to prevent it from becoming a Select? Any way to avoid it and let them remain “buttons” since with CSS I can style them as I like, but when forced into a Select I can no longer control them, just the selects width 😉 https://cdn.discordapp.com/attachments/1446144571259097210/1446144571833585745/botpress_menu.png?ex=69528e95&is=69513d15&hm=11b5dd09f970867c43439f8aedab0e2178be9063ad589f690bce69f45644c04a& https://cdn.discordapp.com/attachments/1446144571259097210/1446144572315926688/botpress_menu2.png?ex=69528e96&is=69513d16&hm=7a8fd6a970fa339b49d0b218d91d3d1f97a489c2d3a294d46f47a46456628668&
For example, can I program an integration that allows me to create a card that, when used, displays a more stylish menu? Like a single choice on steroids. All the integrations I've programmed usually do backend work, but to help me in this case, could I generate a card like this?
w
you can! you can use the [integration SDK](https://botpress.com/docs/for-developers/sdk/integration/getting-started) to built a custom integration with custom cards
b
I'm not so sure that's possible. Because I've programmed integrations, but mostly connections to other platforms. 😔
w
If I understand correctly, you need a custom widget; maybe this can help: https://discord.com/channels/1108396290624213082/1425548589702316062
b
Excellent, I was able to use your recommendation by creating a custom component. In terms of functionality, it's excellent; I was able to emulate a single-choice card. However, I have a problem that I don't understand how to avoid. I'll show you in the image. My custom card displays a stylized menu. When I click on one of the menu buttons, the menu is re-rendered, but it goes to the correct flow. How do I avoid this re-rendering? It's as if the node is mounted twice. My custom component does not run twice in my tests, but when I deploy it and use it in a node, when I click on one of the buttons, instead of going to the destination node, it first re-renders the menu and then goes to the destination node. The image shows what I mean. The menu currently consists of those two buttons there. Clicking on one of them re-renders the menu (I want to avoid this rendering), and it goes to the respective node (I just added some text to test it).
The menu is in the yellow rectangle, then the user clicks. Before going to the flow, it renders again (green rectangle) and below is the node corresponding to the selected button. Before going there, it shows the menu again, but ends up going where it should.
w
It seems a problem of retry on failure. The user click your option and the bot goes to the right node, but your widget seems set validation false.
If you try selecting your menu item 3–4 times, what happens?
What do you see in the log?
b
Copy code
import React from 'react'
import type { Props } from './schema'
import './styles.css'

// Botpress pasa estas props adicionales cuando el componente se usa en Capture Information
// Basado en el código fuente de @botpress/webchat, el componente recibe sendMessage
interface BotpressProps extends Props {
  sendMessage?: (payload: { type: 'text'; text: string; value: string }) => void
}

const Component: React.FC<BotpressProps> = ({
  text,
  choices = [],
  sendMessage
}) => {
  // Flag para evitar múltiples envíos por doble click o re-render
  const hasSentRef = React.useRef(false)
  const [hasSent, setHasSent] = React.useState(false)

  const handleChoiceClick = (value: string, label: string) => {
    if (hasSentRef.current) {
      return
    }

    hasSentRef.current = true
    setHasSent(true)
    // Comportamiento nativo: enviar la elección con sendMessage
    if (!sendMessage) return
    sendMessage({
      type: 'text',
      text: label,  // Label que ve el usuario
      value: value  // Valor que se guarda en Workflow
    })
  }

  return (
    <div className="custom-menu">
      {text && <div className="custom-menu-text">{text}</div>}
      {choices.length > 0 && (
        <div className="custom-menu-choices">
          {choices.map((choice, index) => (
            <button
              key={index}
              className="custom-menu-choice"
              onClick={() => handleChoiceClick(choice.value, choice.label)}
              data-value={choice.value}
              data-label={choice.label}
              aria-label={choice.label}
              disabled={hasSent}
              type="button"
            >
              <span className="choice-label">{choice.label}</span>
            </button>
          ))}
        </div>
      )}
    </div>
  )
}

export default Component
Just in case, here is the component code. If I analyze the log, it only seems to be rendered back since I see the component with a different ID. I added logs to see how it works and also added an ID to see if the node is remounted with a different ID, and indeed it seems that the node completely remounts it, but only for a moment, as it then moves on to the flow it should go to. All this happens with one click, i.e., I choose my option, see the rerender, and go to the destination node. If I click several times, the same thing happens. Both renders have different IDs. That is, I think the node renders the component (I assign it an ID), then I click, the node seems to mount it back in the transition (since I see the component with a different ID) and goes to the normal destination node. Each button goes to the node it should, but that re-render there is annoying and I can't find the problem.
w
@wooden-beard-40210 do you have the same issue?
b
Can anyone give me a hand with this, any ideas or anything? I still can't find a way to avoid double rendering.
w
Nope I haven't faced this problem..
b
So if I wanted to emulate a single choice, what would the component code be? I'm only interested in changing its style so that it doesn't become an automatic dropdown when there are more than 5 options.
😔
2 Views