Skip to content

tuilwindcss

This project is inspired by tailwind.css to offers a similar set of classes that can be used directly to construct TUI apps with Textual. It's an experimental project to see if it makes it easier to construct apps.

A collection of available classes are shown in the gallery below.

Tailwind Compatible Classes

Background Color

This project attemps to mimic the colors that tailwind.css provides. This includes background colors, but text and border colors too.

Overview of all colors.

Slate
50
#F8FAFC
100
#F1F5F9
200
#E2E8F0
300
#CBD5E1
400
#94A3B8
500
#64748B
600
#475569
700
#334155
800
#1E293B
900
#0F172A
Gray
50
#F9FAFB
100
#F3F4F6
200
#E5E7EB
300
#D1D5DB
400
#9CA3AF
500
#6B7280
600
#4B5563
700
#374151
800
#1F2937
900
#111827
Zinc
50
#FAFAFA
100
#F4F4F5
200
#E4E4E7
300
#D4D4D8
400
#A1A1AA
500
#71717A
600
#52525B
700
#3F3F46
800
#27272A
900
#18181B
Neutral
50
#FAFAFA
100
#F5F5F5
200
#E5E5E5
300
#D4D4D4
400
#A3A3A3
500
#737373
600
#525252
700
#404040
800
#262626
900
#171717
Stone
50
#FAFAF9
100
#F5F5F4
200
#E7E5E4
300
#D6D3D1
400
#A8A29E
500
#78716C
600
#57534E
700
#44403C
800
#292524
900
#1C1917
Red
50
#FEF2F2
100
#FEE2E2
200
#FECACA
300
#FCA5A5
400
#F87171
500
#EF4444
600
#DC2626
700
#B91C1C
800
#991B1B
900
#7F1D1D
Orange
50
#FFF7ED
100
#FFEDD5
200
#FED7AA
300
#FDBA74
400
#FB923C
500
#F97316
600
#EA580C
700
#C2410C
800
#9A3412
900
#7C2D12
Amber
50
#FFFBEB
100
#FEF3C7
200
#FDE68A
300
#FCD34D
400
#FBBF24
500
#F59E0B
600
#D97706
700
#B45309
800
#92400E
900
#78350F
Yellow
50
#FEFCE8
100
#FEF9C3
200
#FEF08A
300
#FDE047
400
#FACC15
500
#EAB308
600
#CA8A04
700
#A16207
800
#854D0E
900
#713F12
Lime
50
#F7FEE7
100
#ECFCCB
200
#D9F99D
300
#BEF264
400
#A3E635
500
#84CC16
600
#65A30D
700
#4D7C0F
800
#3F6212
900
#365314
Green
50
#F0FDF4
100
#DCFCE7
200
#BBF7D0
300
#86EFAC
400
#4ADE80
500
#22C55E
600
#16A34A
700
#15803D
800
#166534
900
#14532D
Emerald
50
#ECFDF5
100
#D1FAE5
200
#A7F3D0
300
#6EE7B7
400
#34D399
500
#10B981
600
#059669
700
#047857
800
#065F46
900
#064E3B
Teal
50
#F0FDFA
100
#CCFBF1
200
#99F6E4
300
#5EEAD4
400
#2DD4BF
500
#14B8A6
600
#0D9488
700
#0F766E
800
#115E59
900
#134E4A
Cyan
50
#ECFEFF
100
#CFFAFE
200
#A5F3FC
300
#67E8F9
400
#22D3EE
500
#06B6D4
600
#0891B2
700
#0E7490
800
#155E75
900
#164E63
Sky
50
#F0F9FF
100
#E0F2FE
200
#BAE6FD
300
#7DD3FC
400
#38BDF8
500
#0EA5E9
600
#0284C7
700
#0369A1
800
#075985
900
#0C4A6E
Blue
50
#EFF6FF
100
#DBEAFE
200
#BFDBFE
300
#93C5FD
400
#60A5FA
500
#3B82F6
600
#2563EB
700
#1D4ED8
800
#1E40AF
900
#1E3A8A
Indigo
50
#EEF2FF
100
#E0E7FF
200
#C7D2FE
300
#A5B4FC
400
#818CF8
500
#6366F1
600
#4F46E5
700
#4338CA
800
#3730A3
900
#312E81
Violet
50
#F5F3FF
100
#EDE9FE
200
#DDD6FE
300
#C4B5FD
400
#A78BFA
500
#8B5CF6
600
#7C3AED
700
#6D28D9
800
#5B21B6
900
#4C1D95
Purple
50
#FAF5FF
100
#F3E8FF
200
#E9D5FF
300
#D8B4FE
400
#C084FC
500
#A855F7
600
#9333EA
700
#7E22CE
800
#6B21A8
900
#581C87
Fuchsia
50
#FDF4FF
100
#FAE8FF
200
#F5D0FE
300
#F0ABFC
400
#E879F9
500
#D946EF
600
#C026D3
700
#A21CAF
800
#86198F
900
#701A75
Pink
50
#FDF2F8
100
#FCE7F3
200
#FBCFE8
300
#F9A8D4
400
#F472B6
500
#EC4899
600
#DB2777
700
#BE185D
800
#9D174D
900
#831843
Rose
50
#FFF1F2
100
#FFE4E6
200
#FECDD3
300
#FDA4AF
400
#FB7185
500
#F43F5E
600
#E11D48
700
#BE123C
800
#9F1239
900
#881337
Background Color Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class BackgroundColorDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        for i in [100, 200, 300, 400, 500, 600, 700, 800, 900]:
            yield Static(f"bg-blue-{i}", classes=f"bg-blue-{i}")
        for i in reversed([100, 200, 300, 400, 500, 600, 700, 800, 900]):
            yield Static(f"bg-blue-{i}", classes=f"bg-blue-{i}")


