{"id":"biotoxin495/uihighlighter","name":"uihighlighter","scope":"biotoxin495","platform":"roblox","description":"A lightweight client-side utility for highlighting GuiObjects with animated arrows.","version":"1.0.3","latest":"1.0.3","versions":["1.0.0","1.0.1","1.0.2","1.0.3"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"0dce8db75bc49e0b71d5d9f675e386ef1c0bd1d7b3b4afb74e5864013b6b634e","likes":0,"downloads":0,"install":"forest install biotoxin495/uihighlighter","url":"https://forest.dev/p/roblox/biotoxin495/uihighlighter","files":"https://api.forest.dev/ai/package/roblox/biotoxin495/uihighlighter/files","readme":"# UIHighlighter — An animated arrow highlighter for Roblox UI\n\n**UIHighlighter**, a lightweight, standalone utility for drawing the player's attention to a piece of Roblox UI.\n\nUIHighlighter lets you register any `GuiObject`—such as a button, frame, or icon—and surround it with four pulsing corner arrows, useful for tutorials, quest markers, \"new feature\" callouts, and any other UI element that needs to stand out.\n\nThe module handles overlay creation, per-frame positioning, pulse and color animation, and cleanup internally, while keeping the public API small and simple.\n\n## Quick example\n\nUIHighlighter attaches to any `GuiObject` through `Highlight`.\n\n```lua\nlocal UIHighlighter = require(ReplicatedStorage.UIHighlighter)\n\nlocal highlight = UIHighlighter.Highlight(script.Parent.PlayButton)\n```\n\nFour animated arrows immediately appear around the corners of `PlayButton`, pulsing outward and cycling color. Calling `highlight:Destroy()` removes them.\n\n## 🚀 Features\n\n### Corner arrow highlighting\n\nRegister a highlight on any `GuiObject` and UIHighlighter surrounds it with four arrows, one per corner.\n\n```lua\nUIHighlighter.Highlight(script.Parent.PlayButton)\n```\n\nArrows are repositioned and resized every frame to track the target's `AbsolutePosition` and `AbsoluteSize`, so the highlight follows the target through layout changes, tweens, and screen resizes.\n\n### Pulsing color animation\n\nArrows pulse outward from the target and smoothly lerp between two colors, with an optional rotation wiggle.\n\n```lua\nUIHighlighter.Highlight(script.Parent.PlayButton, {\n\tAnimation = {\n\t\tPulseSpeed = 4,\n\t\tPulseDistance = 18,\n\t\tColorA = Color3.fromRGB(80, 200, 255),\n\t\tColorB = Color3.fromRGB(255, 255, 255),\n\t},\n})\n```\n\nSetting `Animation.Enabled` to `false` freezes the arrows in place using `ColorA`.\n\n### Automatic visibility tracking\n\nThe highlight checks the target's `Visible` property—and that of every ancestor—every frame, and hides itself whenever the target is not actually on screen or has zero size, reappearing automatically once it is visible again.\n\n### Single highlight per target\n\nCalling `Highlight` again on a target that already has one replaces the previous highlight instead of stacking a second set of arrows on top of it.\n\n### Efficient by design\n\nAll active highlights share a single `RenderStepped` connection instead of running one loop per highlight. The loop starts automatically when the first highlight is created and stops automatically once none remain.\n\n### Fully typed, no dependencies\n\nThe module ships with a fully typed Luau API and has no external dependencies or framework requirements.\n\n## 📖 Basic usage\n\nPlace the `UIHighlighter` ModuleScript somewhere accessible to your client scripts, such as `ReplicatedStorage`. UIHighlighter must be required and used from a `LocalScript`.\n\n```lua\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\n\nlocal UIHighlighter = require(ReplicatedStorage.UIHighlighter)\n\nlocal highlight = UIHighlighter.Highlight(script.Parent.PlayButton)\n```\n\n### Example: tutorial arrow pointing at a button\n\n```lua\nlocal highlight = UIHighlighter.Highlight(script.Parent.ShopButton, {\n\tArrowSize = 48,\n\tPadding = 8,\n})\n\nshopButton.Activated:Connect(function()\n\thighlight:Destroy()\nend)\n```\n\n### Example: temporarily disabling a highlight\n\n```lua\nlocal highlight = UIHighlighter.Highlight(script.Parent.QuestButton)\n\n-- Hide the arrows without losing the registration\nhighlight:SetEnabled(false)\n\n-- Show them again later\nhighlight:SetEnabled(true)\n```\n\n### Example: custom colors, arrow image, and animation speed\n\n```lua\nUIHighlighter.Highlight(script.Parent.RewardIcon, {\n\tArrowImageId = \"rbxassetid://0000000000\",\n\tArrowSize = 40,\n\tScaleMultiplier = 1.4,\n\tZIndex = 250,\n\tAnimation = {\n\t\tPulseSpeed = 5,\n\t\tPulseDistance = 15,\n\t\tRotationWiggle = 8,\n\t\tColorA = Color3.fromRGB(255, 215, 0),\n\t\tColorB = Color3.fromRGB(255, 255, 255),\n\t},\n})\n```\n\n## ⚙️ API\n\n### `UIHighlighter.Highlight(target, config?)`\n\nCreates a highlight around a `GuiObject` and returns its controller. Replaces any existing highlight already registered on the same target.\n\n```lua\nlocal highlight = UIHighlighter.Highlight(Button, config)\n```\n\n### `UIHighlighter.Remove(target)`\n\nRemoves the highlight attached to a target, if one exists.\n\n```lua\nUIHighlighter.Remove(Button)\n```\n\n### `UIHighlighter.RemoveAll()`\n\nRemoves every currently active highlight.\n\n```lua\nUIHighlighter.RemoveAll()\n```\n\n### `UIHighlighter.HasHighlight(target)`\n\nReturns whether a target currently has a live highlight.\n\n```lua\nlocal hasHighlight = UIHighlighter.HasHighlight(Button)\n```\n\n### `UIHighlighter.GetHighlight(target)`\n\nReturns the highlight controller attached to a target, or `nil` if none exists.\n\n```lua\nlocal highlight = UIHighlighter.GetHighlight(Button)\n```\n\n### `UIHighlighter.Destroy()`\n\nCompletely tears down the module: removes every active highlight and destroys the generated overlay `ScreenGui`.\n\n```lua\nUIHighlighter.Destroy()\n```\n\n### `highlight:SetEnabled(enabled)`\n\nShows or hides this highlight's arrows without unregistering it.\n\n```lua\nhighlight:SetEnabled(false)\n```\n\n### `highlight:IsDestroyed()`\n\nReturns whether this highlight has already been destroyed.\n\n```lua\nlocal destroyed = highlight:IsDestroyed()\n```\n\n### `highlight:Destroy()`\n\nRemoves this highlight's arrows and unregisters it from its target.\n\n```lua\nhighlight:Destroy()\n```\n\nA highlight is also destroyed automatically once its target leaves the game tree.\n\n## Complete options reference\n\nYou normally only need to provide the options you want to change. Any omitted options use the module defaults.\n\n```lua\n{\n\tArrowImageId = \"rbxassetid://119492233291268\",\n\tArrowSize = 64,\n\tScaleMultiplier = 1.25,\n\tPadding = 0,\n\tZIndex = 100,\n\n\tAnimation = {\n\t\tEnabled = true,\n\t\tPulseSpeed = 3,\n\t\tPulseDistance = 25,\n\t\tRotationWiggle = 5,\n\t\tColorA = Color3.fromRGB(255, 83, 83),\n\t\tColorB = Color3.fromRGB(255, 215, 0),\n\t},\n}\n```\n\n| Option | Type | Description |\n| --- | --- | --- |\n| `ArrowImageId` | `string` | Asset ID used for each corner arrow |\n| `ArrowSize` | `number` | Side length of each arrow, in pixels |\n| `ScaleMultiplier` | `number` | Scales the highlight box relative to the target's size |\n| `Padding` | `number` | Additional pixels added around the target before scaling |\n| `ZIndex` | `number` | ZIndex of the highlight container; arrows render one above it |\n| `Animation.Enabled` | `boolean` | Enables the pulse, wiggle, and color animation |\n| `Animation.PulseSpeed` | `number` | Speed of the pulsing sine wave |\n| `Animation.PulseDistance` | `number` | Maximum distance arrows travel outward while pulsing |\n| `Animation.RotationWiggle` | `number` | Maximum rotation offset applied while pulsing, in degrees |\n| `Animation.ColorA` | `Color3` | First color in the pulse's color cycle |\n| `Animation.ColorB` | `Color3` | Second color in the pulse's color cycle |\n\n## Behavior\n\nOnly one highlight is active per target at a time; registering a new one on the same target replaces the old one.\n\nEach frame, the highlight recomputes its target's `AbsolutePosition` and `AbsoluteSize`, accounting for the topbar inset when the target's `ScreenGui` does not ignore it, then repositions all four arrows and updates their pulse offset, rotation, and color.\n\nIf the target becomes invisible, shrinks to zero size, or is destroyed, the highlight hides or removes itself automatically without any extra bookkeeping on your part.\n\n## 📝 Notes\n\n* UIHighlighter is intended for client-side UI and must be required from a `LocalScript`.\n* All highlights render inside a single shared overlay `ScreenGui` created under `PlayerGui`, above the rest of your interface.\n* The module creates arrow-based corner highlights and does not currently support arbitrary custom highlight shapes or full-border outlines.\n* Call `UIHighlighter.Destroy()` when you no longer need any highlights to clean up the generated overlay and stop the render loop.\n\n## 🛠️ Installation\n\n### Manual installation\n\nPlace the `UIHighlighter` ModuleScript somewhere accessible to your client scripts.\n\nRecommended structure:\n\n```text\nReplicatedStorage\n└── UIHighlighter\n```\n\nThen require it with:\n\n```lua\nlocal ReplicatedStorage = game:GetService(\"ReplicatedStorage\")\n\nlocal UIHighlighter = require(ReplicatedStorage.UIHighlighter)\n```\n\n## License\n\nThis project is available under the license included in the repository.\n\nmade with ❤️ by biotoxin495\n","readmeTruncated":false}