Scroll Area
A box with a styled scrollbar.
<scrollarea.ScrollArea class="h-24 w-48 rounded-md border border-border" attrs={gx.Attrs{{Key: "aria-label", Value: "Lines", Kind: gx.AttrText}}}>
<div class="p-2 text-sm">
<p>Line one.</p>
<p>Line two.</p>
<p>Line three.</p>
<p>Line four.</p>
<p>Line five.</p>
<p>Line six.</p>
<p>Line seven.</p>
<p>Line eight.</p>
</div>
</scrollarea.ScrollArea>Installation
Run the command in the app module.
gx add scroll-areaThe command writes these files.
| File | Path in the app |
|---|---|
ScrollArea.gx |
ui/scroll-area/ScrollArea.gx |
ScrollArea.fixtures.go |
ui/scroll-area/ScrollArea.fixtures.go |
Copy each file to its path in the app. Change each import of a registry package to the path of that package in the app.
package scrollarea
props {
// Class adds classes to the root element.
Class string = ""
// Children is the content that scrolls.
Children gx.Node
// Attrs adds HTML attributes to the root element.
Attrs gx.Attrs = nil
}
<div class={gx.Cx("relative overflow-auto transition-[color,box-shadow] outline-none [scrollbar-color:var(--border)_transparent] [scrollbar-width:thin] focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 motion-reduce:transition-none", p.Class)} tabindex="0" {...p.Attrs}>{p.Children}</div>package scrollarea
import "github.com/alternayte/gx"
// Each line is one paragraph, so the text does not wrap at the scrollbar.
var ScrollAreaFixtures = gx.Fixtures[ScrollAreaProps]{
"Vertical": {Class: "h-24 w-48 rounded-md border border-border", Attrs: gx.Attrs{{Key: "aria-label", Value: "Lines", Kind: gx.AttrText}}, Children: gx.El("div", gx.Attrs{{Key: "class", Value: "p-2 text-sm", Kind: gx.AttrText}},
gx.El("p", nil, gx.Text("Line one.")),
gx.El("p", nil, gx.Text("Line two.")),
gx.El("p", nil, gx.Text("Line three.")),
gx.El("p", nil, gx.Text("Line four.")),
gx.El("p", nil, gx.Text("Line five.")),
gx.El("p", nil, gx.Text("Line six.")),
gx.El("p", nil, gx.Text("Line seven.")),
gx.El("p", nil, gx.Text("Line eight.")),
)},
"Horizontal": {Class: "w-48 rounded-md border border-border whitespace-nowrap", Attrs: gx.Attrs{{Key: "aria-label", Value: "One long line", Kind: gx.AttrText}}, Children: gx.El("div", gx.Attrs{{Key: "class", Value: "p-2 text-sm", Kind: gx.AttrText}},
gx.El("p", nil, gx.Text("One long line that does not wrap and scrolls sideways.")),
)},
}The theme must define these tokens: --border, --ring.
Usage
<scrollarea.ScrollArea class="h-64 rounded-md border">
<div class="p-4">Long content.</div>
</scrollarea.ScrollArea>The area is a native scroller with a thin scrollbar in the border colour. It scrolls on both axes. The browser draws the scrollbar.
Examples
Vertical
<scrollarea.ScrollArea class="h-24 w-48 rounded-md border border-border" attrs={gx.Attrs{{Key: "aria-label", Value: "Lines", Kind: gx.AttrText}}}>
<div class="p-2 text-sm">
<p>Line one.</p>
<p>Line two.</p>
<p>Line three.</p>
<p>Line four.</p>
<p>Line five.</p>
<p>Line six.</p>
<p>Line seven.</p>
<p>Line eight.</p>
</div>
</scrollarea.ScrollArea>Horizontal
<scrollarea.ScrollArea class="w-48 rounded-md border border-border whitespace-nowrap" attrs={gx.Attrs{{Key: "aria-label", Value: "One long line", Kind: gx.AttrText}}}>
<div class="p-2 text-sm"><p>One long line that does not wrap and scrolls sideways.</p></div>
</scrollarea.ScrollArea>API reference
A tag sets a prop by its name with a lower-case first letter: Class is class.
scrollarea.ScrollArea
| Prop | Type | Default | Description |
|---|---|---|---|
Class |
string |
"" |
Class adds classes to the root element. |
Children |
gx.Node |
Required | Children is the content that scrolls. |
Attrs |
gx.Attrs |
nil |
Attrs adds HTML attributes to the root element. |
Do and do not
Do
- Set a height on the area.
- Put the padding on the content, not on the area.
- Keep the scroll on one axis.
Don't
- Do not nest two scroll areas.
- Do not use a scroll area for the whole page.
Keyboard
| Key | Action |
|---|---|
| Tab | Moves focus to the area. |
| Arrow keys, Page keys | Scroll the area when it holds focus. |