if __name__ == "__main__":
    app = BackgroundColorDemo()
    app.run()

BackgroundColorDemo bg-blue-100 bg-blue-200 bg-blue-300 bg-blue-400 bg-blue-500 bg-blue-600 bg-blue-700 bg-blue-800 bg-blue-900 bg-blue-900 bg-blue-800 bg-blue-700 bg-blue-600 bg-blue-500 bg-blue-400 bg-blue-300 bg-blue-200 bg-blue-100

Padding

Simple Padding

Padding Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class PaddingDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("p-1", classes="p-1 bg-blue-400")
        yield Static("p-2", classes="p-2 bg-blue-500")
        yield Static("p-3", classes="p-3 bg-blue-600")
        yield Static("p-4", classes="p-4 bg-blue-700")

if __name__ == "__main__":
    app = PaddingDemo()
    app.run()

PaddingDemo p-1 p-2 p-3 p-4

Padding Direction

You can also be specific in the direction of the padding. So you can specify:

  • pt-1 to add 1 padding to the top
  • pb-1 to add 1 padding to the bottom
  • pl-1 to add 1 padding to the left
  • pr-1 to add 1 padding to the right
  • px-1 to add 1 padding to horizontally
  • py-1 to add 1 padding to vertically
Padding Direction Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class PaddingDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("pt-2", classes="pt-2 bg-gray-200 border-round-gray-600 text-gray-700")
        yield Static("pb-2", classes="pb-2 bg-gray-300 border-round-gray-600 text-gray-700")
        yield Static("pl-2", classes="pl-2 bg-gray-200 border-round-gray-600 text-gray-700")
        yield Static("pr-2", classes="pr-2 bg-gray-300 border-round-gray-600 text-gray-700")
        yield Static("px-2", classes="px-2 bg-gray-200 border-round-gray-600 text-gray-700")
        yield Static("py-2", classes="py-2 bg-gray-300 border-round-gray-600 text-gray-700")

