diff --git a/docs/pages/docs/components/prompt.mdx b/docs/pages/docs/components/prompt.mdx
index 6fd4247..0da9f36 100644
--- a/docs/pages/docs/components/prompt.mdx
+++ b/docs/pages/docs/components/prompt.mdx
@@ -11,6 +11,7 @@ import { Property } from '../../../components/Property'
```lua
n.prompt({
prefix = " > ",
+ placeholder = "Enter a command",
border_label = {
text = "Command",
align = "center",
@@ -25,31 +26,51 @@ n.prompt({
#### value
-
#### prefix
-
+#### placeholder
+
+> Optional placeholder text to show when the input is empty.
+> Can be a string, a single virtual text chunk, or a list of virtual text chunks.
+
+
+
+A virtual text chunk is a tuple-like table where the first element
+is the text and the second element is the highlight group.
+
+```lua
+local placeholder = {
+ { "Hello", "Comment" },
+ { "World", "String" },
+}
+```
+
#### on_change
-
#### on_submit
-
#### submit_key
-
diff --git a/docs/pages/docs/components/text-input.mdx b/docs/pages/docs/components/text-input.mdx
index 0a6c0c0..cc8111d 100644
--- a/docs/pages/docs/components/text-input.mdx
+++ b/docs/pages/docs/components/text-input.mdx
@@ -3,14 +3,14 @@ import { Property } from '../../../components/Property'
## TextInput
-`TextInput` is a component that allows you to enter any text.
+`TextInput` is a component that allows you to enter any text.
![](/gifs/text-input-1.gif)
### Usage Example
```lua
-local signal = n.create_signal({
+local signal = n.create_signal({
value = "hello world",
})
@@ -20,6 +20,7 @@ n.text_input({
size = 1,
value = signal.value,
border_label = "Description",
+ placeholder = "Enter a description",
max_lines = 5,
on_change = function(value, component)
signal.value = value
@@ -38,7 +39,7 @@ n.text_input({
### Properties
-#### autoresize
+#### autoresize
#### value
-
+#### placeholder
+
+> Optional placeholder text to show when the input is empty.
+> Can be a string, a single virtual text chunk, or a list of virtual text chunks.
+
+
+
+A virtual text chunk is a tuple-like table where the first element
+is the text and the second element is the highlight group.
+
+```lua
+local placeholder = {
+ { "Hello", "Comment" },
+ { "World", "String" },
+}
+```
+
#### on_change
-
diff --git a/lua/nui-components/prompt.lua b/lua/nui-components/prompt.lua
index 9497ada..3e5de83 100644
--- a/lua/nui-components/prompt.lua
+++ b/lua/nui-components/prompt.lua
@@ -46,6 +46,8 @@ function Prompt:_attach_change_listener()
self:set_current_value(value)
props.on_change(value, self)
+ self:_update_placeholder()
+
if prefix_length > 0 then
vim.schedule(function()
self._private.prefix:highlight(self.bufnr, self.ns_id, 1, 0)
diff --git a/lua/nui-components/text-input.lua b/lua/nui-components/text-input.lua
index a428e83..434ebe7 100644
--- a/lua/nui-components/text-input.lua
+++ b/lua/nui-components/text-input.lua
@@ -11,6 +11,7 @@ function TextInput:init(props, popup_options)
autoresize = false,
max_lines = nil,
value = "",
+ placeholder = "",
on_change = fn.ignore,
border_style = "rounded",
}, props)
@@ -52,9 +53,39 @@ function TextInput:prop_types()
autoresize = { "boolean", "nil" },
wrap = { "boolean", "nil" },
filetype = { "string", "nil" },
+ placeholder = { "string", "table", "nil" },
}
end
+function TextInput:_update_placeholder()
+ local show = self:get_current_value() == ""
+ local props = self:get_props()
+ local placeholder = props.placeholder
+ if show and placeholder and placeholder ~= "" then
+ local virt_text
+ if type(placeholder) == "table" then
+ if type(placeholder[1]) == "table" then
+ -- multiple virt-text chunks
+ virt_text = placeholder
+ else
+ -- single virt-text chunk
+ virt_text = { placeholder }
+ end
+ else
+ -- string
+ virt_text = { { placeholder, "Comment" } }
+ end
+ self._private.placeholder_extmark = vim.api.nvim_buf_set_extmark(self.bufnr, self.ns_id, 0, 0, {
+ virt_text = virt_text,
+ virt_text_pos = "inline",
+ id = self._private.placeholder_extmark,
+ })
+ elseif self._private.placeholder_extmark then
+ vim.api.nvim_buf_del_extmark(self.bufnr, self.ns_id, self._private.placeholder_extmark)
+ self._private.placeholder_extmark = nil
+ end
+end
+
function TextInput:_attach_change_listener()
local props = self:get_props()
@@ -66,6 +97,8 @@ function TextInput:_attach_change_listener()
self:set_current_value(value)
props.on_change(value, self)
+ self:_update_placeholder()
+
if props.autoresize then
self._private.text_input_signal.size = math.max(#lines, self._private.text_input_initial_size)
end
@@ -184,6 +217,7 @@ end
function TextInput:on_mount()
self:_attach_change_listener()
+ self:_update_placeholder()
end
return TextInput