lesli_view 1.1.3 → 1.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/lesli_view/components/header.html.erb +5 -5
- data/lib/lesli_view/components/tabs.html.erb +59 -26
- data/lib/lesli_view/components/tabs.rb +7 -7
- data/lib/lesli_view/components/timeline.html.erb +28 -25
- data/lib/lesli_view/elements/avatar.html.erb +3 -3
- data/lib/lesli_view/elements/avatar.rb +8 -8
- data/lib/lesli_view/items/activities.html.erb +4 -6
- data/lib/lesli_view/items/discussion.html.erb +6 -5
- data/lib/lesli_view/items/discussions.html.erb +8 -6
- data/lib/lesli_view/items/task.html.erb +16 -11
- data/lib/lesli_view/items/tasks.html.erb +8 -13
- data/lib/lesli_view/partials/engine_spec.html.erb +28 -41
- data/lib/lesli_view/version.rb +2 -2
- data/readme.md +82 -55
- metadata +1 -7
- data/lib/lesli_view/components/tabs.scss +0 -49
- data/lib/lesli_view/components/tabs_spec.rb +0 -0
- data/lib/lesli_view/components/timeline.scss +0 -216
- data/lib/lesli_view/elements/avatar.scss +0 -50
- data/lib/lesli_view/items/activities.scss +0 -39
- data/lib/lesli_view/items/discussions.scss +0 -47
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 256282d3858c50d538cab6dd29cfe07c2474e61da8b8f1ca131178b9a7418156
|
|
4
|
+
data.tar.gz: f554e466ed571e19aa6f905b99ff821cad077846bd60369d11f15726d96f4011
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cf903d1af2c3487d35b4842222377d59d97c1a512833bb234154b7908d926787bd61531870f5f1ea25676de3425503eee46a93ce4c2d13df2427c96f74c43b1e
|
|
7
|
+
data.tar.gz: da6644cdb5dad1e382e03fd19465491068b39bf17eca2de0511ab2039b22525d84e0dce44539a434ae33fe06070a588f7fdbad7c67de0a657087b436cae8d6aa
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
<section
|
|
3
|
-
class="mx-auto my-8
|
|
3
|
+
class="mx-auto my-8 grid w-full grid-cols-1 gap-5 md:grid-cols-[minmax(0,1fr)_auto] md:items-start"
|
|
4
4
|
<% if title.present? %>aria-labelledby="<%= title_id %>"<% end %>>
|
|
5
5
|
|
|
6
6
|
<div class="min-w-0">
|
|
7
|
-
<div class="flex items-
|
|
7
|
+
<div class="flex items-center gap-4">
|
|
8
8
|
|
|
9
9
|
<% if back? %>
|
|
10
10
|
<%= link_to(
|
|
11
11
|
back_path,
|
|
12
|
-
class: "
|
|
12
|
+
class: "inline-flex h-12 w-12 shrink-0 items-center justify-center rounded-2xl border border-sky-600 bg-white text-sky-700 shadow-sm transition hover:bg-sky-50 hover:text-sky-800 focus:outline-none focus:ring-2 focus:ring-sky-500/30",
|
|
13
13
|
aria: { label: I18n.t("actions.back", default: "Go back") },
|
|
14
14
|
data: { turbo_frame: "_top" }
|
|
15
15
|
) do %>
|
|
16
|
-
<span class="material-symbols
|
|
16
|
+
<span class="material-symbols text-[26px] leading-none" aria-hidden="true">arrow_back</span>
|
|
17
17
|
<% end %>
|
|
18
18
|
<% end %>
|
|
19
19
|
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
<% if actions? %>
|
|
38
38
|
<div
|
|
39
|
-
class="flex
|
|
39
|
+
class="flex flex-wrap items-center gap-3 md:justify-self-end"
|
|
40
40
|
role="group"
|
|
41
41
|
aria-label="<%= I18n.t('actions.label', default: 'Page actions') %>">
|
|
42
42
|
<% if new_path.present? %>
|
|
@@ -1,34 +1,67 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
<% tabs.each_with_index { |tab, index| tab.set_tab_id(tab.tab_id, index) } %>
|
|
2
|
+
<% initial_tab = active_tab.presence || tabs.first&.tab_id %>
|
|
3
|
+
|
|
4
|
+
<div
|
|
5
|
+
class="lesli-tabs min-w-0<%= " flex items-start gap-6" if vertical %>"
|
|
6
|
+
x-data="{
|
|
7
|
+
activeTab: '<%= j(initial_tab.to_s) %>',
|
|
8
|
+
focusTab(event, offset) {
|
|
9
|
+
const tabs = Array.from(event.currentTarget.closest('[role=tablist]').querySelectorAll('[role=tab]'));
|
|
10
|
+
const currentIndex = tabs.indexOf(event.currentTarget);
|
|
11
|
+
const nextTab = tabs[(currentIndex + offset + tabs.length) % tabs.length];
|
|
12
|
+
|
|
13
|
+
nextTab.focus();
|
|
14
|
+
nextTab.click();
|
|
15
|
+
}
|
|
16
|
+
}">
|
|
17
|
+
|
|
18
|
+
<div class="<%= vertical ? "w-48 shrink-0" : "overflow-x-auto" %>">
|
|
19
|
+
<div
|
|
20
|
+
class="<%= vertical ? "flex w-full flex-col border-r border-slate-200" : "flex min-w-max border-b border-slate-200" %>"
|
|
21
|
+
role="tablist"
|
|
22
|
+
aria-orientation="<%= vertical ? "vertical" : "horizontal" %>">
|
|
23
|
+
|
|
24
|
+
<% tabs.each do |tab| %>
|
|
25
|
+
<button
|
|
26
|
+
id="<%= tab.tab_id %>-tab"
|
|
27
|
+
class="inline-flex min-h-11 cursor-pointer items-center gap-2 whitespace-nowrap px-4 py-2.5 text-sm font-medium transition-colors duration-150 focus:outline-none focus-visible:z-10 focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-inset <%= vertical ? "-mr-px w-full border-r-2 text-left" : "-mb-px justify-center border-b-2" %>"
|
|
28
|
+
type="button"
|
|
29
|
+
role="tab"
|
|
30
|
+
aria-controls="<%= tab.tab_id %>"
|
|
31
|
+
:aria-selected="activeTab === '<%= j(tab.tab_id) %>'"
|
|
32
|
+
:tabindex="activeTab === '<%= j(tab.tab_id) %>' ? 0 : -1"
|
|
33
|
+
:class="{
|
|
34
|
+
'border-blue-600 text-blue-700': activeTab === '<%= j(tab.tab_id) %>',
|
|
35
|
+
'border-transparent text-slate-500 hover:text-slate-700': activeTab !== '<%= j(tab.tab_id) %>'
|
|
36
|
+
}"
|
|
37
|
+
@click="activeTab = '<%= j(tab.tab_id) %>'"
|
|
38
|
+
@keydown.right.prevent="focusTab($event, 1)"
|
|
39
|
+
@keydown.down.prevent="focusTab($event, 1)"
|
|
40
|
+
@keydown.left.prevent="focusTab($event, -1)"
|
|
41
|
+
@keydown.up.prevent="focusTab($event, -1)">
|
|
42
|
+
|
|
43
|
+
<% if tab.icon %>
|
|
44
|
+
<span class="material-symbols-outlined text-xl leading-none" aria-hidden="true">
|
|
45
|
+
<%= tab.icon %>
|
|
19
46
|
</span>
|
|
20
|
-
|
|
21
|
-
|
|
47
|
+
<% end %>
|
|
48
|
+
|
|
49
|
+
<span><%= tab.title %></span>
|
|
50
|
+
</button>
|
|
22
51
|
<% end %>
|
|
23
|
-
</
|
|
52
|
+
</div>
|
|
24
53
|
</div>
|
|
25
|
-
|
|
26
|
-
|
|
54
|
+
|
|
55
|
+
<div class="min-w-0 flex-1<%= " pt-5" unless vertical %>">
|
|
56
|
+
<% tabs.each do |tab| %>
|
|
27
57
|
<div
|
|
28
58
|
id="<%= tab.tab_id %>"
|
|
29
|
-
class="
|
|
30
|
-
|
|
31
|
-
|
|
59
|
+
class="min-w-0"
|
|
60
|
+
role="tabpanel"
|
|
61
|
+
aria-labelledby="<%= tab.tab_id %>-tab"
|
|
62
|
+
tabindex="0"
|
|
63
|
+
x-show="activeTab === '<%= j(tab.tab_id) %>'"
|
|
64
|
+
x-transition.opacity.duration.150ms
|
|
32
65
|
x-cloak>
|
|
33
66
|
<%= tab %>
|
|
34
67
|
</div>
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
=begin
|
|
2
|
-
<%= render LesliView::
|
|
3
|
-
<% tabs.with_tab(
|
|
2
|
+
<%= render LesliView::Components::Tabs.new(active_tab: "tab1") do |tabs| %>
|
|
3
|
+
<% tabs.with_tab(id: "tab1", title: "Tab 1") do %>
|
|
4
4
|
hola
|
|
5
5
|
<% end %>
|
|
6
|
-
<% tabs.with_tab(
|
|
7
|
-
<% tabs.with_tab(
|
|
8
|
-
<% tabs.with_tab(
|
|
9
|
-
<% tabs.with_tab(
|
|
10
|
-
<% tabs.with_tab(
|
|
6
|
+
<% tabs.with_tab(id: "tab2", title: "Tab 2") %>
|
|
7
|
+
<% tabs.with_tab(id: "tab3", title: "Tab 3") %>
|
|
8
|
+
<% tabs.with_tab(id: "tab4", title: "Tab 4", icon: "save") %>
|
|
9
|
+
<% tabs.with_tab(id: "tab5", title: "Tab 5", icon: "edit") %>
|
|
10
|
+
<% tabs.with_tab(id: "tab6", title: "Tab 6", icon: "delete") %>
|
|
11
11
|
<% end %>
|
|
12
12
|
=end
|
|
13
13
|
|
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
<div class="lesli-timelines">
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
<
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
<div class="lesli-timelines py-6">
|
|
2
|
+
<ul class="m-0 w-full list-none p-0">
|
|
3
|
+
<% activities.each do |activity| %>
|
|
4
|
+
<li class="group grid grid-cols-[1.5rem_minmax(0,1fr)] gap-x-4 md:grid-cols-[minmax(8rem,auto)_1.5rem_minmax(0,1fr)] md:gap-x-6">
|
|
5
|
+
<div class="col-start-2 mb-2 min-w-0 text-xs font-bold uppercase tracking-[0.2em] text-slate-500 md:col-start-1 md:row-start-1 md:mb-0 md:pt-1 md:text-right">
|
|
6
|
+
<span><%= activity['date'] %></span>
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div class="relative col-start-1 row-span-2 row-start-1 flex justify-center md:col-start-2">
|
|
10
|
+
<span
|
|
11
|
+
class="material-symbols-outlined relative z-10 bg-white text-xl leading-none text-[var(--lesli-color-primary)]"
|
|
12
|
+
aria-hidden="true">
|
|
13
|
+
<%= icons.dig(activity['icon']&.to_sym) || 'radio_button_checked' %>
|
|
14
|
+
</span>
|
|
15
|
+
<span class="absolute top-7 bottom-0 left-1/2 w-px -translate-x-1/2 bg-slate-300 group-last:hidden" aria-hidden="true"></span>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="col-start-2 row-start-2 min-w-0 pb-10 md:col-start-3 md:row-start-1">
|
|
19
|
+
<h6 class="text-base font-semibold text-slate-800">
|
|
20
|
+
<%= activity['operation'] %>
|
|
21
|
+
</h6>
|
|
22
|
+
<p class="mt-1 text-sm leading-6 text-slate-600">
|
|
23
|
+
<%= activity['description'] %>
|
|
24
|
+
</p>
|
|
25
|
+
</div>
|
|
26
|
+
</li>
|
|
27
|
+
<% end %>
|
|
28
|
+
</ul>
|
|
26
29
|
</div>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
<figure class="lesli-element-avatar
|
|
1
|
+
<figure class="lesli-element-avatar <%= avatar_size %> flex shrink-0 items-center justify-center overflow-hidden rounded-full border-[0.1px] border-slate-400 bg-slate-100">
|
|
2
2
|
<% if image %>
|
|
3
|
-
<img src="<%= image %>" alt="Avatar image">
|
|
3
|
+
<img class="h-full w-full object-cover" src="<%= image %>" alt="Avatar image">
|
|
4
4
|
<% else %>
|
|
5
|
-
<span class="
|
|
5
|
+
<span class="font-bold text-slate-700 <%= font_size %>"><%= letter %></span>
|
|
6
6
|
<% end %>
|
|
7
7
|
</figure>
|
|
@@ -32,7 +32,7 @@ Building a better future, one line of code at a time.
|
|
|
32
32
|
module LesliView
|
|
33
33
|
module Elements
|
|
34
34
|
class Avatar < ViewComponent::Base
|
|
35
|
-
attr_reader :image, :name, :size, :letter, :font_size, :
|
|
35
|
+
attr_reader :image, :name, :size, :letter, :font_size, :avatar_size
|
|
36
36
|
|
|
37
37
|
def initialize(image: nil, name: "", size: "medium")
|
|
38
38
|
@image = image
|
|
@@ -40,7 +40,7 @@ module LesliView
|
|
|
40
40
|
@size = size
|
|
41
41
|
@letter = ""
|
|
42
42
|
@font_size = ""
|
|
43
|
-
@
|
|
43
|
+
@avatar_size = ""
|
|
44
44
|
calculate_size
|
|
45
45
|
get_letter unless @image
|
|
46
46
|
end
|
|
@@ -51,14 +51,14 @@ module LesliView
|
|
|
51
51
|
def calculate_size
|
|
52
52
|
case size
|
|
53
53
|
when "small"
|
|
54
|
-
@font_size = "
|
|
55
|
-
@
|
|
54
|
+
@font_size = "text-xl"
|
|
55
|
+
@avatar_size = "size-[60px]"
|
|
56
56
|
when "medium"
|
|
57
|
-
@font_size = "
|
|
58
|
-
@
|
|
57
|
+
@font_size = "text-[2rem]"
|
|
58
|
+
@avatar_size = "size-[120px]"
|
|
59
59
|
when "large"
|
|
60
|
-
@font_size = "
|
|
61
|
-
@
|
|
60
|
+
@font_size = "text-5xl"
|
|
61
|
+
@avatar_size = "size-[180px]"
|
|
62
62
|
else
|
|
63
63
|
raise ArgumentError, "Invalid size: #{size}"
|
|
64
64
|
end
|
|
@@ -29,10 +29,8 @@ Building a better future, one line of code at a time.
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
<%= render(LesliView::Components::Timeline.new(activities:@activities, icons:@icons)) %>
|
|
32
|
+
<article
|
|
33
|
+
class="lesli-items-activities bg-white p-4 sm:p-8"
|
|
34
|
+
id="lesli-items-activities">
|
|
35
|
+
<%= render(LesliView::Components::Timeline.new(activities: @activities, icons: @icons)) %>
|
|
37
36
|
</article>
|
|
38
|
-
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
<
|
|
2
|
-
<div class="
|
|
3
|
-
<strong>Luis Donis</strong>
|
|
1
|
+
<li class="lesli-items-discussions-comments-comment flex flex-col gap-3 border-b border-slate-200 pb-6 last:border-b-0 last:pb-0 sm:flex-row sm:gap-4">
|
|
2
|
+
<div class="shrink-0 text-sm leading-5 text-slate-500 sm:w-40 sm:text-right">
|
|
3
|
+
<strong class="block font-semibold text-slate-800">Luis Donis</strong>
|
|
4
4
|
<%= discussion['created_at_string'] || Date2.new.date_time %>
|
|
5
5
|
</div>
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
<div class="lexxy-content min-w-0 flex-1 break-words text-slate-700">
|
|
7
8
|
<%== discussion.message %>
|
|
8
9
|
</div>
|
|
9
|
-
</
|
|
10
|
+
</li>
|
|
@@ -29,8 +29,8 @@ Building a better future, one line of code at a time.
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
|
-
<article class="lesli-items-discussions" id="lesli-items-discussions">
|
|
33
|
-
<div class="lesli-items-discussions-form">
|
|
32
|
+
<article class="lesli-items-discussions bg-white p-4 sm:p-8" id="lesli-items-discussions">
|
|
33
|
+
<div class="lesli-items-discussions-form p-4">
|
|
34
34
|
<% discussion_class = "#{@resource.class.name.deconstantize}::Items::Discussion".constantize %>
|
|
35
35
|
<% scope_key = ActiveSupport::Inflector.underscore(discussion_class.name).tr("/", "_") %>
|
|
36
36
|
<%= form_with(
|
|
@@ -45,13 +45,15 @@ Building a better future, one line of code at a time.
|
|
|
45
45
|
<%= form.field_control_submit("Add comment") %>
|
|
46
46
|
<% end %>
|
|
47
47
|
</div>
|
|
48
|
-
<hr
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
<hr class="my-6 border-0 border-t border-slate-200">
|
|
49
|
+
|
|
50
|
+
<div class="lesli-items-discussions-container p-4">
|
|
51
|
+
<ul
|
|
52
|
+
id="<%= "#{scope_key}-lesli-items-discussions-list" %>"
|
|
53
|
+
class="m-0 list-none space-y-6 p-0">
|
|
51
54
|
<% @resource.discussions.order(created_at: :desc).each do |comment| %>
|
|
52
55
|
<%= render(LesliView::Items::Discussion.new(comment)) %>
|
|
53
56
|
<% end %>
|
|
54
57
|
</ul>
|
|
55
58
|
</div>
|
|
56
59
|
</article>
|
|
57
|
-
|
|
@@ -30,9 +30,9 @@ Building a better future, one line of code at a time.
|
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
32
|
|
|
33
|
-
<li
|
|
33
|
+
<li
|
|
34
34
|
id="<%= dom_id(@resource, @scope_key) %>"
|
|
35
|
-
class="lesli-items-tasks-item
|
|
35
|
+
class="lesli-items-tasks-item rounded-xl border transition-colors <%= @resource.done ? "lesli-items-tasks-task-done cursor-not-allowed border-slate-200 bg-slate-50" : "border-slate-200 hover:border-slate-300 hover:bg-slate-50" %>">
|
|
36
36
|
<%= form_with(
|
|
37
37
|
url: helpers.polymorphic_path(@resource),
|
|
38
38
|
method: :patch,
|
|
@@ -40,16 +40,21 @@ Building a better future, one line of code at a time.
|
|
|
40
40
|
local: true
|
|
41
41
|
) do |form| %>
|
|
42
42
|
<%= form.hidden_field :id, value: @resource.id %>
|
|
43
|
-
<%= form.button
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
43
|
+
<%= form.button(
|
|
44
|
+
type: "submit",
|
|
45
|
+
disabled: @resource.done?,
|
|
46
|
+
class: "flex w-full cursor-pointer items-center rounded-xl px-4 py-3 text-left text-sm font-medium text-slate-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--lesli-color-primary)] disabled:cursor-not-allowed"
|
|
47
|
+
) do %>
|
|
48
|
+
<span class="flex min-w-0 items-center gap-3">
|
|
49
|
+
<span
|
|
50
|
+
class="material-symbols-outlined shrink-0 text-xl leading-none <%= @resource.done ? "text-slate-400" : "text-[var(--lesli-color-primary)]" %>"
|
|
51
|
+
aria-hidden="true">
|
|
52
|
+
<%= @resource.done ? "check_box" : "check_box_outline_blank" %>
|
|
49
53
|
</span>
|
|
50
|
-
<span
|
|
51
|
-
|
|
54
|
+
<span class="min-w-0 break-words <%= "text-slate-500 line-through" if @resource.done %>">
|
|
55
|
+
<%= @resource.title %>
|
|
56
|
+
</span>
|
|
57
|
+
</span>
|
|
52
58
|
<% end %>
|
|
53
59
|
<% end %>
|
|
54
60
|
</li>
|
|
55
|
-
|
|
@@ -29,16 +29,9 @@ Building a better future, one line of code at a time.
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
31
|
%>
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
text-decoration: line-through;
|
|
36
|
-
opacity: 0.6;
|
|
37
|
-
cursor: not-allowed;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
</style>
|
|
41
|
-
<article class="lesli-items-tasks box p-6" id="<%= dom_id(@resource, :tasks) %>">
|
|
32
|
+
<article
|
|
33
|
+
class="lesli-items-tasks rounded-2xl border border-slate-200 bg-white p-6 shadow-sm"
|
|
34
|
+
id="<%= dom_id(@resource, :tasks) %>">
|
|
42
35
|
<div class="lesli-items-tasks-form">
|
|
43
36
|
<% task_class = "#{@resource.class.name.deconstantize}::Items::Task".constantize %>
|
|
44
37
|
<% scope_key = ActiveSupport::Inflector.underscore(task_class.name).tr("/", "_") %>
|
|
@@ -54,13 +47,15 @@ Building a better future, one line of code at a time.
|
|
|
54
47
|
<%= form.field_control_submit "Add task" %>
|
|
55
48
|
<% end %>
|
|
56
49
|
</div>
|
|
57
|
-
<hr>
|
|
50
|
+
<hr class="my-6 border-0 border-t border-slate-200">
|
|
51
|
+
|
|
58
52
|
<div class="lesli-items-tasks-container">
|
|
59
|
-
<ul
|
|
53
|
+
<ul
|
|
54
|
+
id="<%= "#{scope_key}-lesli-items-tasks-list" %>"
|
|
55
|
+
class="m-0 list-none space-y-3 p-0">
|
|
60
56
|
<% @resource.tasks.each do |task| %>
|
|
61
57
|
<%= render(LesliView::Items::Task.new(task, scope_key)) %>
|
|
62
58
|
<% end %>
|
|
63
59
|
</ul>
|
|
64
60
|
</div>
|
|
65
61
|
</article>
|
|
66
|
-
|
|
@@ -1,51 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
<style>
|
|
3
|
-
.partial-engine-spec div {
|
|
4
|
-
border-bottom: 1px solid silver;
|
|
5
|
-
}
|
|
6
|
-
.partial-engine-spec li {
|
|
7
|
-
font-size: 1.1rem;
|
|
8
|
-
margin-left: .4rem;
|
|
9
|
-
}
|
|
10
|
-
</style>
|
|
11
1
|
<div class="partial-engine-spec">
|
|
12
|
-
<div class="mb-
|
|
13
|
-
<h5 class="
|
|
14
|
-
<p class="
|
|
2
|
+
<div class="mb-4 border-b border-slate-300 pb-3">
|
|
3
|
+
<h5 class="text-xl font-semibold text-slate-800"><%= engine[:name] %></h5>
|
|
4
|
+
<p class="mt-1 text-xl leading-7 text-slate-600"><%= engine[:summary] %></p>
|
|
15
5
|
</div>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
</span>
|
|
22
|
-
<span></span>
|
|
6
|
+
|
|
7
|
+
<ul class="m-0 list-none space-y-2 p-0">
|
|
8
|
+
<li class="ml-1.5 flex items-center gap-2 text-[1.1rem] text-slate-600">
|
|
9
|
+
<span class="material-symbols shrink-0 text-2xl leading-none text-slate-400" aria-hidden="true">
|
|
10
|
+
pest_control
|
|
23
11
|
</span>
|
|
24
|
-
Version: <%= engine[:version]
|
|
12
|
+
<span>Version: <%= engine[:version] %></span>
|
|
25
13
|
</li>
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
</span>
|
|
31
|
-
<span></span>
|
|
14
|
+
|
|
15
|
+
<li class="ml-1.5 flex items-center gap-2 text-[1.1rem] text-slate-600">
|
|
16
|
+
<span class="material-symbols shrink-0 text-2xl leading-none text-slate-400" aria-hidden="true">
|
|
17
|
+
schedule
|
|
32
18
|
</span>
|
|
33
|
-
Build: <%= LesliDate::Formatter.new(Time.at(engine[:build].to_i)).date_time
|
|
19
|
+
<span>Build: <%= LesliDate::Formatter.new(Time.at(engine[:build].to_i)).date_time %></span>
|
|
34
20
|
</li>
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
21
|
+
|
|
22
|
+
<li class="ml-1.5 flex min-w-0 items-center gap-2 text-[1.1rem] text-slate-600">
|
|
23
|
+
<span class="material-symbols shrink-0 text-2xl leading-none text-slate-400" aria-hidden="true">
|
|
24
|
+
library_books
|
|
25
|
+
</span>
|
|
26
|
+
<span class="min-w-0 break-all">
|
|
27
|
+
<%= link_to_if(
|
|
28
|
+
engine.dig(:metadata, "documentation_uri"),
|
|
29
|
+
engine.dig(:metadata, "documentation_uri"),
|
|
30
|
+
engine.dig(:metadata, "documentation_uri"),
|
|
31
|
+
target: "_blank",
|
|
32
|
+
rel: "noopener noreferrer",
|
|
33
|
+
class: "font-sans text-[var(--lesli-color-primary)] underline-offset-4 hover:underline focus-visible:rounded-sm focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--lesli-color-primary)]"
|
|
34
|
+
) %>
|
|
41
35
|
</span>
|
|
42
|
-
<%= link_to_if(
|
|
43
|
-
engine.dig(:metadata, "documentation_uri"),
|
|
44
|
-
engine.dig(:metadata, "documentation_uri"),
|
|
45
|
-
engine.dig(:metadata, "documentation_uri"),
|
|
46
|
-
target: "_blank",
|
|
47
|
-
class: "is-family-sans-serif"
|
|
48
|
-
) %>
|
|
49
36
|
</li>
|
|
50
37
|
</ul>
|
|
51
38
|
</div>
|
data/lib/lesli_view/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -26,78 +26,96 @@
|
|
|
26
26
|
|
|
27
27
|
<br />
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
## Introduction
|
|
30
|
+
|
|
31
|
+
LesliView is the official user-interface library for the [Lesli Framework](https://github.com/LesliTech/Lesli). It packages the framework's shared interface patterns as ViewComponent-powered components, Rails form builders, and domain-oriented views.
|
|
32
|
+
|
|
33
|
+
Use LesliView to build consistent server-rendered interfaces without recreating common layouts, controls, forms, and application states in every Lesli engine.
|
|
30
34
|
|
|
31
35
|
<br />
|
|
32
36
|
|
|
33
|
-
##
|
|
37
|
+
## Why LesliView?
|
|
34
38
|
|
|
35
|
-
LesliView
|
|
39
|
+
LesliView provides:
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
- A shared visual language across Lesli applications and engines
|
|
42
|
+
- Composable, testable components built with ViewComponent
|
|
43
|
+
- Rails-native form builders with consistent labels, controls, messages, and actions
|
|
44
|
+
- Reusable views for common product concepts such as activities, attachments, discussions, and tasks
|
|
45
|
+
- Responsive presentation based on Tailwind CSS utility classes
|
|
46
|
+
- Accessible defaults for labels, button states, navigation, and page actions
|
|
38
47
|
|
|
39
48
|
<br />
|
|
40
49
|
|
|
41
|
-
##
|
|
50
|
+
## Quick Start
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
- Form builders with consistent fields, inputs, and fieldsets
|
|
45
|
-
- Application layout and navigation components
|
|
46
|
-
- Buttons, tables, avatars, and empty states
|
|
47
|
-
- Charts, calendars, counters, dates, and weather widgets
|
|
48
|
-
- Tasks, discussions, activities, and attachment interfaces
|
|
49
|
-
- Shared Tailwind-based presentation for Lesli applications
|
|
52
|
+
### Requirements
|
|
50
53
|
|
|
51
|
-
|
|
54
|
+
The current development baseline is:
|
|
55
|
+
|
|
56
|
+
- Ruby 3.2 or newer
|
|
57
|
+
- Rails 8.1
|
|
58
|
+
- LesliAssets, configured in the host application's asset build
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
ViewComponent and Lexxy are installed as runtime dependencies of LesliView.
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
### Install with Lesli
|
|
63
|
+
|
|
64
|
+
LesliView and LesliAssets are installed automatically with the main `lesli` gem. No additional gem or asset configuration is required in a standard Lesli application.
|
|
65
|
+
|
|
66
|
+
### Install in another Rails application
|
|
67
|
+
|
|
68
|
+
Add LesliView to the application:
|
|
56
69
|
|
|
57
70
|
```shell
|
|
58
71
|
bundle add lesli_view
|
|
59
72
|
```
|
|
60
73
|
|
|
61
|
-
|
|
74
|
+
For the complete Lesli presentation layer, also install the shared assets package:
|
|
75
|
+
|
|
76
|
+
```shell
|
|
77
|
+
bundle add lesli_assets
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The host application must configure LesliAssets in its asset build so the Lesli styles and icon fonts are available before rendering the components.
|
|
62
81
|
|
|
63
82
|
<br />
|
|
64
83
|
|
|
65
84
|
## Usage
|
|
66
85
|
|
|
67
|
-
###
|
|
86
|
+
### Build a page header
|
|
68
87
|
|
|
69
|
-
|
|
88
|
+
Compose a layout and header directly from an ERB template:
|
|
70
89
|
|
|
71
90
|
```erb
|
|
72
|
-
<%= render
|
|
73
|
-
<%= render
|
|
91
|
+
<%= render LesliView::Layout::Container.new("tickets") do %>
|
|
92
|
+
<%= render LesliView::Components::Header.new(
|
|
93
|
+
"Tickets",
|
|
94
|
+
"Manage customer requests and follow-up work.",
|
|
95
|
+
new_path: new_ticket_path,
|
|
96
|
+
new_label: "Create ticket"
|
|
97
|
+
) %>
|
|
74
98
|
<% end %>
|
|
75
99
|
```
|
|
76
100
|
|
|
77
|
-
### Render an
|
|
101
|
+
### Render an action
|
|
78
102
|
|
|
79
|
-
Elements provide
|
|
103
|
+
Elements provide focused interface primitives with consistent behavior and styling:
|
|
80
104
|
|
|
81
105
|
```erb
|
|
82
|
-
<%= render(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
solid: true,
|
|
87
|
-
url: new_ticket_path
|
|
88
|
-
)
|
|
106
|
+
<%= render LesliView::Elements::Button.new(
|
|
107
|
+
"Create ticket",
|
|
108
|
+
icon: "add",
|
|
109
|
+
url: new_ticket_path
|
|
89
110
|
) %>
|
|
90
111
|
```
|
|
91
112
|
|
|
92
|
-
###
|
|
113
|
+
### Build a form
|
|
93
114
|
|
|
94
|
-
Pass the LesliView builder to Rails form helpers:
|
|
115
|
+
Pass the LesliView builder to the standard Rails form helpers:
|
|
95
116
|
|
|
96
117
|
```erb
|
|
97
|
-
<%= form_with(
|
|
98
|
-
model: @ticket,
|
|
99
|
-
builder: LesliView::Forms::Builder
|
|
100
|
-
) do |form| %>
|
|
118
|
+
<%= form_with(model: @ticket, builder: LesliView::Forms::Builder) do |form| %>
|
|
101
119
|
<%= form.field_control_text :subject %>
|
|
102
120
|
<%= form.field_control_textarea :description %>
|
|
103
121
|
<%= form.field_control_submit "Save ticket" %>
|
|
@@ -108,18 +126,27 @@ Pass the LesliView builder to Rails form helpers:
|
|
|
108
126
|
|
|
109
127
|
## Library
|
|
110
128
|
|
|
111
|
-
LesliView organizes its interface
|
|
129
|
+
LesliView organizes its public interface into focused groups:
|
|
130
|
+
|
|
131
|
+
| Group | Included building blocks |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| Charts | Bar, line, and general chart rendering |
|
|
134
|
+
| Components | Headers, panels, tabs, timelines, and toolbars |
|
|
135
|
+
| Elements | Avatars, buttons, empty states, and tables |
|
|
136
|
+
| Forms | Standard and horizontal builders, fields, inputs, and fieldsets |
|
|
137
|
+
| Items | Actions, activities, attachments, discussions, and tasks |
|
|
138
|
+
| Layouts | Shared application containers |
|
|
139
|
+
| Partials | Reusable engine information |
|
|
140
|
+
| Widgets | Calendars, charts, counters, dates, and weather |
|
|
112
141
|
|
|
113
|
-
|
|
114
|
-
- **Components:** headers, panels, tabs, timelines, and toolbars
|
|
115
|
-
- **Elements:** avatars, buttons, empty states, and tables
|
|
116
|
-
- **Forms:** standard and horizontal builders, fields, inputs, and fieldsets
|
|
117
|
-
- **Items:** actions, activities, attachments, discussions, and tasks
|
|
118
|
-
- **Layouts:** shared application containers
|
|
119
|
-
- **Partials:** reusable engine information
|
|
120
|
-
- **Widgets:** calendars, charts, counters, dates, and weather
|
|
142
|
+
See the [LesliView documentation](https://www.lesli.dev/gems/view/) for component options and additional examples.
|
|
121
143
|
|
|
122
|
-
|
|
144
|
+
- [Installation](https://www.lesli.dev/gems/view/about/installation)
|
|
145
|
+
- [Components](https://www.lesli.dev/gems/view/components)
|
|
146
|
+
- [Elements](https://www.lesli.dev/gems/view/elements)
|
|
147
|
+
- [Forms](https://www.lesli.dev/gems/view/forms)
|
|
148
|
+
- [Charts](https://www.lesli.dev/gems/view/charts)
|
|
149
|
+
- [Widgets](https://www.lesli.dev/gems/view/widgets)
|
|
123
150
|
|
|
124
151
|
<br />
|
|
125
152
|
|
|
@@ -133,27 +160,27 @@ cd LesliView
|
|
|
133
160
|
bundle install
|
|
134
161
|
```
|
|
135
162
|
|
|
136
|
-
|
|
163
|
+
Run the default test suite:
|
|
137
164
|
|
|
138
|
-
```
|
|
139
|
-
|
|
165
|
+
```shell
|
|
166
|
+
bundle exec rake
|
|
140
167
|
```
|
|
141
168
|
|
|
142
|
-
|
|
169
|
+
To develop LesliView inside a local Lesli workspace, reference the repository from the host application's `Gemfile`:
|
|
143
170
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
```shell
|
|
147
|
-
bundle exec rake
|
|
171
|
+
```ruby
|
|
172
|
+
gem "lesli_view", path: "gems/LesliView"
|
|
148
173
|
```
|
|
149
174
|
|
|
175
|
+
Then run `bundle install` from the host application so changes to the local gem are loaded immediately.
|
|
176
|
+
|
|
150
177
|
<br />
|
|
151
178
|
|
|
152
179
|
## Documentation
|
|
153
180
|
|
|
154
181
|
- [Lesli website](https://www.lesli.dev/)
|
|
155
|
-
- [
|
|
156
|
-
- [
|
|
182
|
+
- [LesliView documentation](https://www.lesli.dev/gems/view/)
|
|
183
|
+
- [Releases and changelog](https://github.com/LesliTech/LesliView/releases)
|
|
157
184
|
- [Issue tracker](https://github.com/LesliTech/LesliView/issues)
|
|
158
185
|
- [Source code](https://github.com/LesliTech/LesliView)
|
|
159
186
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lesli_view
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Lesli Development Team
|
|
@@ -59,17 +59,13 @@ files:
|
|
|
59
59
|
- lib/lesli_view/components/panel.scss
|
|
60
60
|
- lib/lesli_view/components/tabs.html.erb
|
|
61
61
|
- lib/lesli_view/components/tabs.rb
|
|
62
|
-
- lib/lesli_view/components/tabs.scss
|
|
63
|
-
- lib/lesli_view/components/tabs_spec.rb
|
|
64
62
|
- lib/lesli_view/components/timeline.html.erb
|
|
65
63
|
- lib/lesli_view/components/timeline.rb
|
|
66
|
-
- lib/lesli_view/components/timeline.scss
|
|
67
64
|
- lib/lesli_view/components/toolbar.css
|
|
68
65
|
- lib/lesli_view/components/toolbar.html.erb
|
|
69
66
|
- lib/lesli_view/components/toolbar.rb
|
|
70
67
|
- lib/lesli_view/elements/avatar.html.erb
|
|
71
68
|
- lib/lesli_view/elements/avatar.rb
|
|
72
|
-
- lib/lesli_view/elements/avatar.scss
|
|
73
69
|
- lib/lesli_view/elements/button.css
|
|
74
70
|
- lib/lesli_view/elements/button.html.erb
|
|
75
71
|
- lib/lesli_view/elements/button.rb
|
|
@@ -91,14 +87,12 @@ files:
|
|
|
91
87
|
- lib/lesli_view/items/actions.rb
|
|
92
88
|
- lib/lesli_view/items/activities.html.erb
|
|
93
89
|
- lib/lesli_view/items/activities.rb
|
|
94
|
-
- lib/lesli_view/items/activities.scss
|
|
95
90
|
- lib/lesli_view/items/attachments.html.erb
|
|
96
91
|
- lib/lesli_view/items/attachments.rb
|
|
97
92
|
- lib/lesli_view/items/discussion.html.erb
|
|
98
93
|
- lib/lesli_view/items/discussion.rb
|
|
99
94
|
- lib/lesli_view/items/discussions.html.erb
|
|
100
95
|
- lib/lesli_view/items/discussions.rb
|
|
101
|
-
- lib/lesli_view/items/discussions.scss
|
|
102
96
|
- lib/lesli_view/items/task.html.erb
|
|
103
97
|
- lib/lesli_view/items/task.rb
|
|
104
98
|
- lib/lesli_view/items/tasks.html.erb
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
.lesli-tabs.is-vertical {
|
|
3
|
-
display: flex;
|
|
4
|
-
|
|
5
|
-
.tabs {
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-direction: column;
|
|
8
|
-
align-items: flex-start;
|
|
9
|
-
|
|
10
|
-
ul {
|
|
11
|
-
display: flex;
|
|
12
|
-
flex-direction: column;
|
|
13
|
-
border-bottom: none;
|
|
14
|
-
border-right: 1px solid #dbdbdb;
|
|
15
|
-
margin-right: 1.5rem;
|
|
16
|
-
min-width: 150px;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
li {
|
|
20
|
-
width: 100%;
|
|
21
|
-
margin-bottom: 0.5rem;
|
|
22
|
-
|
|
23
|
-
&:last-child {
|
|
24
|
-
margin-bottom: 0;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
a {
|
|
28
|
-
justify-content: flex-start;
|
|
29
|
-
padding: 0.75em 1em;
|
|
30
|
-
border-bottom: none;
|
|
31
|
-
border-right: 2px solid transparent;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
&.is-active a {
|
|
35
|
-
border-right-color: var(--color-primary);
|
|
36
|
-
border-bottom-color: transparent;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.tab-content {
|
|
41
|
-
flex-grow: 1;
|
|
42
|
-
padding: 1rem;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
.tab-items {
|
|
47
|
-
flex: 1;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
File without changes
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
.lesli-timelines {
|
|
3
|
-
|
|
4
|
-
.lesli-timeline {
|
|
5
|
-
line-height: 1.4em;
|
|
6
|
-
list-style: none;
|
|
7
|
-
margin: 0;
|
|
8
|
-
padding: 0;
|
|
9
|
-
width: 100%;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/*----- TIMELINE ITEM -----*/
|
|
13
|
-
.lesli-timeline-item {
|
|
14
|
-
padding-left: 40px;
|
|
15
|
-
position: relative;
|
|
16
|
-
}
|
|
17
|
-
.lesli-timeline-item:last-child {
|
|
18
|
-
padding-bottom: 0;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/*----- TIMELINE INFO -----*/
|
|
22
|
-
.lesli-timeline-info {
|
|
23
|
-
font-size: 12px;
|
|
24
|
-
font-weight: 700;
|
|
25
|
-
letter-spacing: 3px;
|
|
26
|
-
margin: 0 0 0.5em 0;
|
|
27
|
-
text-transform: uppercase;
|
|
28
|
-
white-space: nowrap;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/*----- TIMELINE MARKER -----*/
|
|
32
|
-
.lesli-timeline-marker {
|
|
33
|
-
position: absolute;
|
|
34
|
-
top: 0;
|
|
35
|
-
bottom: 0;
|
|
36
|
-
left: 0;
|
|
37
|
-
width: 15px;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
.lesli-timeline-marker:before2 {
|
|
41
|
-
background: #ff6b6b;
|
|
42
|
-
border: 3px solid transparent;
|
|
43
|
-
border-radius: 100%;
|
|
44
|
-
content: "";
|
|
45
|
-
display: block;
|
|
46
|
-
height: 15px;
|
|
47
|
-
position: absolute;
|
|
48
|
-
top: 4px;
|
|
49
|
-
left: 0;
|
|
50
|
-
width: 15px;
|
|
51
|
-
transition: background 0.3s ease-in-out, border 0.3s ease-in-out;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.lesli-timeline-marker:after {
|
|
55
|
-
content: "";
|
|
56
|
-
width: 2px;
|
|
57
|
-
background: #ccd5db;
|
|
58
|
-
display: block;
|
|
59
|
-
position: absolute;
|
|
60
|
-
top: 24px;
|
|
61
|
-
bottom: 0;
|
|
62
|
-
left: 0;
|
|
63
|
-
right: 0;
|
|
64
|
-
margin-left: auto;
|
|
65
|
-
margin-right: auto;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.lesli-timeline-item:last-child .lesli-timeline-marker:after {
|
|
69
|
-
content: none;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.lesli-timeline-item:not(.period):hover .lesli-timeline-marker:before {
|
|
73
|
-
background: transparent;
|
|
74
|
-
border: 3px solid #ff6b6b;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/*----- TIMELINE CONTENT -----*/
|
|
78
|
-
.lesli-timeline-content {
|
|
79
|
-
padding-bottom: 40px;
|
|
80
|
-
}
|
|
81
|
-
.lesli-timeline-content p:last-child {
|
|
82
|
-
margin-bottom: 0;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/*----- TIMELINE PERIOD -----*/
|
|
86
|
-
.period {
|
|
87
|
-
padding: 0;
|
|
88
|
-
}
|
|
89
|
-
.period .lesli-timeline-info {
|
|
90
|
-
display: none;
|
|
91
|
-
}
|
|
92
|
-
.period .lesli-timeline-marker:before {
|
|
93
|
-
background: transparent;
|
|
94
|
-
content: "";
|
|
95
|
-
width: 15px;
|
|
96
|
-
height: auto;
|
|
97
|
-
border: none;
|
|
98
|
-
border-radius: 0;
|
|
99
|
-
top: 0;
|
|
100
|
-
bottom: 30px;
|
|
101
|
-
position: absolute;
|
|
102
|
-
border-top: 3px solid #ccd5db;
|
|
103
|
-
border-bottom: 3px solid #ccd5db;
|
|
104
|
-
}
|
|
105
|
-
.period .lesli-timeline-marker:after {
|
|
106
|
-
content: "";
|
|
107
|
-
height: 32px;
|
|
108
|
-
top: auto;
|
|
109
|
-
}
|
|
110
|
-
.period .lesli-timeline-content {
|
|
111
|
-
padding: 40px 0 70px;
|
|
112
|
-
}
|
|
113
|
-
.period .timeline-title {
|
|
114
|
-
margin: 0;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/*----------------------------------------------
|
|
118
|
-
MOD: TIMELINE SPLIT
|
|
119
|
-
----------------------------------------------*/
|
|
120
|
-
@media (min-width: 768px) {
|
|
121
|
-
.lesli-timeline-split .timeline, .timeline-centered .lesli-timeline {
|
|
122
|
-
display: table;
|
|
123
|
-
}
|
|
124
|
-
.lesli-timeline-split .lesli-timeline-item, .timeline-centered .lesli-timeline-item {
|
|
125
|
-
display: table-row;
|
|
126
|
-
padding: 0;
|
|
127
|
-
}
|
|
128
|
-
.lesli-timeline-split .lesli-timeline-info, .timeline-centered .lesli-timeline-info,
|
|
129
|
-
.lesli-timeline-split .lesli-timeline-marker,
|
|
130
|
-
.timeline-centered .lesli-timeline-marker,
|
|
131
|
-
.lesli-timeline-split .lesli-timeline-content,
|
|
132
|
-
.timeline-centered .lesli-timeline-content,
|
|
133
|
-
.lesli-timeline-split .period .lesli-timeline-info {
|
|
134
|
-
display: table-cell;
|
|
135
|
-
vertical-align: top;
|
|
136
|
-
}
|
|
137
|
-
.lesli-timeline-split .lesli-timeline-marker, .timeline-centered .lesli-timeline-marker {
|
|
138
|
-
position: relative;
|
|
139
|
-
}
|
|
140
|
-
.lesli-timeline-split .lesli-timeline-content, .timeline-centered .lesli-timeline-content {
|
|
141
|
-
padding-left: 30px;
|
|
142
|
-
}
|
|
143
|
-
.lesli-timeline-split .lesli-timeline-info, .timeline-centered .lesli-timeline-info {
|
|
144
|
-
padding-right: 30px;
|
|
145
|
-
}
|
|
146
|
-
.lesli-timeline-split .period .timeline-title, .timeline-centered .period .timeline-title {
|
|
147
|
-
position: relative;
|
|
148
|
-
left: -45px;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/*----------------------------------------------
|
|
153
|
-
MOD: TIMELINE CENTERED
|
|
154
|
-
----------------------------------------------*/
|
|
155
|
-
@media (min-width: 992px) {
|
|
156
|
-
.timeline-centered,
|
|
157
|
-
.timeline-centered .lesli-timeline-item,
|
|
158
|
-
.timeline-centered .lesli-timeline-info,
|
|
159
|
-
.timeline-centered .lesli-timeline-marker,
|
|
160
|
-
.timeline-centered .lesli-timeline-content {
|
|
161
|
-
display: block;
|
|
162
|
-
margin: 0;
|
|
163
|
-
padding: 0;
|
|
164
|
-
}
|
|
165
|
-
.timeline-centered .lesli-timeline-item {
|
|
166
|
-
padding-bottom: 40px;
|
|
167
|
-
overflow: hidden;
|
|
168
|
-
}
|
|
169
|
-
.timeline-centered .lesli-timeline-marker {
|
|
170
|
-
position: absolute;
|
|
171
|
-
left: 50%;
|
|
172
|
-
margin-left: -7.5px;
|
|
173
|
-
}
|
|
174
|
-
.timeline-centered .lesli-timeline-info,
|
|
175
|
-
.timeline-centered .lesli-timeline-content {
|
|
176
|
-
width: 50%;
|
|
177
|
-
}
|
|
178
|
-
.timeline-centered > .lesli-timeline-item:nth-child(odd) .lesli-timeline-info {
|
|
179
|
-
float: left;
|
|
180
|
-
text-align: right;
|
|
181
|
-
padding-right: 30px;
|
|
182
|
-
}
|
|
183
|
-
.timeline-centered > .lesli-timeline-item:nth-child(odd) .lesli-timeline-content {
|
|
184
|
-
float: right;
|
|
185
|
-
text-align: left;
|
|
186
|
-
padding-left: 30px;
|
|
187
|
-
}
|
|
188
|
-
.timeline-centered > .lesli-timeline-item:nth-child(even) .lesli-timeline-info {
|
|
189
|
-
float: right;
|
|
190
|
-
text-align: left;
|
|
191
|
-
padding-left: 30px;
|
|
192
|
-
}
|
|
193
|
-
.timeline-centered > .lesli-timeline-item:nth-child(even) .lesli-timeline-content {
|
|
194
|
-
float: left;
|
|
195
|
-
text-align: right;
|
|
196
|
-
padding-right: 30px;
|
|
197
|
-
}
|
|
198
|
-
.timeline-centered > .lesli-timeline-item.period .lesli-timeline-content {
|
|
199
|
-
float: none;
|
|
200
|
-
padding: 0;
|
|
201
|
-
width: 100%;
|
|
202
|
-
text-align: center;
|
|
203
|
-
}
|
|
204
|
-
.timeline-centered .lesli-timeline-item.period {
|
|
205
|
-
padding: 50px 0 90px;
|
|
206
|
-
}
|
|
207
|
-
.timeline-centered .period .lesli-timeline-marker:after {
|
|
208
|
-
height: 30px;
|
|
209
|
-
bottom: 0;
|
|
210
|
-
top: auto;
|
|
211
|
-
}
|
|
212
|
-
.timeline-centered .period .timeline-title {
|
|
213
|
-
left: auto;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
Lesli
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2023, Lesli Technologies, S. A.
|
|
6
|
-
|
|
7
|
-
This program is free software: you can redistribute it and/or modify
|
|
8
|
-
it under the terms of the GNU General Public License as published by
|
|
9
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
-
(at your option) any later version.
|
|
11
|
-
|
|
12
|
-
This program is distributed in the hope that it will be useful,
|
|
13
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
-
GNU General Public License for more details.
|
|
16
|
-
|
|
17
|
-
You should have received a copy of the GNU General Public License
|
|
18
|
-
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
|
-
|
|
20
|
-
Lesli · Ruby on Rails SaaS development platform.
|
|
21
|
-
|
|
22
|
-
Made with ♥ by https://www.lesli.tech
|
|
23
|
-
Building a better future, one line of code at a time.
|
|
24
|
-
|
|
25
|
-
@contact hello@lesli.tech
|
|
26
|
-
@website https://www.lesli.tech
|
|
27
|
-
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
-
|
|
29
|
-
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
-
// ·
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
.lesli-element-avatar {
|
|
34
|
-
display: flex;
|
|
35
|
-
justify-content: center;
|
|
36
|
-
align-items: center;
|
|
37
|
-
border-radius: 50%;
|
|
38
|
-
background-color: lesli-css-color(silver, 100);
|
|
39
|
-
|
|
40
|
-
& > img {
|
|
41
|
-
width: 100%;
|
|
42
|
-
height: 100%;
|
|
43
|
-
object-fit: cover;
|
|
44
|
-
border-radius: 50%;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
& > span {
|
|
48
|
-
color: lesli-css-color(silver, 700);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
Lesli
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2025, Lesli Technologies, S. A.
|
|
6
|
-
|
|
7
|
-
This program is free software: you can redistribute it and/or modify
|
|
8
|
-
it under the terms of the GNU General Public License as published by
|
|
9
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
-
(at your option) any later version.
|
|
11
|
-
|
|
12
|
-
This program is distributed in the hope that it will be useful,
|
|
13
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
-
GNU General Public License for more details.
|
|
16
|
-
|
|
17
|
-
You should have received a copy of the GNU General Public License
|
|
18
|
-
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
|
-
|
|
20
|
-
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
|
-
|
|
22
|
-
Made with ♥ by LesliTech
|
|
23
|
-
Building a better future, one line of code at a time.
|
|
24
|
-
|
|
25
|
-
@contact hello@lesli.tech
|
|
26
|
-
@website https://www.lesli.tech
|
|
27
|
-
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
-
|
|
29
|
-
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
-
// ·
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
@use "lesli-css" as lesli;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.lesli-items-activities {
|
|
37
|
-
background-color: white;
|
|
38
|
-
padding: 2rem;
|
|
39
|
-
}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
|
|
3
|
-
Lesli
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2025, Lesli Technologies, S. A.
|
|
6
|
-
|
|
7
|
-
This program is free software: you can redistribute it and/or modify
|
|
8
|
-
it under the terms of the GNU General Public License as published by
|
|
9
|
-
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
-
(at your option) any later version.
|
|
11
|
-
|
|
12
|
-
This program is distributed in the hope that it will be useful,
|
|
13
|
-
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
-
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
-
GNU General Public License for more details.
|
|
16
|
-
|
|
17
|
-
You should have received a copy of the GNU General Public License
|
|
18
|
-
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
|
-
|
|
20
|
-
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
|
-
|
|
22
|
-
Made with ♥ by LesliTech
|
|
23
|
-
Building a better future, one line of code at a time.
|
|
24
|
-
|
|
25
|
-
@contact hello@lesli.tech
|
|
26
|
-
@website https://www.lesli.tech
|
|
27
|
-
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
-
|
|
29
|
-
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
-
// ·
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
@use "lesli-css" as lesli;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
.lesli-items-discussions {
|
|
37
|
-
background-color: white;
|
|
38
|
-
padding: 2rem;
|
|
39
|
-
|
|
40
|
-
&-form {
|
|
41
|
-
padding: 1rem;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
&-comments {
|
|
45
|
-
padding: 1rem;
|
|
46
|
-
}
|
|
47
|
-
}
|