if __name__ == "__main__":
    app = PaddingDemo()
    app.run()

PaddingDemo ╭────────────────────────────────────────────────────────────────────────────╮ pt-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ pb-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ pl-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ pr-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ px-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ py-2▆▆

Margin

Simple Margin

Padding Demo
from textual.app import App, ComposeResult
from textual.widgets import Static
from textual.containers import Vertical

class MarginDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Vertical(
            Static("m-1 p-1", classes="m-1 p-1 bg-gray-200 border-round-gray-600 text-gray-600"),
            Static("m-2 p-1", classes="m-2 p-1 bg-gray-200 border-round-gray-600 text-gray-600"),
            Static("m-3 p-2", classes="m-3 p-2 bg-gray-200 border-round-gray-600 text-gray-600"),
            classes="bg-gray-300"
        )

if __name__ == "__main__":
    app = MarginDemo()
    app.run()

MarginDemo ╭──────────────────────────────────────────────────────────────────────────╮ m-1 p-1 ╰──────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ m-2 p-1 ╰────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────╮ m-3 p-2 ╰──────────────────────────────────────────────────────────────────────╯▆▆

Margin Direction

You can also be specific in the direction of the padding. So you can specify:

  • mt-1 to add 1 padding to the top
  • mb-1 to add 1 padding to the bottom
  • ml-1 to add 1 padding to the left
  • mr-1 to add 1 padding to the right
  • mx-1 to add 1 padding to horizontally
  • my-1 to add 1 padding to vertically
Padding Direction Demo
from textual.app import App, ComposeResult
from textual.widgets import Static
from textual.containers import Vertical


class PaddingDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Vertical(
            Static("mt-2", classes="mt-2 bg-gray-200 border-round-gray-600 text-gray-800"),
            Static("mb-2", classes="mb-2 bg-gray-300 border-round-gray-600 text-gray-800"),
            Static("ml-2", classes="ml-2 bg-gray-200 border-round-gray-600 text-gray-800"),
            Static("mr-2", classes="mr-2 bg-gray-300 border-round-gray-600 text-gray-800"),
            Static("mx-2", classes="mx-2 bg-gray-200 border-round-gray-600 text-gray-800"),
            Static("my-2", classes="my-2 bg-gray-300 border-round-gray-600 text-gray-800"),
            classes="bg-gray-400"
        )

if __name__ == "__main__":
    app = PaddingDemo()
    app.run()

PaddingDemo ╭────────────────────────────────────────────────────────────────────────────╮ mt-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ mb-2 ╰────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ ml-2 ╰──────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────╮ mr-2 ╰──────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ mx-2 ╰────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────╮ my-2▆▆ ╰────────────────────────────────────────────────────────────────────────────╯

Text

Text Color

This project attemps to mimic the tet colors that tailwind.css provides.

Overview of all colors.

