Skip to content

Commit

Permalink
feat: ✨ add support for video block
Browse files Browse the repository at this point in the history
  • Loading branch information
themashcodee committed Jun 28, 2024
1 parent 16968f7 commit f597b66
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 7 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
],
"repository": "https://github.com/themashcodee/slack-blocks-to-jsx.git",
"license": "MIT",
"version": "0.3.0",
"version": "0.3.1",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
Expand Down
17 changes: 13 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# Slack Blocks to JSX Documentation

## Overview

The `slack-blocks-to-jsx` package allows you to render Slack blocks in React with styles that closely mimic how they are displayed in Slack. This library converts Slack's block kit components into JSX components, maintaining the visual fidelity and interactive elements.

**🚨 Quickly test out the libray on online playground**: https://slack-block-to-jsx-playground.vercel.app/

## Installation

To use this package in your project, install it via npm:

```bash
Expand All @@ -21,13 +23,15 @@ yarn add slack-blocks-to-jsx
## Usage

### Importing Styles

Import the necessary CSS file in your entry point to ensure the styles are applied:

```javascript
import "slack-blocks-to-jsx/dist/style.css";
```

### Using Components

Import the `Message` component from the package and use it to render your Slack blocks:

```javascript
Expand All @@ -39,6 +43,7 @@ const blocks = [...]; // your Slack blocks data
```

### Types

For better type safety, you can import the `Block` type:

```javascript
Expand All @@ -50,6 +55,7 @@ const blocks: Block[] = [...]; // your Slack blocks data
## Components

### `Message`

This is the main component that renders the entire Slack message. It supports various props to customize the appearance and behavior:

- `blocks`: Array of Slack block objects.
Expand All @@ -64,6 +70,7 @@ This is the main component that renders the entire Slack message. It supports va
- `showBlockKitDebug?`: Show a link to open the message in the Slack Block Kit Builder, for debugging purposes. Defaults to false.

### Block Components

Each Slack block type has a corresponding component:

- `Section` (✅ supported)
Expand All @@ -75,11 +82,12 @@ Each Slack block type has a corresponding component:
- `Header` (❌ not supported yet)
- `Input` (🟨 partially supported)
- `RichText` (✅ supported)
- `Video` (❌ not supported yet)
- `Video` (supported)

If you want a support of a particular block or element which is not supported yet so please raise a github issue or mail me at [email protected]. I will try to push it asap.

## Customization

You can handle custom rendering and interactions using the `hooks` prop in the `Message` component. This allows you to define custom behavior for user mentions, channels, and other interactive elements. You can also override default styling. Here are the classes structure to understand to override any block styling.

