Give the parts a look
Style @markless/ui parts with a class and their ui-* attributes, and beat the few built-in defaults with one plain CSS rule.
Your select works, but it looks like plain HTML. Here is how to give it a look.
@markless/ui ships no stylesheet. Put a class on a part. Then style that class together with the part’s ui-* attributes.
import { select } from '@markless/ui';
export default function StyledPicker() @{
<section>
<style>
.picker[ui-open] { outline: 2px solid purple; }
.option[ui-selected] { font-weight: 700; }
.option[ui-disabled] { opacity: 0.5; }
.mark[ui-hidden] { visibility: hidden; }
</style>
<select.root class="picker">
<select.label>Theme</select.label>
<select.trigger>Choose</select.trigger>
<select.content>
<select.item class="option" value="light">
<select.itemlabel>Light</select.itemlabel>
<select.itemindicator class="mark">✓</select.itemindicator>
</select.item>
<select.item class="option" value="dark" disabled>
<select.itemlabel>Dark</select.itemlabel>
<select.itemindicator class="mark">✓</select.itemindicator>
</select.item>
</select.content>
</select.root>
</section>
}
An on/off attribute such as ui-open is there or it is not. A few attributes carry a value, such as ui-value.
Defaults you can beat
A few families need some CSS to work at all, such as where a tooltip sits. Each one keeps that CSS inside a CSS layer named markless. A plain rule of yours beats any layer, with no !important.
Point at Save. Then click Add your rule and point at it again.
Which rule places the tip?
Point at Save, or press Tab to reach it. Then press Add your rule and try again.
@layer markless { [overlay] { position-area: block-start; } (wins)}- tooltip.rootui-closed
- tooltip.triggerui-closed
- tooltip.contentclass="tip"ui-closedhidden
Simplified. The built-in rule has three more lines that tie the tip to Save. This window places the tip with plain positions so it works in every browser. The two values come from the tooltip's own browser test.
Notice that you moved the tip with CSS, not a prop. A tooltip sits above its trigger until your rule says otherwise:
import { tooltip } from '@markless/ui';
export default function SaveTip() @{
<section>
<style>
.tip { position-area: inline-end; }
</style>
<tooltip.root>
<tooltip.trigger>Save</tooltip.trigger>
<tooltip.content class="tip">Save this draft</tooltip.content>
</tooltip.root>
</section>
}
Parts that nest
A tree or a submenu uses the same parts again, one level down. An item holds an itemcontent, and that holds more items.
Click the arrow next to src.
How does an item hold more items?
Press the arrow next to src. Or Tab into the tree and use the arrow keys.
- tree.root
- tree.itemsrcui-closed
- tree.itemtriggerui-closed
- tree.itemindicatorclass="arrow"ui-closed
- tree.itemcontentui-closedhidden
- tree.itemindex.tsui-leafsame part, one level down
- tree.itemapp.tsrxui-leafsame part, one level down
- tree.itemREADME.mdui-leaf
.arrow[ui-open] { rotate: 90deg; } (waits for ui-open)Simplified. The parts list leaves out the label parts and attributes that do not change when src opens. The parts match the tree's own example in its source.
Notice that index.ts and app.tsrx use the same tree.item part as src, one level down.
import { tree } from '@markless/ui';
export default function Files() @{
<tree.root aria-label="Project files">
<tree.item level={1}>
<tree.itemtrigger>
<tree.itemindicator>▸</tree.itemindicator>
</tree.itemtrigger>
<tree.itemlabel>src</tree.itemlabel>
<tree.itemcontent>
<tree.item leaf level={2}>
<tree.itemlabel>index.ts</tree.itemlabel>
</tree.item>
</tree.itemcontent>
</tree.item>
</tree.root>
}
Next: Which families can you style this way? Component list →