Slate
50
#F8FAFC
100
#F1F5F9
200
#E2E8F0
300
#CBD5E1
400
#94A3B8
500
#64748B
600
#475569
700
#334155
800
#1E293B
900
#0F172A
Gray
50
#F9FAFB
100
#F3F4F6
200
#E5E7EB
300
#D1D5DB
400
#9CA3AF
500
#6B7280
600
#4B5563
700
#374151
800
#1F2937
900
#111827
Zinc
50
#FAFAFA
100
#F4F4F5
200
#E4E4E7
300
#D4D4D8
400
#A1A1AA
500
#71717A
600
#52525B
700
#3F3F46
800
#27272A
900
#18181B
Neutral
50
#FAFAFA
100
#F5F5F5
200
#E5E5E5
300
#D4D4D4
400
#A3A3A3
500
#737373
600
#525252
700
#404040
800
#262626
900
#171717
Stone
50
#FAFAF9
100
#F5F5F4
200
#E7E5E4
300
#D6D3D1
400
#A8A29E
500
#78716C
600
#57534E
700
#44403C
800
#292524
900
#1C1917
Red
50
#FEF2F2
100
#FEE2E2
200
#FECACA
300
#FCA5A5
400
#F87171
500
#EF4444
600
#DC2626
700
#B91C1C
800
#991B1B
900
#7F1D1D
Orange
50
#FFF7ED
100
#FFEDD5
200
#FED7AA
300
#FDBA74
400
#FB923C
500
#F97316
600
#EA580C
700
#C2410C
800
#9A3412
900
#7C2D12
Amber
50
#FFFBEB
100
#FEF3C7
200
#FDE68A
300
#FCD34D
400
#FBBF24
500
#F59E0B
600
#D97706
700
#B45309
800
#92400E
900
#78350F
Yellow
50
#FEFCE8
100
#FEF9C3
200
#FEF08A
300
#FDE047
400
#FACC15
500
#EAB308
600
#CA8A04
700
#A16207
800
#854D0E
900
#713F12
Lime
50
#F7FEE7
100
#ECFCCB
200
#D9F99D
300
#BEF264
400
#A3E635
500
#84CC16
600
#65A30D
700
#4D7C0F
800
#3F6212
900
#365314
Green
50
#F0FDF4
100
#DCFCE7
200
#BBF7D0
300
#86EFAC
400
#4ADE80
500
#22C55E
600
#16A34A
700
#15803D
800
#166534
900
#14532D
Emerald
50
#ECFDF5
100
#D1FAE5
200
#A7F3D0
300
#6EE7B7
400
#34D399
500
#10B981
600
#059669
700
#047857
800
#065F46
900
#064E3B
Teal
50
#F0FDFA
100
#CCFBF1
200
#99F6E4
300
#5EEAD4
400
#2DD4BF
500
#14B8A6
600
#0D9488
700
#0F766E
800
#115E59
900
#134E4A
Cyan
50
#ECFEFF
100
#CFFAFE
200
#A5F3FC
300
#67E8F9
400
#22D3EE
500
#06B6D4
600
#0891B2
700
#0E7490
800
#155E75
900
#164E63
Sky
50
#F0F9FF
100
#E0F2FE
200
#BAE6FD
300
#7DD3FC
400
#38BDF8
500
#0EA5E9
600
#0284C7
700
#0369A1
800
#075985
900
#0C4A6E
Blue
50
#EFF6FF
100
#DBEAFE
200
#BFDBFE
300
#93C5FD
400
#60A5FA
500
#3B82F6
600
#2563EB
700
#1D4ED8
800
#1E40AF
900
#1E3A8A
Indigo
50
#EEF2FF
100
#E0E7FF
200
#C7D2FE
300
#A5B4FC
400
#818CF8
500
#6366F1
600
#4F46E5
700
#4338CA
800
#3730A3
900
#312E81
Violet
50
#F5F3FF
100
#EDE9FE
200
#DDD6FE
300
#C4B5FD
400
#A78BFA
500
#8B5CF6
600
#7C3AED
700
#6D28D9
800
#5B21B6
900
#4C1D95
Purple
50
#FAF5FF
100
#F3E8FF
200
#E9D5FF
300
#D8B4FE
400
#C084FC
500
#A855F7
600
#9333EA
700
#7E22CE
800
#6B21A8
900
#581C87
Fuchsia
50
#FDF4FF
100
#FAE8FF
200
#F5D0FE
300
#F0ABFC
400
#E879F9
500
#D946EF
600
#C026D3
700
#A21CAF
800
#86198F
900
#701A75
Pink
50
#FDF2F8
100
#FCE7F3
200
#FBCFE8
300
#F9A8D4
400
#F472B6
500
#EC4899
600
#DB2777
700
#BE185D
800
#9D174D
900
#831843
Rose
50
#FFF1F2
100
#FFE4E6
200
#FECDD3
300
#FDA4AF
400
#FB7185
500
#F43F5E
600
#E11D48
700
#BE123C
800
#9F1239
900
#881337
Text Color Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class TextColorDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("# This is the blue bit!", classes="text-center bold")
        for i in [100, 200, 300, 400, 500, 600, 700, 800, 900]:
            yield Static("This is some example text.", classes=f"text-blue-{i}")
        yield Static("# This is a new section!", classes="text-center bold")
        for i in [100, 200, 300, 400, 500, 600, 700, 800, 900]:
            yield Static("This is some example text.", classes=f"text-gray-{i}")