`.slack_blocks_to_jsx`: Main Wrapper
Expand All @@ -90,25 +98,26 @@ You can handle custom rendering and interactions using the `hooks` prop in the `
`.slack_blocks_to_jsx__section`: Section Block
`.slack_blocks_to_jsx__image`: Image Block
`.slack_blocks_to_jsx__context`: Context Block
`.slack_blocks_to_jsx__actions`: Actions Block
`.slack_blocks_to_jsx__actions`: Actions Block
`.slack_blocks_to_jsx__input`: Input Block
`.slack_blocks_to_jsx__rich_text`: Rich Text Block
`.slack_blocks_to_jsx__rich_text_list_element`: Rich Text Block List Element
`.slack_blocks_to_jsx__rich_text_preformatted_element`: Rich Text Block Preformatted Element
`.slack_blocks_to_jsx__rich_text_quote_element`: Rich Text Block Element Quote Element
`.slack_blocks_to_jsx__rich_text_section_element`: Rich Text Block Section Element
`.slack_blocks_to_jsx__rich_text_section_element`: Rich Text Block Section Element

...as so on (all the other classes will be similar too, for example `.slack_blocks_to_jsx__rich_text_section_element_user` for Rich Text Block Section Element User)

If you want any other customization so please raise a github issue or mail me at [email protected]. I will try to push it asap if it aligns with the library development vision.


## Development and Contribution

The project is open-source, and contributions are welcome. If you encounter any issues or want to suggest improvements, please file an issue on the GitHub repository:

[GitHub Repository Issues](https://github.com/themashcodee/slack-blocks-to-jsx/issues)

## License

The project is licensed under the MIT license, allowing free use, modification, and distribution.

## Support
Expand Down
86 changes: 84 additions & 2 deletions src/components/blocks/video.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,93 @@
import { useState } from "react";
import { VideoBlock } from "../../types";
import { TextObject } from "../composition_objects";

type VideoProps = {
data: VideoBlock;
};

export const Video = (props: VideoProps) => {
const { type } = props.data;
const {
// thumbnail_url,

This comment has been minimized.

Copy link
@StephenTangCook

StephenTangCook Jul 3, 2024

Contributor

nit: remove

This comment has been minimized.

Copy link
@themashcodee

themashcodee Jul 4, 2024

Author Owner

Hey sorry I couldn't get it. Which line are you suggesting to remove?

This comment has been minimized.

Copy link
@StephenTangCook

StephenTangCook Jul 4, 2024

Contributor

The commented-out code

// provider_icon_url,
// provider_name,
//
alt_text,
title,
video_url,
author_name,
block_id,
description,
title_url,
iframeProps = {},
} = props.data;

return null;
const [showVideo, setShowVideo] = useState(true);

return (
<div className="py-2 slack_blocks_to_jsx__video" id={block_id}>
{author_name && (
<div className="slack_blocks_to_jsx__video_author">
<span className="font-bold">Manish Panwar</span>

This comment has been minimized.

Copy link
@StephenTangCook

StephenTangCook Jul 3, 2024

Contributor

Remove please 🙏

This comment has been minimized.

Copy link
@themashcodee

themashcodee Jul 4, 2024

Author Owner

Hey sorry I couldn't get it. Which line are you suggesting to remove?

This comment has been minimized.

Copy link
@StephenTangCook

StephenTangCook Jul 4, 2024

Contributor

Was it intentional that you left in your name as the author? :)

This comment has been minimized.

Copy link
@themashcodee

themashcodee Jul 5, 2024

Author Owner

😅 actually no, I did it by mistake.

This comment has been minimized.

Copy link
@themashcodee

themashcodee Jul 5, 2024

Author Owner

✅ fixed in v0.3.6

</div>
)}

{description && (
<div className="slack_blocks_to_jsx__video_description">
<TextObject data={description} />
</div>
)}

<div className="flex flex-wrap items-center gap-1 slack_blocks_to_jsx__video_title">
{title_url ? (
<a href={title_url} className="text-blue-primary" target="_blank" rel="noreferrer">
<TextObject data={title} />
</a>
) : (
<p>
<TextObject data={title} />
</p>
)}

<button
type="button"
className="w-[15px] h-[15px]"
onClick={() => setShowVideo((prev) => !prev)}
>
<svg
xmlns="http://www.w3.org/2000/svg"
fillRule="evenodd"
clipRule="evenodd"
className="text-blue-primary"
imageRendering="optimizeQuality"
shapeRendering="geometricPrecision"
textRendering="geometricPrecision"
viewBox="0 0 512 336.36"
width={6}
height={6}
style={{
transform: showVideo ? "rotate(0deg)" : "rotate(-90deg)",
}}
>
<path
fill="currentColor"
fillRule="nonzero"
d="M42.47.01L469.5 0C492.96 0 512 19.04 512 42.5c0 11.07-4.23 21.15-11.17 28.72L294.18 320.97c-14.93 18.06-41.7 20.58-59.76 5.65-1.8-1.49-3.46-3.12-4.97-4.83L10.43 70.39C-4.97 52.71-3.1 25.86 14.58 10.47 22.63 3.46 32.57.02 42.47.01z"
></path>
</svg>
</button>
</div>

<div className="slack_blocks_to_jsx__video_container max-w-max">
{showVideo && (
<iframe

This comment has been minimized.

Copy link
@StephenTangCook

StephenTangCook Jul 3, 2024

Contributor

Curious, what are the advantages of iframe over a <video> tag?

This comment has been minimized.

Copy link
@themashcodee

themashcodee Jul 4, 2024

Author Owner

There is no advantage as such, but iframe was easy and quick to implement and I also did not have to create a custom video player which will need a lot of states for the controllers.

title={alt_text}
className="max-w-[360px] bg-gray-100 w-full aspect-video"
src={video_url}
{...iframeProps}
/>
)}
</div>
</div>
);
};
5 changes: 5 additions & 0 deletions src/types/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
UsersSelectElement,
} from ".";
import { RichTextBlockElement } from "../types";
import { ComponentPropsWithoutRef } from "react";

export type Block =
| ActionsBlock
Expand Down Expand Up @@ -303,6 +304,10 @@ export type VideoBlock = {
* The URL to be embedded. Must match any existing {@link https://api.slack.com/reference/messaging/link-unfurling#configuring_domains unfurl domains} within the app and point to a HTTPS URL.
*/
video_url: string;
/**
* This is a custom property added by slack-block-to-jsx library to more control over iframe
*/
iframeProps?: ComponentPropsWithoutRef<"iframe">;
};

export type RichTextBlock = {
Expand Down

0 comments on commit f597b66

Please sign in to comment.