-
Notifications
You must be signed in to change notification settings - Fork 5
Add <HtmlPanel>
component
#4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First half of my review, second half coming up
README.md
Outdated
@@ -274,13 +274,28 @@ Accepted props: | |||
loading | |||
- `chatboxRef` (resp. `inboxRef`, `popupRef`) - Pass a ref (created with `useRef`) and it'll be set to the vanilla JS [Chatbox](https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Chatbox/) (resp. [Inbox](https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Inbox/), [Popup](https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Popup/)) instance. See [above](#using-refs) for an example. | |||
- All [Talk.ChatboxOptions](https://talkjs.com/docs/Reference/JavaScript_Chat_SDK/Session/#ChatboxOptions) | |||
- `children?: ReactNode` - Optional. You can provide an `<HtmlPanel>` component as a child to use [HTML Panels](https://talkjs.com/docs/Features/Customizations/HTML_Panels/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should explicitly say that HtmlPanels can be the only direct children
README.md
Outdated
|
||
Accepted props: | ||
|
||
- `url: string` - The URL you want to load inside the HTML panel. The URL can be absolute or relative. We recommend using same origin pages to have better control of the page. Learn more about HTML Panels and same origin pages [here](https://talkjs.com/docs/Features/Customizations/HTML_Panels/) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could be more precise, “to have better control” is a bit meaningless and also kinda wrong. It must be the same origin if they want to render children into it. If they don’t want to render their contents right here from React then the origin doesn’t matter. (Btw make sure you test both cases, ie that if there’s no children passed, and the panel has a different origin, there are no errors).
README.md
Outdated
|
||
- `height?: number` - Optional. The panel height in pixels. Defaults to `100px`. | ||
|
||
- `show?: boolean` - Optional. Sets the visibility of the panel. Defaults to `true`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Worth explaining how this is different vs conditionally rendering the HtmlPanel element
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
love it. got lots of nits tho cause i'm like that
lib/HtmlPanel.tsx
Outdated
|
||
return () => { | ||
if (state.type === "loaded") { | ||
state.panel.destroy(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't we always destroy it, regardless of loading state? else if customer code creates it and then quickly removes it, the chatbox will create it anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(maybe just put the Promise<HtmlPanel>
in the state, and do state.panelPromise.then(panel => panel.destroy())
. i don't think there's a downside to already-resolved panels being destroyed in the next microtask instead of right there in the cleanup callback, right?
lib/HtmlPanel.tsx
Outdated
state.panel.hide(); | ||
} | ||
} | ||
}, [state, show]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shouldn't this be state.type
instead of the entire state? (same for height
)
lib/HtmlPanel.tsx
Outdated
<> | ||
{state.type === "loaded" && | ||
createPortal(children, state.panel.window.document.body)} | ||
</> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
magic, isn't it? :D
btw i think this needs some "if no children given, then no portal" type logic, so we dont get errors when people mount non-same-origin html panels (eg because they're SSR'ing something from somewhere else)
lib/HtmlPanel.tsx
Outdated
const panel = await box.createHtmlPanel({ | ||
url, | ||
conversation: conversationId, | ||
height, | ||
show, | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
meta comment, I just realized that a set of <HtmlPanel>
components in a react app is semantically equivalent to the htmlPanelOptions
we pass from the JSSDK in the frontend.
this is actually super nuts. we internally have a declarative data structure, we built an imperative interface around that to mutate that data structure (createHtmlPanel, destroy, show, etc), and now here we're building the same thing in the opposite direction!
i don't think we need to do anything rn with this observation but i'm thinking that maybe one day we should deprecate all create*
and set*
methods entirely in favour of some vanilla JS, react-y declarative "spec your chatbox here" interface. would make the entire react sdk a near no-op, also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it. I think I reviewed everything now!
example/panel.html
Outdated
<head> | ||
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Document</title> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit meaningless, no? Maybe just keep the title out
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Document</title> | ||
<style> | ||
body { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's just give body, html
a padding: 0
for good measure? (and eg a margin on the button). i expect anybody will want to do that, so the html panel behaves pretty much like a div.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean here; the buttons already have margin: 0.6rem auto
<meta charset="UTF-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Document</title> | ||
<style> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about we prepend something here like
<link rel="stylesheet" href="./your-styles.css">
<!-- Put your app's CSS here. For instance, if your bundler generates a CSS file from all component styles, load it here as well and your components will be styled correctly inside the HTML Panel -->
Previously we'd incorrectly pass their `children` into `useUIBox` which would cause the UIBoxes to be destroyed and re-initialized over and over.
Hello there ! Thank you so much for your Pull Request, I'll move to your fork as I definitely need it :) Might be nice to merge it at some point |
@eteeselink Arf actually I cannot manage to use this branch directly, no types etc... Could you release it on a canary version or whatsoever ? It would be of great help :) |
The experimental
|
Merge branch 'master' into feat/htmlpanel
This PR adds the
<HtmlPanel>
component.I've also updated the example app to include an HTML panel so you can see it in action.