if __name__ == "__main__":
    app = TextColorDemo()
    app.run()

TextColorDemo                             # This is the blue bit!                              This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text.                             # This is a new section!                             This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text. This is some example text.

Text Style

You can also apply some style to text in Textual. Nothing with text sizes, but the full types are shown below.

Text Style Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class TextStyleDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("This is some text.", classes="")
        yield Static("This is some text.", classes="bold")
        yield Static("This is some text.", classes="italic")
        yield Static("This is some text.", classes="underline")
        yield Static("This is some text.", classes="strike")
        yield Static("This is some text.", classes="reverse")


if __name__ == "__main__":
    app = TextStyleDemo()
    app.run()

TextStyleDemo This is some text. This is some text. This is some text. This is some text. This is some text. This is some text.

Text Alignment

Text Alignment Demo
from textual.app import App, ComposeResult
from textual.widgets import Static

text = """This text is certainly a fair bit long to proove a point. 
Oh my yes indeed, it really is a fair bit longer than many other examples!"""

class TextAlignmentDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static(text, classes="p-1 bg-gray-500 text-left")
        yield Static(text, classes="p-1 bg-gray-600 text-center")
        yield Static(text, classes="p-1 bg-gray-700 text-right")
        yield Static(text, classes="p-1 bg-gray-500 text-justify")
        yield Static(text, classes="p-1 bg-gray-600 text-start")
        yield Static(text, classes="p-1 bg-gray-700 text-end")

if __name__ == "__main__":
    app = TextAlignmentDemo()
    app.run()

TextAlignmentDemo This text is certainly a fair bit long to proove a point.                      Oh my yes indeed, it really is a fair bit longer than many other examples!               This text is certainly a fair bit long to proove a point.              Oh my yes indeed, it really is a fair bit longer than many other examples!                        This text is certainly a fair bit long to proove a point.     Oh my yes indeed, it really is a fair bit longer than many other examples! This text is certainly a fair bit long to proove a point.  Oh my yes indeed, it really is a fair bit longer than many other examples! This text is certainly a fair bit long to proove a point.                      Oh my yes indeed, it really is a fair bit longer than many other examples!                          This text is certainly a fair bit long to proove a point.     Oh my yes indeed, it really is a fair bit longer than many other examples!

Tailwind Inconsistent Classes

Border

Borders in CSS allow you to define the border-width seperately from the border-color. Textual doesn't do this, which is why the class names are much longer. That said, this project attemps to mimic the border colors that tailwind.css provides.

Overview of all colors.

