Skip to content

Commit ea90b04

Browse files
authored
feat!: redesign tabs (#2745)
1 parent 41cba40 commit ea90b04

File tree

8 files changed

+113
-42
lines changed

8 files changed

+113
-42
lines changed

yazi-config/preset/theme-dark.toml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ marker_cut = { fg = "lightred", bg = "lightred" }
3838
marker_marked = { fg = "lightcyan", bg = "lightcyan" }
3939
marker_selected = { fg = "lightyellow", bg = "lightyellow" }
4040

41-
# Tab
42-
tab_active = { reversed = true }
43-
tab_inactive = {}
44-
tab_width = 1
45-
4641
# Count
4742
count_copied = { fg = "white", bg = "green" }
4843
count_cut = { fg = "white", bg = "red" }
@@ -58,6 +53,19 @@ syntect_theme = ""
5853
# : }}}
5954

6055

56+
# : Tabs {{{
57+
58+
[tabs]
59+
active = { bg = "blue", bold = true }
60+
inactive = { fg = "blue", bg = "gray" }
61+
62+
# Separator
63+
sep_inner = { open = "", close = "" }
64+
sep_outer = { open = "", close = "" }
65+
66+
# : }}}
67+
68+
6169
# : Mode {{{
6270

6371
[mode]

yazi-config/preset/theme-light.toml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,6 @@ marker_cut = { fg = "lightred", bg = "lightred" }
3838
marker_marked = { fg = "lightcyan", bg = "lightcyan" }
3939
marker_selected = { fg = "lightyellow", bg = "lightyellow" }
4040

41-
# Tab
42-
tab_active = { reversed = true }
43-
tab_inactive = {}
44-
tab_width = 1
45-
4641
# Count
4742
count_copied = { fg = "white", bg = "green" }
4843
count_cut = { fg = "white", bg = "red" }
@@ -58,6 +53,19 @@ syntect_theme = ""
5853
# : }}}
5954

6055

56+
# : Tabs {{{
57+
58+
[tabs]
59+
active = { bg = "blue", bold = true }
60+
inactive = { fg = "blue", bg = "gray" }
61+
62+
# Separator
63+
sep_inner = { open = "", close = "" }
64+
sep_outer = { open = "", close = "" }
65+
66+
# : }}}
67+
68+
6169
# : Mode {{{
6270

6371
[mode]

yazi-config/src/theme/theme.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ pub struct Theme {
1313
pub flavor: Flavor,
1414
#[serde(rename = "manager")]
1515
pub mgr: Mgr, // TODO: Remove `serde(rename)`
16+
pub tabs: Tabs,
1617
pub mode: Mode,
1718
pub status: Status,
1819
pub which: Which,
@@ -53,11 +54,6 @@ pub struct Mgr {
5354
marker_marked: Style,
5455
marker_selected: Style,
5556

56-
// Tab
57-
tab_active: Style,
58-
tab_inactive: Style,
59-
tab_width: u8,
60-
6157
// Count
6258
count_copied: Style,
6359
count_cut: Style,
@@ -71,6 +67,21 @@ pub struct Mgr {
7167
pub syntect_theme: PathBuf,
7268
}
7369

70+
#[derive(Deserialize, DeserializeOver2, Serialize)]
71+
pub struct Tabs {
72+
pub active: Style,
73+
pub inactive: Style,
74+
75+
pub sep_inner: TabsSep,
76+
pub sep_outer: TabsSep,
77+
}
78+
79+
#[derive(Deserialize, DeserializeOver2, Serialize)]
80+
pub struct TabsSep {
81+
pub open: String,
82+
pub close: String,
83+
}
84+
7485
#[derive(Deserialize, DeserializeOver2, Serialize)]
7586
pub struct Mode {
7687
pub normal_main: Style,
@@ -197,9 +208,7 @@ pub struct Help {
197208

198209
impl Theme {
199210
pub(crate) fn reshape(mut self, light: bool) -> Result<Self> {
200-
if self.mgr.tab_width < 1 {
201-
bail!("[mgr].tab_width must be greater than 0");
202-
} else if self.which.cols < 1 || self.which.cols > 3 {
211+
if self.which.cols < 1 || self.which.cols > 3 {
203212
bail!("[which].cols must be between 1 and 3");
204213
}
205214

yazi-plugin/preset/components/header.lua

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ Header = {
99
},
1010
_right = {
1111
{ "count", id = 1, order = 1000 },
12-
{ "tabs", id = 2, order = 2000 },
1312
},
1413
}
1514

@@ -74,27 +73,6 @@ function Header:count()
7473
}
7574
end
7675

77-
function Header:tabs()
78-
local tabs = #cx.tabs
79-
if tabs == 1 then
80-
return ""
81-
end
82-
83-
local spans = {}
84-
for i = 1, tabs do
85-
local text = i
86-
if th.mgr.tab_width > 2 then
87-
text = ya.truncate(text .. " " .. cx.tabs[i].name, { max = th.mgr.tab_width })
88-
end
89-
if i == cx.tabs.idx then
90-
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(th.mgr.tab_active)
91-
else
92-
spans[#spans + 1] = ui.Span(" " .. text .. " "):style(th.mgr.tab_inactive)
93-
end
94-
end
95-
return ui.Line(spans)
96-
end
97-
9876
function Header:reflow() return { self } end
9977

10078
function Header:redraw()

yazi-plugin/preset/components/root.lua

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ function Root:layout()
1515
:direction(ui.Layout.VERTICAL)
1616
:constraints({
1717
ui.Constraint.Length(1),
18+
ui.Constraint.Length(#cx.tabs > 1 and 1 or 0),
1819
ui.Constraint.Fill(1),
1920
ui.Constraint.Length(1),
2021
})
@@ -24,8 +25,9 @@ end
2425
function Root:build()
2526
self._children = {
2627
Header:new(self._chunks[1], cx.active),
27-
Tab:new(self._chunks[2], cx.active),
28-
Status:new(self._chunks[3], cx.active),
28+
Tabs:new(self._chunks[2]),
29+
Tab:new(self._chunks[3], cx.active),
30+
Status:new(self._chunks[4], cx.active),
2931
Modal:new(self._area),
3032
}
3133
end
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
Tabs = {
2+
_id = "tabs",
3+
_offsets = {},
4+
}
5+
6+
function Tabs:new(area)
7+
return setmetatable({
8+
_area = area,
9+
}, { __index = self })
10+
end
11+
12+
function Tabs:reflow() return { self } end
13+
14+
function Tabs:redraw()
15+
local len = #cx.tabs
16+
if len < 2 then
17+
return {}
18+
end
19+
20+
local lines = {
21+
ui.Line(th.tabs.sep_outer.open):fg(th.tabs.inactive.bg),
22+
}
23+
24+
local pos = lines[1]:width()
25+
local max = math.floor(self:inner_width() / len)
26+
for i = 1, len do
27+
local name = ya.truncate(string.format(" %d %s ", i, cx.tabs[i].name), { max = max })
28+
if i == cx.tabs.idx then
29+
lines[#lines + 1] = ui.Line {
30+
ui.Span(th.tabs.sep_inner.open):style(th.tabs.inactive),
31+
ui.Span(name):style(th.tabs.active),
32+
ui.Span(th.tabs.sep_inner.close):style(th.tabs.inactive),
33+
}
34+
else
35+
lines[#lines + 1] = ui.Line(name):style(th.tabs.inactive)
36+
end
37+
self._offsets[i], pos = pos, pos + lines[#lines]:width()
38+
end
39+
40+
lines[#lines + 1] = ui.Line(th.tabs.sep_outer.close):fg(th.tabs.inactive.bg)
41+
return { ui.Line(lines):area(self._area) }
42+
end
43+
44+
function Tabs:inner_width()
45+
local si, so = th.tabs.sep_inner, th.tabs.sep_outer
46+
return math.max(0, self._area.w - ui.Line({ si.open, si.close, so.open, so.close }):width())
47+
end
48+
49+
-- Mouse events
50+
function Tabs:click(event, up)
51+
if up or event.is_middle then
52+
return
53+
end
54+
for i = #self._offsets, 1, -1 do
55+
if event.x >= self._offsets[i] then
56+
ya.emit("tab_switch", { i - 1 })
57+
break
58+
end
59+
end
60+
end
61+
62+
function Tabs:scroll(event, step) end
63+
64+
function Tabs:touch(event, step) end

yazi-plugin/src/config/theme.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ impl Theme {
1111
Composer::make(lua, 15, |lua, key| {
1212
match key {
1313
b"mgr" => lua.to_value_with(&THEME.mgr, OPTS)?,
14+
b"tabs" => lua.to_value_with(&THEME.tabs, OPTS)?,
1415
b"mode" => lua.to_value_with(&THEME.mode, OPTS)?,
1516
b"status" => lua.to_value_with(&THEME.status, OPTS)?,
1617
b"which" => lua.to_value_with(&THEME.which, OPTS)?,

yazi-plugin/src/lua.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
5252
lua.load(preset!("components/root")).set_name("root.lua").exec()?;
5353
lua.load(preset!("components/status")).set_name("status.lua").exec()?;
5454
lua.load(preset!("components/tab")).set_name("tab.lua").exec()?;
55+
lua.load(preset!("components/tabs")).set_name("tabs.lua").exec()?;
5556

5657
Ok(())
5758
}

0 commit comments

Comments
 (0)