[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-5007":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":14,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":10,"updatedAt":33,"readmeContent":34,"aiSummary":35,"trendingCount":16,"starSnapshotCount":16,"syncStatus":36,"lastSyncTime":37,"discoverSource":38},5007,"lipgloss","charmbracelet\u002Flipgloss","charmbracelet","Style definitions for nice terminal layouts 👄","",null,"Go",11410,359,40,61,0,6,168,27,109.67,"MIT License",false,"main",true,[26,27,28,29,30,31,32],"cli","go","golang","hacktoberfest","layout","style","tui","2026-06-12 04:00:24","# Lip Gloss\n\n\u003Cp >\n    \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd13bbe1a-d2b2-4d18-9302-419a0bc3f579\" width=\"350\">\u003Cbr>\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Freleases\">\u003Cimg src=\"https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Frelease\u002Fcharmbracelet\u002Flipgloss.svg\" alt=\"Latest Release\">\u003C\u002Fa>\n    \u003Ca href=\"https:\u002F\u002Fpkg.go.dev\u002Fcharm.land\u002Flipgloss\u002Fv2?tab=doc\">\u003Cimg src=\"https:\u002F\u002Fgodoc.org\u002Fgithub.com\u002Fgolang\u002Fgddo?status.svg\" alt=\"GoDoc\">\u003C\u002Fa>\n    \u003Ca href=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Factions\">\u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fworkflows\u002Fbuild\u002Fbadge.svg\" alt=\"Build Status\">\u003C\u002Fa>\n\u003C\u002Fp>\n\n\u003Cp>Style definitions for nice terminal layouts. Built with TUIs in mind.\u003C\u002Fp>\n\n![Lip Gloss example](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F92560e60-d70e-4ce0-b39e-a60bb933356b)\n\nLip Gloss takes an expressive, declarative approach to terminal rendering.\nUsers familiar with CSS will feel at home with Lip Gloss.\n\n```go\nimport \"charm.land\u002Flipgloss\u002Fv2\"\n\nvar style = lipgloss.NewStyle().\n    Bold(true).\n    Foreground(lipgloss.Color(\"#FAFAFA\")).\n    Background(lipgloss.Color(\"#7D56F4\")).\n    PaddingTop(2).\n    PaddingLeft(4).\n    Width(22)\n\nlipgloss.Println(style.Render(\"Hello, kitty\"))\n```\n\n## Installation\n\n```bash\ngo get charm.land\u002Flipgloss\u002Fv2\n```\n\n> [!TIP]\n>\n> Upgrading from v1? Check out the [upgrade guide](.\u002FUPGRADE_GUIDE_V2.md), or\n> point your LLM at it and let it go to town.\n\n## Colors\n\nLip Gloss supports the following color profiles:\n\n### ANSI 16 colors (4-bit)\n\n```go\nlipgloss.Color(\"5\")  \u002F\u002F magenta\nlipgloss.Color(\"9\")  \u002F\u002F red\nlipgloss.Color(\"12\") \u002F\u002F light blue\n```\n\n### ANSI 256 Colors (8-bit)\n\n```go\nlipgloss.Color(\"86\")  \u002F\u002F aqua\nlipgloss.Color(\"201\") \u002F\u002F hot pink\nlipgloss.Color(\"202\") \u002F\u002F orange\n```\n\n### True Color (16,777,216 colors; 24-bit)\n\n```go\nlipgloss.Color(\"#0000FF\") \u002F\u002F good ol' 100% blue\nlipgloss.Color(\"#04B575\") \u002F\u002F a green\nlipgloss.Color(\"#3C3C3C\") \u002F\u002F a dark gray\n```\n\n...as well as a 1-bit ASCII profile, which is black and white only.\n\nThere are also named constants for the 16 standard ANSI colors:\n\n```go\nlipgloss.Black\nlipgloss.Red\nlipgloss.Green\nlipgloss.Yellow\nlipgloss.Blue\nlipgloss.Magenta\nlipgloss.Cyan\nlipgloss.White\nlipgloss.BrightBlack\nlipgloss.BrightRed\nlipgloss.BrightGreen\nlipgloss.BrightYellow\nlipgloss.BrightBlue\nlipgloss.BrightMagenta\nlipgloss.BrightCyan\nlipgloss.BrightWhite\n```\n\n### Automatically Downsampling Colors\n\nSome users don't have Truecolor terminals. Other times, output might not\nsupport color at all (for example, in logs). Lip Gloss was designed to handle\nthis gracefully by automatically downsampling colors to the best available\nprofile.\n\nIf you're using Lip Gloss with Bubble Tea, there’s nothing to do. If you're\nusing Lip Gloss standalone, just use `lipgloss.Println` or `lipgloss.Sprint`\n(and their variants).\n\nFor more, see [advanced color usage](#advanced-color-usage).\n\n### Color Utilities\n\nLip Gloss ships with a handful of handy tools for working with colors:\n\n```go\nc := lipgloss.Color(\"#EB4268\")      \u002F\u002F Sriracha sauce color\ndark := lipgloss.Darken(c, 0.5)     \u002F\u002F dark Sriracha sauce\nlight := lipgloss.Lighten(c, 0.35)  \u002F\u002F light Sriracha sauce\ngreen := lipgloss.Complementary(c)  \u002F\u002F greenish Sriracha sauce\nwithAlpha := lipgloss.Alpha(c, 0.2) \u002F\u002F watered down Sriracha sauce\n```\n\n### Advanced Color Tooling\n\nLip Gloss also supports color blending, automatically choosing light or dark\nvariants of colors at runtime, and a lot more. For details, see [Advanced Color\nUsage](#advanced-color-usage) and [the docs][docs].\n\n## Inline Formatting\n\nLip Gloss supports the usual ANSI text formatting options:\n\n```go\nvar style = lipgloss.NewStyle().\n    Bold(true).\n    Italic(true).\n    Faint(true).\n    Blink(true).\n    Strikethrough(true).\n    Underline(true).\n    Reverse(true)\n```\n\n### Underline Styles\n\nBeyond simple on\u002Foff, underlines support multiple styles and custom colors:\n\n```go\ns := lipgloss.NewStyle().\n    UnderlineStyle(lipgloss.UnderlineCurly).\n    UnderlineColor(lipgloss.Color(\"#FF0000\"))\n```\n\nAvailable styles: `UnderlineNone`, `UnderlineSingle`, `UnderlineDouble`,\n`UnderlineCurly`, `UnderlineDotted`, `UnderlineDashed`.\n\n### Hyperlinks\n\nStyles can render clickable hyperlinks in supporting terminals:\n\n```go\ns := lipgloss.NewStyle().\n    Foreground(lipgloss.Color(\"#7B2FBE\")).\n    Hyperlink(\"https:\u002F\u002Fcharm.land\")\n\nlipgloss.Println(s.Render(\"Visit Charm\"))\n```\n\nIn unsupported terminals this will degrade gracefully and hyperlinks will\nsimply not render.\n\n## Block-Level Formatting\n\nLip Gloss also supports rules for block-level formatting:\n\n```go\n\u002F\u002F Padding\nvar style = lipgloss.NewStyle().\n    PaddingTop(2).\n    PaddingRight(4).\n    PaddingBottom(2).\n    PaddingLeft(4)\n\n\u002F\u002F Margins\nvar style = lipgloss.NewStyle().\n    MarginTop(2).\n    MarginRight(4).\n    MarginBottom(2).\n    MarginLeft(4)\n```\n\nThere is also shorthand syntax for margins and padding, which follows the same\nformat as CSS:\n\n```go\n\u002F\u002F 2 cells on all sides\nlipgloss.NewStyle().Padding(2)\n\n\u002F\u002F 2 cells on the top and bottom, 4 cells on the left and right\nlipgloss.NewStyle().Margin(2, 4)\n\n\u002F\u002F 1 cell on the top, 4 cells on the sides, 2 cells on the bottom\nlipgloss.NewStyle().Padding(1, 4, 2)\n\n\u002F\u002F Clockwise, starting from the top: 2 cells on the top, 4 on the right, 3 on\n\u002F\u002F the bottom, and 1 on the left\nlipgloss.NewStyle().Margin(2, 4, 3, 1)\n```\n\nYou can also customize the characters used for padding and margin fill:\n\n```go\ns := lipgloss.NewStyle().\n    Padding(1, 2).\n    PaddingChar('·').\n    Margin(1, 2).\n    MarginChar('░')\n```\n\n## Aligning Text\n\nYou can align paragraphs of text to the left, right, or center.\n\n```go\nvar style = lipgloss.NewStyle().\n    Width(24).\n    Align(lipgloss.Left).  \u002F\u002F align it left\n    Align(lipgloss.Right). \u002F\u002F no wait, align it right\n    Align(lipgloss.Center) \u002F\u002F just kidding, align it in the center\n```\n\n## Width and Height\n\nSetting a minimum width and height is simple and straightforward.\n\n```go\nvar style = lipgloss.NewStyle().\n    SetString(\"What’s for lunch?\").\n    Width(24).\n    Height(32).\n    Foreground(lipgloss.Color(\"63\"))\n```\n\n## Borders\n\nAdding borders is easy:\n\n```go\n\u002F\u002F Add a purple, rectangular border\nvar style = lipgloss.NewStyle().\n    BorderStyle(lipgloss.NormalBorder()).\n    BorderForeground(lipgloss.Color(\"63\"))\n\n\u002F\u002F Set a rounded, yellow-on-purple border to the top and left\nvar anotherStyle = lipgloss.NewStyle().\n    BorderStyle(lipgloss.RoundedBorder()).\n    BorderForeground(lipgloss.Color(\"228\")).\n    BorderBackground(lipgloss.Color(\"63\")).\n    BorderTop(true).\n    BorderLeft(true)\n\n\u002F\u002F Make your own border\nvar myCuteBorder = lipgloss.Border{\n    Top:         \"._.:*:\",\n    Bottom:      \"._.:*:\",\n    Left:        \"|*\",\n    Right:       \"|*\",\n    TopLeft:     \"*\",\n    TopRight:    \"*\",\n    BottomLeft:  \"*\",\n    BottomRight: \"*\",\n}\n```\n\nThere are also shorthand functions for defining borders, which follow a similar\npattern to the margin and padding shorthand functions.\n\n```go\n\u002F\u002F Add a thick border to the top and bottom\nlipgloss.NewStyle().\n    Border(lipgloss.ThickBorder(), true, false)\n\n\u002F\u002F Add a double border to the top and left sides. Rules are set clockwise\n\u002F\u002F from top.\nlipgloss.NewStyle().\n    Border(lipgloss.DoubleBorder(), true, false, false, true)\n```\n\nYou can also pass multiple colors to a border for a gradient effect:\n\n```go\ns := lipgloss.NewStyle().\n    Border(lipgloss.RoundedBorder()).\n    BorderForegroundBlend(lipgloss.Color(\"#FF0000\"), lipgloss.Color(\"#0000FF\"))\n```\n\nFor more on borders see [the docs](https:\u002F\u002Fpkg.go.dev\u002Fcharm.land\u002Flipgloss\u002Fv2#Border).\n\n## Copying Styles\n\nJust use assignment:\n\n```go\nstyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"219\"))\n\ncopiedStyle := style \u002F\u002F this is a true copy\n\nwildStyle := style.Blink(true) \u002F\u002F this is also true copy, with blink added\n```\n\nSince `Style` is a pure value type, assigning a style to another effectively\ncreates a new copy of the style without mutating the original.\n\n## Inheritance\n\nStyles can inherit rules from other styles. When inheriting, only unset rules\non the receiver are inherited.\n\n```go\nvar styleA = lipgloss.NewStyle().\n    Foreground(lipgloss.Color(\"229\")).\n    Background(lipgloss.Color(\"63\"))\n\n\u002F\u002F Only the background color will be inherited here, because the foreground\n\u002F\u002F color will have been already set:\nvar styleB = lipgloss.NewStyle().\n    Foreground(lipgloss.Color(\"201\")).\n    Inherit(styleA)\n```\n\n## Unsetting Rules\n\nAll rules can be unset:\n\n```go\nvar style = lipgloss.NewStyle().\n    Bold(true).                        \u002F\u002F make it bold\n    UnsetBold().                       \u002F\u002F jk don't make it bold\n    Background(lipgloss.Color(\"227\")). \u002F\u002F yellow background\n    UnsetBackground()                  \u002F\u002F never mind\n```\n\nWhen a rule is unset, it won’t be inherited or copied.\n\n## Enforcing Rules\n\nSometimes, such as when developing a component, you want to make sure style\ndefinitions respect their intended purpose in the UI. This is where `Inline`\nand `MaxWidth`, and `MaxHeight` come in:\n\n```go\n\u002F\u002F Force rendering onto a single line, ignoring margins, padding, and borders.\nsomeStyle.Inline(true).Render(\"yadda yadda\")\n\n\u002F\u002F Also limit rendering to five cells\nsomeStyle.Inline(true).MaxWidth(5).Render(\"yadda yadda\")\n\n\u002F\u002F Limit rendering to a 5x5 cell block\nsomeStyle.MaxWidth(5).MaxHeight(5).Render(\"yadda yadda\")\n```\n\n## Tabs\n\nThe tab character (`\\t`) is rendered differently in different terminals (often\nas 8 spaces, sometimes 4). Because of this inconsistency, Lip Gloss converts\ntabs to 4 spaces at render time. This behavior can be changed on a per-style\nbasis, however:\n\n```go\nstyle := lipgloss.NewStyle() \u002F\u002F tabs will render as 4 spaces, the default\nstyle = style.TabWidth(2)    \u002F\u002F render tabs as 2 spaces\nstyle = style.TabWidth(0)    \u002F\u002F remove tabs entirely\nstyle = style.TabWidth(lipgloss.NoTabConversion) \u002F\u002F leave tabs intact\n```\n\n## Wrapping\n\nThe `Wrap` function wraps text while preserving ANSI styles and hyperlinks\nacross line boundaries:\n\n```go\nwrapped := lipgloss.Wrap(styledText, 40, \" \")\n```\n\n## Rendering\n\nGenerally, you just call the `Render(string...)` method on a `lipgloss.Style`:\n\n```go\nstyle := lipgloss.NewStyle().Bold(true).SetString(\"Hello,\")\nlipgloss.Println(style.Render(\"kitty.\")) \u002F\u002F Hello, kitty.\nlipgloss.Println(style.Render(\"puppy.\")) \u002F\u002F Hello, puppy.\n```\n\nBut you could also use the Stringer interface:\n\n```go\nvar style = lipgloss.NewStyle().SetString(\"你好，猫咪。\").Bold(true)\nlipgloss.Println(style) \u002F\u002F 你好，猫咪。\n```\n\n## Utilities\n\nIn addition to pure styling, Lip Gloss also ships with some utilities to help\nassemble your layouts.\n\n### Compositing\n\n\u003Cp>\u003Cimg width=\"350\" alt=\"xx\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F1921bac6-2408-436a-9d9e-7930fe4c6ec9\" \u002F>\u003C\u002Fp>\n\nLip Gloss includes a powerful, cell-based compositor for rendering layered\ncontent:\n\n```go\n\u002F\u002F Create some layers.\na := lipgloss.NewLayer(pickles).X(4).Y(2).Z(1)\nb := lipgloss.NewLayer(bitterMelon).X(22).Y(1)\nc := lipgloss.NewLayer(sriracha).X(11).Y(7)\n\n\u002F\u002F Composite 'em and render.\noutput := compositor.Compose(a, b, c).Render()\n```\n\nFor a more thorough example, see [the canvas\nexample](.\u002Fexamples\u002Fcanvas\u002Fmain.go). For reference, including how to detect\nmouse clicks on layers, see [the docs][docs].\n\n### Joining Paragraphs\n\nHorizontally and vertically joining paragraphs is a cinch.\n\n```go\n\u002F\u002F Horizontally join three paragraphs along their bottom edges\nlipgloss.JoinHorizontal(lipgloss.Bottom, paragraphA, paragraphB, paragraphC)\n\n\u002F\u002F Vertically join two paragraphs along their center axes\nlipgloss.JoinVertical(lipgloss.Center, paragraphA, paragraphB)\n\n\u002F\u002F Horizontally join three paragraphs, with the shorter ones aligning 20%\n\u002F\u002F from the top of the tallest\nlipgloss.JoinHorizontal(0.2, paragraphA, paragraphB, paragraphC)\n```\n\n### Measuring Width and Height\n\nSometimes you’ll want to know the width and height of text blocks when building\nyour layouts.\n\n```go\n\u002F\u002F Render a block of text.\nvar style = lipgloss.NewStyle().\n    Width(40).\n    Padding(2)\nvar block string = style.Render(someLongString)\n\n\u002F\u002F Get the actual, physical dimensions of the text block.\nwidth := lipgloss.Width(block)\nheight := lipgloss.Height(block)\n\n\u002F\u002F Here's a shorthand function.\nw, h := lipgloss.Size(block)\n```\n\n### Blending Colors\n\nYou can blend colors in one or two dimensions for gradient effects:\n\n```go\n\u002F\u002F 1-dimentinoal gradient\ncolors := lipgloss.Blend1D(10, lipgloss.Color(\"#FF0000\"), lipgloss.Color(\"#0000FF\"))\n\n\u002F\u002F 2-dimensional gradient with rotation\ncolors := lipgloss.Blend2D(80, 24, 45.0, color1, color2, color3)\n```\n\n### Placing Text in Whitespace\n\nSometimes you’ll simply want to place a block of text in whitespace. This is\na lightweight alternative to compositing.\n\n```go\n\u002F\u002F Center a paragraph horizontally in a space 80 cells wide. The height of\n\u002F\u002F the block returned will be as tall as the input paragraph.\nblock := lipgloss.PlaceHorizontal(80, lipgloss.Center, fancyStyledParagraph)\n\n\u002F\u002F Place a paragraph at the bottom of a space 30 cells tall. The width of\n\u002F\u002F the text block returned will be as wide as the input paragraph.\nblock := lipgloss.PlaceVertical(30, lipgloss.Bottom, fancyStyledParagraph)\n\n\u002F\u002F Place a paragraph in the bottom right corner of a 30x80 cell space.\nblock := lipgloss.Place(30, 80, lipgloss.Right, lipgloss.Bottom, fancyStyledParagraph)\n```\n\nYou can also style the whitespace. For details, see [the docs][docs].\n\n## Rendering Tables\n\nLip Gloss ships with a table rendering sub-package.\n\n```go\nimport \"charm.land\u002Flipgloss\u002Fv2\u002Ftable\"\n```\n\nDefine some rows of data.\n\n```go\nrows := [][]string{\n    {\"Chinese\", \"您好\", \"你好\"},\n    {\"Japanese\", \"こんにちは\", \"やあ\"},\n    {\"Arabic\", \"أهلين\", \"أهلا\"},\n    {\"Russian\", \"Здравствуйте\", \"Привет\"},\n    {\"Spanish\", \"Hola\", \"¿Qué tal?\"},\n}\n```\n\nUse the table package to style and render the table.\n\n```go\nvar (\n    purple    = lipgloss.Color(\"99\")\n    gray      = lipgloss.Color(\"245\")\n    lightGray = lipgloss.Color(\"241\")\n\n    headerStyle  = lipgloss.NewStyle().Foreground(purple).Bold(true).Align(lipgloss.Center)\n    cellStyle    = lipgloss.NewStyle().Padding(0, 1).Width(14)\n    oddRowStyle  = cellStyle.Foreground(gray)\n    evenRowStyle = cellStyle.Foreground(lightGray)\n)\n\nt := table.New().\n    Border(lipgloss.NormalBorder()).\n    BorderStyle(lipgloss.NewStyle().Foreground(purple)).\n    StyleFunc(func(row, col int) lipgloss.Style {\n        switch {\n        case row == table.HeaderRow:\n            return headerStyle\n        case row%2 == 0:\n            return evenRowStyle\n        default:\n            return oddRowStyle\n        }\n    }).\n    Headers(\"LANGUAGE\", \"FORMAL\", \"INFORMAL\").\n    Rows(rows...)\n\n\u002F\u002F You can also add tables row-by-row\nt.Row(\"English\", \"You look absolutely fabulous.\", \"How's it going?\")\n```\n\nPrint the table.\n\n```go\nlipgloss.Println(t)\n```\n\n![Table Example](https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fassets\u002F42545625\u002F6e4b70c4-f494-45da-a467-bdd27df30d5d)\n\n### Table Borders\n\nThere are helpers to generate tables in markdown or ASCII style:\n\n#### Markdown Table\n\n```go\ntable.New().Border(lipgloss.MarkdownBorder()).BorderTop(false).BorderBottom(false)\n```\n\n```\n| LANGUAGE |    FORMAL    | INFORMAL  |\n|----------|--------------|-----------|\n| Chinese  | Nǐn hǎo      | Nǐ hǎo    |\n| French   | Bonjour      | Salut     |\n| Russian  | Zdravstvuyte | Privet    |\n| Spanish  | Hola         | ¿Qué tal? |\n```\n\n#### ASCII Table\n\n```go\ntable.New().Border(lipgloss.ASCIIBorder())\n```\n\n```\n+----------+--------------+-----------+\n| LANGUAGE |    FORMAL    | INFORMAL  |\n+----------+--------------+-----------+\n| Chinese  | Nǐn hǎo      | Nǐ hǎo    |\n| French   | Bonjour      | Salut     |\n| Russian  | Zdravstvuyte | Privet    |\n| Spanish  | Hola         | ¿Qué tal? |\n+----------+--------------+-----------+\n```\n\nFor more on tables see [the docs][docs] and [examples](https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Ftree\u002Fmaster\u002Fexamples\u002Ftable).\n\n## Rendering Lists\n\nLip Gloss ships with a list rendering sub-package.\n\n```go\nimport \"charm.land\u002Flipgloss\u002Fv2\u002Flist\"\n```\n\nDefine a new list.\n\n```go\nl := list.New(\"A\", \"B\", \"C\")\n```\n\nPrint the list.\n\n```go\nlipgloss.Println(l)\n\n\u002F\u002F • A\n\u002F\u002F • B\n\u002F\u002F • C\n```\n\nLists have the ability to nest.\n\n```go\nl := list.New(\n    \"A\", list.New(\"Artichoke\"),\n    \"B\", list.New(\"Baking Flour\", \"Bananas\", \"Barley\", \"Bean Sprouts\"),\n    \"C\", list.New(\"Cashew Apple\", \"Cashews\", \"Coconut Milk\", \"Curry Paste\", \"Currywurst\"),\n    \"D\", list.New(\"Dill\", \"Dragonfruit\", \"Dried Shrimp\"),\n    \"E\", list.New(\"Eggs\"),\n    \"F\", list.New(\"Fish Cake\", \"Furikake\"),\n    \"J\", list.New(\"Jicama\"),\n    \"K\", list.New(\"Kohlrabi\"),\n    \"L\", list.New(\"Leeks\", \"Lentils\", \"Licorice Root\"),\n)\n```\n\nPrint the list.\n\n```go\nlipgloss.Println(l)\n```\n\n\u003Cp align=\"center\">\n\u003Cimg width=\"600\" alt=\"image\" src=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fassets\u002F42545625\u002F0dc9f440-0748-4151-a3b0-7dcf29dfcdb0\">\n\u003C\u002Fp>\n\nLists can be customized via their enumeration function as well as using\n`lipgloss.Style`s.\n\n```go\nenumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"99\")).MarginRight(1)\nitemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"212\")).MarginRight(1)\n\nl := list.New(\n    \"Glossier\",\n    \"Claire's Boutique\",\n    \"Nyx\",\n    \"Mac\",\n    \"Milk\",\n    ).\n    Enumerator(list.Roman).\n    EnumeratorStyle(enumeratorStyle).\n    ItemStyle(itemStyle)\n```\n\nPrint the list.\n\n\u003Cp align=\"center\">\n\u003Cimg width=\"600\" alt=\"List example\" src=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fassets\u002F42545625\u002F360494f1-57fb-4e13-bc19-0006efe01561\">\n\u003C\u002Fp>\n\nIn addition to the predefined enumerators (`Arabic`, `Alphabet`, `Roman`, `Bullet`, `Tree`),\nyou may also define your own custom enumerator:\n\n```go\nl := list.New(\"Duck\", \"Duck\", \"Duck\", \"Duck\", \"Goose\", \"Duck\", \"Duck\")\n\nfunc DuckDuckGooseEnumerator(l list.Items, i int) string {\n    if l.At(i).Value() == \"Goose\" {\n        return \"Honk →\"\n    }\n    return \"\"\n}\n\nl = l.Enumerator(DuckDuckGooseEnumerator)\n```\n\nPrint the list:\n\n\u003Cp align=\"center\">\n\u003Cimg width=\"600\" alt=\"image\" src=\"https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fassets\u002F42545625\u002F157aaf30-140d-4948-9bb4-dfba46e5b87e\">\n\u003C\u002Fp>\n\nIf you need, you can also build lists incrementally:\n\n```go\nl := list.New()\n\nfor i := 0; i \u003C repeat; i++ {\n    l.Item(\"Lip Gloss\")\n}\n```\n\n## Rendering Trees\n\nLip Gloss ships with a tree rendering sub-package.\n\n```go\nimport \"charm.land\u002Flipgloss\u002Fv2\u002Ftree\"\n```\n\nDefine a new tree.\n\n```go\nt := tree.Root(\".\").\n    Child(\"A\", \"B\", \"C\")\n```\n\nPrint the tree.\n\n```go\nlipgloss.Println(t)\n\n\u002F\u002F .\n\u002F\u002F ├── A\n\u002F\u002F ├── B\n\u002F\u002F └── C\n```\n\nTrees have the ability to nest.\n\n```go\nt := tree.Root(\".\").\n    Child(\"macOS\").\n    Child(\n        tree.New().\n            Root(\"Linux\").\n            Child(\"NixOS\").\n            Child(\"Arch Linux (btw)\").\n            Child(\"Void Linux\"),\n        ).\n    Child(\n        tree.New().\n            Root(\"BSD\").\n            Child(\"FreeBSD\").\n            Child(\"OpenBSD\"),\n    )\n```\n\nPrint the tree.\n\n```go\nlipgloss.Println(t)\n```\n\n\u003Cp align=\"center\">\n\u003Cimg width=\"663\" alt=\"Tree Example (simple)\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F5ef14eb8-a5d4-4f94-8834-e15d1e714f89\">\n\u003C\u002Fp>\n\nTrees can be customized via their enumeration function as well as using\n`lipgloss.Style`s.\n\n```go\nenumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"63\")).MarginRight(1)\nrootStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"35\"))\nitemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color(\"212\"))\n\nt := tree.\n    Root(\"⁜ Makeup\").\n    Child(\n        \"Glossier\",\n        \"Fenty Beauty\",\n        tree.New().Child(\n            \"Gloss Bomb Universal Lip Luminizer\",\n            \"Hot Cheeks Velour Blushlighter\",\n        ),\n        \"Nyx\",\n        \"Mac\",\n        \"Milk\",\n    ).\n    Enumerator(tree.RoundedEnumerator).\n    EnumeratorStyle(enumeratorStyle).\n    RootStyle(rootStyle).\n    ItemStyle(itemStyle)\n```\n\nPrint the tree.\n\n\u003Cp align=\"center\">\n\u003Cimg width=\"663\" alt=\"Tree Example (makeup)\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F06d12d87-744a-4c89-bd98-45de9094a97e\">\n\u003C\u002Fp>\n\nThe predefined enumerators for trees are `DefaultEnumerator` and `RoundedEnumerator`.\n\nIf you need, you can also build trees incrementally:\n\n```go\nt := tree.New()\n\nfor i := 0; i \u003C repeat; i++ {\n    t.Child(\"Lip Gloss\")\n}\n```\n\n## Advanced Color Usage\n\nOne of the most powerful features of Lip Gloss is the ability to render\ndifferent colors at runtime depending on the user's terminal and environment,\nallowing you to present the best possible user experience.\n\nThis section shows you how to do exactly that.\n\n\u003Cdetails>\n\u003Csummary>Migrating from v1?\u003C\u002Fsummary>\n\nThe `compat` package provides `AdaptiveColor`, `CompleteColor`, and\n`CompleteAdaptiveColor` for a quicker migration from v1. These work by\nlooking at `stdin` and `stdout` on a global basis:\n\n```go\nimport \"charm.land\u002Flipgloss\u002Fv2\u002Fcompat\"\n\ncolor := compat.AdaptiveColor{\n    Light: lipgloss.Color(\"#f1f1f1\"),\n    Dark:  lipgloss.Color(\"#cccccc\"),\n}\n```\n\nNote that we don't recommend this for new code as it removes the purity from\nLip Gloss, computationally speaking, as it removes transparency around when\nI\u002FO happens, which could cause Lip Gloss to compete for resources (like stdin)\nwith other tools.\n\n\u003C\u002Fdetails>\n\n### Adaptive Colors\n\nYou can render different colors at runtime depending on whether the terminal\nhas a light or dark background:\n\n```go\nhasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stdout)\nlightDark := lipgloss.LightDark(hasDarkBG)\n\nmyColor := lightDark(lipgloss.Color(\"#D7FFAE\"), lipgloss.Color(\"#D75FEE\"))\n```\n\n#### With Bubble Tea\n\nIn Bubble Tea, request the background color, listen for a\n`BackgroundColorMsg`, and respond accordingly:\n\n```go\nfunc (m model) Init() tea.Cmd {\n    \u002F\u002F First, send a Cmd to request the terminal background color.\n    return tea.RequestBackgroundColor\n}\n\nfunc (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {\n    switch msg := msg.(type) {\n    case tea.BackgroundColorMsg:\n        \u002F\u002F Great, we have the background color. Now we can set up our styles\n        \u002F\u002F against the color.\n        m.styles = newStyles(msg.IsDark())\n        return m, nil\n    }\n}\n\nfunc newStyles(bgIsDark bool) styles {\n    \u002F\u002F A little ternary function that will return the appropriate color\n    \u002F\u002F based on the background color.\n    lightDark := lipgloss.LightDark(bgIsDark)\n\n    return styles{\n        myHotStyle: lipgloss.NewStyle().Foreground(lightDark(\n            lipgloss.Color(\"#f1f1f1\"),\n            lipgloss.Color(\"#333333\"),\n        )),\n    }\n}\n```\n\n#### Standalone\n\nIf you’re not using Bubble Tea you can perform the query manually:\n\n```go\n\u002F\u002F What's the background color?\nhasDarkBG := lipgloss.HasDarkBackground(os.Stdin, os.Stderr)\n\n\u002F\u002F A helper function that will return the appropriate color based on the\n\u002F\u002F background.\nlightDark := lipgloss.LightDark(hasDarkBG)\n\n\u002F\u002F A couple colors with light and dark variants.\nthisColor := lightDark(lipgloss.Color(\"#C5ADF9\"), lipgloss.Color(\"#864EFF\"))\nthatColor := lightDark(lipgloss.Color(\"#37CD96\"), lipgloss.Color(\"#22C78A\"))\n\na := lipgloss.NewStyle().Foreground(thisColor).Render(\"this\")\nb := lipgloss.NewStyle().Foreground(thatColor).Render(\"that\")\n\n\u002F\u002F Render the appropriate colors at runtime:\nlipgloss.Fprintf(os.Stderr, \"my fave colors are %s and %s\", a, b)\n```\n\n### Complete Colors\n\nIn some cases where you may want to specify exact values for each color profile\n(ANSI 16, ANSI 156, and TrueColor). For these cases, use the `Complete` helper:\n\n```go\n\u002F\u002F You'll need the colorprofile package.\nimport \"github.com\u002Fcharmbracelet\u002Fcolorprofile\"\n\n\u002F\u002F Get the color profile.\nprofile := colorprofile.Detect(os.Stdout, os.Environ())\n\n\u002F\u002F Create a function for rendering the appropriate color based on the profile.\nvar completeColor := lipgloss.Complete(profile)\n\n\u002F\u002F Now we'll choose the appropriate color at runtime.\nmyColor := completeColor(ansiColor, ansi256Color, trueColor)\n```\n\n### Color Downsampling\n\nOne of the best things about Lip Gloss is that it can automatically downsample\ncolors to the best available profile, stripping colors (and ANSI) entirely when\noutput is not a TTY.\n\nIf you’re using Lip Gloss with Bubble Tea there’s nothing to do here:\ndownsampling is built into Bubble Tea v2. If you’re not using Bubble Tea, use\nthe Lip Gloss writer functions, which are a drop-in replacement for the `fmt`\npackage:\n\n```go\ns := lipgloss.NewStyle()\n    .Foreground(lipgloss.Color(\"#EB4268\"))\n    .Render(\"Hello!\")\n\n\u002F\u002F Downsample if needed and print to stdout.\nlipgloss.Println(s)\n\n\u002F\u002F Render to a variable.\ndownsampled := lipgloss.Sprint(s)\n\n\u002F\u002F Print to stderr.\nlipgloss.Fprint(os.Stderr, s)\n```\n\nThe full set: `Print`, `Println`, `Printf`, `Fprint`, `Fprintln`, `Fprintf`,\n`Sprint`, `Sprintln`, `Sprintf`.\n\nNeed more control? Check out\n[Colorprofile](https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Fcolorprofile), which Lip Gloss\nuses under the hood.\n\n## What about [Bubble Tea][tea]?\n\nLip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea\ncompanion. It was designed to make assembling terminal user interface views as\nsimple and fun as possible so that you can focus on building your application\ninstead of concerning yourself with low-level layout details.\n\nIn simple terms, you can use Lip Gloss to help build your Bubble Tea views.\n\n[tea]: https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Fbubbletea\n\n## Rendering Markdown\n\nFor a more document-centric rendering solution with support for things like\nlists, tables, and syntax-highlighted code have a look at [Glamour][glamour],\nthe stylesheet-based Markdown renderer.\n\n[glamour]: https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Fglamour\n\n## Contributing\n\nSee [contributing][contribute].\n\n[contribute]: https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fcontribute\n\n## Feedback\n\nWe’d love to hear your thoughts on this project. Feel free to drop us a note!\n\n- [Discord](https:\u002F\u002Fcharm.land\u002Fchat)\n- [Matrix](https:\u002F\u002Fcharm.land\u002Fmatrix)\n\n## License\n\n[MIT](https:\u002F\u002Fgithub.com\u002Fcharmbracelet\u002Flipgloss\u002Fraw\u002Fmaster\u002FLICENSE)\n\n---\n\nPart of [Charm](https:\u002F\u002Fcharm.land).\n\n\u003Ca href=\"https:\u002F\u002Fcharm.land\u002F\">\u003Cimg alt=\"The Charm logo\" src=\"https:\u002F\u002Fstuff.charm.sh\u002Fcharm-banner-next.jpg\" width=\"400\">\u003C\u002Fa>\n\nCharm热爱开源 • Charm loves open source\n\n[docs]: https:\u002F\u002Fpkg.go.dev\u002Fcharm.land\u002Flipgloss\u002Fv2?tab=doc\n","Lip Gloss 是一个用于创建美观终端布局的样式定义库。它采用声明式方法进行终端渲染，支持多种颜色配置（包括ANSI 16色、256色以及真彩色），并能自动适应不同终端的颜色能力，确保输出效果的一致性与美观度。项目以Go语言编写，为熟悉CSS的开发者提供了友好的API设计。适用于需要在命令行界面或基于文本的用户界面中实现丰富视觉效果的应用场景，如构建复杂的CLI工具或TUI应用。",2,"2026-06-11 03:02:01","top_language"]