Slate
50
#F8FAFC
100
#F1F5F9
200
#E2E8F0
300
#CBD5E1
400
#94A3B8
500
#64748B
600
#475569
700
#334155
800
#1E293B
900
#0F172A
Gray
50
#F9FAFB
100
#F3F4F6
200
#E5E7EB
300
#D1D5DB
400
#9CA3AF
500
#6B7280
600
#4B5563
700
#374151
800
#1F2937
900
#111827
Zinc
50
#FAFAFA
100
#F4F4F5
200
#E4E4E7
300
#D4D4D8
400
#A1A1AA
500
#71717A
600
#52525B
700
#3F3F46
800
#27272A
900
#18181B
Neutral
50
#FAFAFA
100
#F5F5F5
200
#E5E5E5
300
#D4D4D4
400
#A3A3A3
500
#737373
600
#525252
700
#404040
800
#262626
900
#171717
Stone
50
#FAFAF9
100
#F5F5F4
200
#E7E5E4
300
#D6D3D1
400
#A8A29E
500
#78716C
600
#57534E
700
#44403C
800
#292524
900
#1C1917
Red
50
#FEF2F2
100
#FEE2E2
200
#FECACA
300
#FCA5A5
400
#F87171
500
#EF4444
600
#DC2626
700
#B91C1C
800
#991B1B
900
#7F1D1D
Orange
50
#FFF7ED
100
#FFEDD5
200
#FED7AA
300
#FDBA74
400
#FB923C
500
#F97316
600
#EA580C
700
#C2410C
800
#9A3412
900
#7C2D12
Amber
50
#FFFBEB
100
#FEF3C7
200
#FDE68A
300
#FCD34D
400
#FBBF24
500
#F59E0B
600
#D97706
700
#B45309
800
#92400E
900
#78350F
Yellow
50
#FEFCE8
100
#FEF9C3
200
#FEF08A
300
#FDE047
400
#FACC15
500
#EAB308
600
#CA8A04
700
#A16207
800
#854D0E
900
#713F12
Lime
50
#F7FEE7
100
#ECFCCB
200
#D9F99D
300
#BEF264
400
#A3E635
500
#84CC16
600
#65A30D
700
#4D7C0F
800
#3F6212
900
#365314
Green
50
#F0FDF4
100
#DCFCE7
200
#BBF7D0
300
#86EFAC
400
#4ADE80
500
#22C55E
600
#16A34A
700
#15803D
800
#166534
900
#14532D
Emerald
50
#ECFDF5
100
#D1FAE5
200
#A7F3D0
300
#6EE7B7
400
#34D399
500
#10B981
600
#059669
700
#047857
800
#065F46
900
#064E3B
Teal
50
#F0FDFA
100
#CCFBF1
200
#99F6E4
300
#5EEAD4
400
#2DD4BF
500
#14B8A6
600
#0D9488
700
#0F766E
800
#115E59
900
#134E4A
Cyan
50
#ECFEFF
100
#CFFAFE
200
#A5F3FC
300
#67E8F9
400
#22D3EE
500
#06B6D4
600
#0891B2
700
#0E7490
800
#155E75
900
#164E63
Sky
50
#F0F9FF
100
#E0F2FE
200
#BAE6FD
300
#7DD3FC
400
#38BDF8
500
#0EA5E9
600
#0284C7
700
#0369A1
800
#075985
900
#0C4A6E
Blue
50
#EFF6FF
100
#DBEAFE
200
#BFDBFE
300
#93C5FD
400
#60A5FA
500
#3B82F6
600
#2563EB
700
#1D4ED8
800
#1E40AF
900
#1E3A8A
Indigo
50
#EEF2FF
100
#E0E7FF
200
#C7D2FE
300
#A5B4FC
400
#818CF8
500
#6366F1
600
#4F46E5
700
#4338CA
800
#3730A3
900
#312E81
Violet
50
#F5F3FF
100
#EDE9FE
200
#DDD6FE
300
#C4B5FD
400
#A78BFA
500
#8B5CF6
600
#7C3AED
700
#6D28D9
800
#5B21B6
900
#4C1D95
Purple
50
#FAF5FF
100
#F3E8FF
200
#E9D5FF
300
#D8B4FE
400
#C084FC
500
#A855F7
600
#9333EA
700
#7E22CE
800
#6B21A8
900
#581C87
Fuchsia
50
#FDF4FF
100
#FAE8FF
200
#F5D0FE
300
#F0ABFC
400
#E879F9
500
#D946EF
600
#C026D3
700
#A21CAF
800
#86198F
900
#701A75
Pink
50
#FDF2F8
100
#FCE7F3
200
#FBCFE8
300
#F9A8D4
400
#F472B6
500
#EC4899
600
#DB2777
700
#BE185D
800
#9D174D
900
#831843
Rose
50
#FFF1F2
100
#FFE4E6
200
#FECDD3
300
#FDA4AF
400
#FB7185
500
#F43F5E
600
#E11D48
700
#BE123C
800
#9F1239
900
#881337

