diff --git a/docs/pages/docs/components/buffer.mdx b/docs/pages/docs/components/buffer.mdx
new file mode 100644
index 0000000..501fe20
--- /dev/null
+++ b/docs/pages/docs/components/buffer.mdx
@@ -0,0 +1,100 @@
+import { Callout } from 'nextra/components';
+import { Property } from '../../../components/Property'
+
+## Buffer
+
+`Buffer` is a component that handles window layout only and renders the contents of a given buffer.
+
+![](/gifs/buffer-1.gif)
+
+### Usage Example
+
+
+ The code example is using the [`gen.nvim`](https://github.com/David-Kunz/gen.nvim) plugin.
+
+
+```lua
+local renderer = n.create_renderer({
+ width = 60,
+ height = 3,
+})
+
+local signal = n.create_signal({
+ chat = "",
+ is_preview_visible = false,
+})
+
+local buf = vim.api.nvim_create_buf(false, true)
+
+local body = function()
+ return n.rows(
+ n.text_input({
+ border_label = "Chat",
+ autofocus = true,
+ wrap = true,
+ on_change = function(value)
+ signal.chat = value
+ end,
+ }),
+ n.buffer({
+ id = "preview",
+ flex = 1,
+ buf = buf,
+ autoscroll = true,
+ border_label = "Preview",
+ hidden = signal.is_preview_visible:negate(),
+ })
+ )
+end
+
+renderer:add_mappings({
+ {
+ mode = { "n", "i" },
+ key = "",
+ handler = function()
+ local gen = require("gen")
+ local state = signal:get_value()
+
+ renderer:set_size({ height = 20 })
+ signal.is_preview_visible = true
+
+ renderer:schedule(function()
+ gen.float_win = renderer:get_component_by_id("preview").winid
+ gen.result_buffer = buf
+ gen.exec({ prompt = state.chat })
+ end)
+ end,
+ },
+})
+
+renderer:render(body)
+```
+
+### Properties
+
+#### buf
+
+
+
+#### autoscroll
+
+
+
+#### filetype
+
+
+
+#### linebreak
+
+
diff --git a/docs/public/gifs/buffer-1.gif b/docs/public/gifs/buffer-1.gif
new file mode 100644
index 0000000..99f1afb
Binary files /dev/null and b/docs/public/gifs/buffer-1.gif differ
diff --git a/lua/nui-components/buffer.lua b/lua/nui-components/buffer.lua
new file mode 100644
index 0000000..4c7af22
--- /dev/null
+++ b/lua/nui-components/buffer.lua
@@ -0,0 +1,86 @@
+local Component = require("nui-components.component")
+local buf_storage = require("nui.utils.buf_storage")
+
+local fn = require("nui-components.utils.fn")
+
+local Buffer = Component:extend("Buffer")
+
+function Buffer:init(props, popup_options)
+ Buffer.super.init(
+ self,
+ fn.merge({
+ buf = nil,
+ autoscroll = false,
+ }, props),
+ fn.deep_merge({
+ buf_options = {
+ filetype = props.filetype or "",
+ },
+ win_options = {
+ linebreak = fn.default_to(props.linebreak, true),
+ },
+ }, popup_options)
+ )
+end
+
+function Buffer:prop_types()
+ return {
+ buf = "number",
+ autoscroll = "boolean",
+ filetype = { "string", "nil" },
+ }
+end
+
+function Buffer:_buf_create()
+ local props = self:get_props()
+
+ self.bufnr = props.buf
+
+ if props.autoscroll then
+ self._private.autoscroll_id = vim.api.nvim_create_autocmd("TextChanged", {
+ buffer = self.bufnr,
+ callback = function()
+ if not self.winid or not vim.api.nvim_win_is_valid(self.winid) then
+ return
+ end
+
+ if not self.bufnr or not vim.api.nvim_buf_is_valid(self.bufnr) then
+ return true
+ end
+
+ vim.api.nvim_win_set_cursor(self.winid, {
+ vim.api.nvim_buf_line_count(self.bufnr),
+ 9999,
+ })
+ end,
+ })
+ end
+end
+
+function Buffer:_buf_destroy()
+ buf_storage.cleanup(self.bufnr)
+
+ if self._private.autoscroll_id then
+ pcall(vim.api.nvim_del_autocmd, self._private.autoscroll_id)
+ self._private.autoscroll_id = nil
+ end
+
+ self.bufnr = nil
+end
+
+function Buffer:on_update()
+ local props = self:get_props()
+
+ if props.buf and self.bufnr ~= props.buf and self._.layout_ready then
+ local is_focused = vim.api.nvim_get_current_win() == self.winid
+
+ self:unmount()
+ self:mount()
+
+ if is_focused then
+ vim.api.nvim_set_current_win(self.winid)
+ end
+ end
+end
+
+return Buffer
diff --git a/lua/nui-components/init.lua b/lua/nui-components/init.lua
index 8459696..d042365 100644
--- a/lua/nui-components/init.lua
+++ b/lua/nui-components/init.lua
@@ -66,6 +66,7 @@ M.checkbox = require("nui-components.checkbox")
M.paragraph = require("nui-components.paragraph")
M.spinner = require("nui-components.spinner")
M.animated_text = require("nui-components.animated-text")
+M.buffer = require("nui-components.buffer")
M.tabs = add_children_prop(Tabs)
M.tab = add_children_prop(Tab)