I'd like to add css class names depending on the card type to the corresponding html element.
I already did this by setting the [AdaptiveCard.customCssSelector
] 1 attribute.
E.g. you just need to add builder.card.customCssSelector = "ac-thumbnail";
in this line and the resulting html-block will contain class="ac-container ac-thumbnail"
.
However, I'd like to be independent of Botframework-Webchat updates and put this logic into a middleware. According to the BotFramework-Webchat docs it's possible to add attachmentMiddleware
to the renderWebChat
function and manipulate the html elements.
In fact I get activities and attachments, but I'm not able to manipulate html-blocks or add a css selector.
Here's my middleware code:
export const cardCssSelector = ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const { activity } = action.payload;
for (var index in activity.attachments) {
const card = activity.attachments[index].content;
if(card.tap && card.tap.value){
card.customCssSelector = 'tap';
}
}
}
console.log(action);
return next(action);
};
Of course this doesn't work, since the attachments don't have the customCssSelector attribute.
To do true custom styling of web chat, then a little hacking is required. Some things to note:
adaptiveCards
[HTMLCollection] to a true array (cards
) for iterating.card-
classes for mapping the CSS to the card(s).children[2]
) for retrieving values. You will need to account for variations in your cards.First, create a store and filter on incoming activities, messages, and then on the ac-adaptiveCard
class.
const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => async action => {
if(activity.type === 'message') {
let aCards = document.body.getElementsByClassName('ac-adaptiveCard');
let bCards = Object.values( aCards);
for(let i = 0; i <= bCards.length - 1; i++) {
if( cards[i].children[2] && cards[i].children[2].innerText && cards[ i ].children[ 2 ].innerText === 'Request Assistance') {
cards[i].className += ' card-Adaptive'
}
if( cards[i].children[2] && cards[i].children[2].innerText && cards[ i ].children[ 2 ].innerText === 'Service details') {
cards[i].className += ' card-Hero'
}
}
}
}
I apply styling to the cards by assigned class.
.card-Adaptive {
background-color: black;
}
.card-Adaptive p {
color: white;
}
.card-Hero {
background-color: green;
}
I pass store
as a parameter.
window.ReactDOM.render(
<ReactWebChat
directLine={ directLine }
store={store}
/>,
document.getElementById( 'webchat' )
);
The adaptive card is black and the hero card is green.