Base Border

The syntax for a border is <border>-<border-type>-<color>. The supported border types are:

"ascii","blank","dashed","double","heavy","hidden","hkey","inner","none","outer","round","solid","tall","vkey","wide"
Border Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class BorderDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("first",  classes="p-2 text-center text-gray-800 bg-gray-100 border-solid-gray-900")
        yield Static("second", classes="p-2 text-center text-gray-800 bg-gray-200 border-round-gray-900")
        yield Static("third",  classes="p-2 text-center text-gray-800 bg-gray-400 border-double-gray-900")

if __name__ == "__main__":
    app = BorderDemo()
    app.run()

BorderDemo ┌──────────────────────────────────────────────────────────────────────────────┐                                   first                                    └──────────────────────────────────────────────────────────────────────────────┘ ╭──────────────────────────────────────────────────────────────────────────────╮                                   second                                   ╰──────────────────────────────────────────────────────────────────────────────╯ ╔══════════════════════════════════════════════════════════════════════════════╗                                   third                                    ╚══════════════════════════════════════════════════════════════════════════════╝

Border Direction

You can also be specific in the direction of the border. So you can specify:

  • border-t-1-<COLOR> to add a border to the top
  • border-b-1-<COLOR> to add a border to the bottom
  • border-l-1-<COLOR> to add a border to the left
  • border-r-1-<COLOR> to add a border to the right
  • border-x-1-<COLOR> to add a border to horizontally
  • border-y-1-<COLOR> to add a border to vertically
Border Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class BorderSidesDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("t", classes="p-1 text-center text-gray-800 bg-gray-200 border-t-heavy-gray-600")
        yield Static("l", classes="p-1 text-center text-gray-800 bg-gray-300 border-l-heavy-gray-600")
        yield Static("r", classes="p-1 text-center text-gray-800 bg-gray-200 border-r-heavy-gray-600")
        yield Static("b", classes="p-1 text-center text-gray-800 bg-gray-300 border-b-heavy-gray-600")
        yield Static("x", classes="p-1 text-center text-gray-800 bg-gray-200 border-x-heavy-gray-600")
        yield Static("y", classes="p-1 text-center text-gray-800 bg-gray-300 border-y-heavy-gray-600")

if __name__ == "__main__":
    app = BorderSidesDemo()
    app.run()

BorderSidesDemo ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                       t                                                                              l                                                                             r                                                                             b                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                      x                                       ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━                                       y                                        ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Textual Specific Classes

We try to mimic tailwindcss as much as possible. But there are a few places where textual has it's own definitions. For these instances we try to offer classes that follow the spirit of tailwind.

Dock

The "dock" is something that is specific to TUI apps. But we felt like we could apply a familiar similar syntax for it.

Dock Left/Right

Dock Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class DockDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("left",  classes="dock-left  h-full bg-red-600    w-15")
        yield Static("right", classes="dock-right h-full bg-yellow-600 w-20")

if __name__ == "__main__":
    app = DockDemo()
    app.run()

DockDemo leftright

Dock Top/Bottom

Dock Demo
from textual.app import App, ComposeResult
from textual.widgets import Static


class DockDemo(App):
    CSS_PATH = "tuilwind.css"

    def compose(self) -> ComposeResult:
        """Called to add widgets to the app."""
        yield Static("top",    classes="dock-top    h-2 bg-green-600 w-full text-center")
        yield Static("bottom", classes="dock-bottom h-4 bg-blue-600  w-full text-center")

if __name__ == "__main__":
    app = DockDemo()
    app.run()

DockDemo                                       top                                                                             bottom