Skip to content

Commit

Permalink
Merge pull request #1541 from Kajabi/SAGE-535/pjs-sortable-list-inter…
Browse files Browse the repository at this point in the history
…actions-update

List: Sortable list interactions update
  • Loading branch information
philschanely authored Aug 23, 2022
2 parents 90a6b82 + 62c7bf1 commit 71a5a82
Show file tree
Hide file tree
Showing 12 changed files with 215 additions and 104 deletions.
63 changes: 49 additions & 14 deletions docs/app/views/examples/components/list/_preview.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -55,41 +55,76 @@ sample_products = [

<h3 class="<%= SageClassnames::TYPE::HEADING_6 %>">Default configuration</h3>
<%= md("
SageList is implemented most simply by passing the desired contents for the items through the `SageList` `items` property.
This assumes that the contents of the list are already formatted as desired.
`SageList` is implemented most simply by passing the desired contents for the items through the `SageList` `items` property.
This assumes that the contents of the list are already formatted as desired or you're outputting simple content values.
", use_sage_type: true) %>

<%= sage_component SageList, {
items: sample_products.map { | item | {
content: "Item #{item[:name]}",
id: "example-default-item-#{item[:id]}",
more_actions: { items: dropdown_items(item[:id]) },
}
},
} %>

<h3 class="<%= SageClassnames::TYPE::HEADING_6 %>">Sortable configuration</h3>
<%= md("
Sortable lists can be created with `SageList` by adding `sortable: true` and a `sortable_resource`.
You can also pass a `sortable_update_url` for sorting callbacks to items
that will be called after the user finishes sorting an item.
", use_sage_type: true) %>

<%= sage_component SageList, {
sortable: true,
sortable_resource: "sample_products",
items: sample_products.map { | item | {
content: %(
<h4>Item #{item[:name]}</h4>
<p>Item #{item[:id]} specs</p>
).html_safe,
id: item[:id],
content: "Item #{item[:name]}",
id: "example-sortable-item-#{item[:id]}",
more_actions: { items: dropdown_items(item[:id]) },
sortable: true,
sortable_update_url: "#sortable-update-url?item=#{item[:id]}",
}
}
},
} %>

<h3 class="<%= SageClassnames::TYPE::HEADING_6 %>">Fully draggable row</h3>
<%= md('
By default only the drag handle is active for dragging/sorting a row.
However, `drag_handle_type` can be set to `"row"` in order to allow the whole row to be draggable instead.
', use_sage_type: true) %>

<%= sage_component SageList, {
sortable: true,
sortable_resource: "sample_products_2",
items: sample_products.map { | item | {
content: "Item #{item[:name]}",
id: "example-fully-draggable-item-#{item[:id]}",
more_actions: { items: dropdown_items(item[:id]) },
sortable_update_url: "#sortable-update-url?item=#{item[:id]}",
}},
drag_handle_type: "row",
} %>

<h3 class="<%= SageClassnames::TYPE::HEADING_6 %>">Compositional approach</h3>
<%= md("
If you need more native content formatting you can instead opt to render items using a nested loop and the SageListItem component.
If you need more native content formatting you can instead opt to render items using a nested loop and the `SageListItem` component.
Note that this example also implements the [Reveal utility class](#{pages_helpers_path(:reveal)}).
", use_sage_type: true) %>

<%= sage_component SageList, { sortable_resource: "sample_products_2" } do %>
<%= sage_component SageList, {
sortable: true,
sortable_resource: "sample_products_3",
drag_handle_type: "row",
} do %>
<% sample_products.each do | item | %>
<%= sage_component SageListItem, {
id: item[:id],
id: "example-default-item-#{item[:id]}",
more_actions: { items: dropdown_items(item[:id]) },
sortable: true,
sortable_update_url: "#sortable-update-url?item={item[:id]}",
css_classes: SageClassnames::REVEAL_CONTAINER,
} do %>
<%= sage_component SageCardRow, { grid_template: "ete" } do %>
<img src="//source.unsplash.com/random/240x160?v=<%= item[:id] %>" width="100" alt="" />
<img src="https://source.unsplash.com/random/240x160?v=<%= item[:id] %>" width="64" alt="" />
<%= sage_component SageCardBlock, {} do %>
<h4><%= item[:name] %></h4>
<p>Item <%= item[:id] %> specs</p>
Expand Down
15 changes: 9 additions & 6 deletions docs/app/views/examples/components/list/_props.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,21 @@
<td><%= md('See schema for `SageListItem` below.') %></td>
<td><%= md('`[]`') %></td>
</tr>
<tr>
<td><%= md('`drag_handle_type`') %></td>
<td><%= md('
By default only the drag handle is active for dragging/sorting a row.
However, `drag_handle_type` can be set to `"row"` in order to allow the whole row to be draggable instead.
') %></td>
<td><%= md('`"default"` | `"row"` ') %></td>
<td><%= md('`"default"`') %></td>
</tr>
<tr>
<td><%= md('`sortable_resource`') %></td>
<td><%= md('Provide the resource name for a sortable list. Required only when `sortable` is activated for any child items') %></td>
<td><%= md('String') %></td>
<td><%= md('`nil`') %></td>
</tr>
<tr>
<td><%= md('`hide_first_border`') %></td>
<td><%= md('Removes top border from first list item within a SageList') %></td>
<td><%= md('Boolean') %></td>
<td><%= md('`false`') %></td>
</tr>
<tr>
<td colspan="4">
<%= md("**SageListItem**") %>
Expand Down
4 changes: 2 additions & 2 deletions docs/lib/sage_rails/app/sage_tokens/sage_schemas.rb
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ module SageSchemas
LIST_ITEM = {
id: [:optional, Integer, String],
more_actions: [:optional, NilClass, SageSchemas::DROPDOWN],
sortable: [:optional, NilClass, TrueClass],
sortable_update_url: [:optional, NilClass, String],
}

LIST = {
drag_handle_type: [:optional, NilClass, Set.new(["default", "row"])],
items: [:optional, [[SageSchemas::LIST_ITEM]]],
sortable: [:optional, NilClass, TrueClass],
sortable_resource: [:optional, NilClass, String],
tag: [:optional, NilClass, Set.new(["ul", "ol"])],
hide_first_border: [:optional, TrueClass, String],
}

PANEL_FIGURE = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<%
tag = component.tag.present? ? component.tag : "ul"
tag = component.sortable ? "ol" : "ul"
tag = component.tag || tag
drag_handle_type = component.drag_handle_type.present? ? component.drag_handle_type : "default"
%>
<<%= tag %>
class="
sage-list
<%= component.generated_css_classes %>
<%= "sage-list--hide-first-border" if component.hide_first_border %>
<%= "sage-list--sortable" if component.sortable %>
<%= "sage-list--draggable-by-row" if drag_handle_type == "row" %>
"
<%= "data-js-list-sortable=#{component.sortable_resource}" if component.sortable_resource.present? %>
<%= component.generated_html_attributes.html_safe %>
Expand All @@ -15,6 +18,5 @@ tag = component.tag.present? ? component.tag : "ul"
<%= sage_component SageListItem, item_configs %>
<% end %>
<% end %>

<%= component.content %>
</<%= tag %>>
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,15 @@ end
<li
class="
sage-list__item
<%= "sage-list__item--sortable" if component.sortable %>
<%= component.generated_css_classes %>
"
<%= "data-js-list-sortable-update-url=#{component.sortable_update_url}" if component.sortable_update_url.present? %>
<%= "id=#{component.id}" if component.id %>
<%= component.generated_html_attributes.html_safe %>
>
<% if component.sortable %>
<div class="sage-list__item-sortable-handle">
<%= sage_component SageIcon, { icon: "handle" } %>
</div>
<% end %>
<div class="sage-list__item-sortable-handle">
<%= sage_component SageIcon, { icon: "handle-2-vertical" } %>
</div>

<div class="sage-list__item-content">
<%= component.content %>
Expand Down
64 changes: 46 additions & 18 deletions packages/sage-assets/lib/stylesheets/components/_list.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,45 +13,73 @@
.sage-list__item {
display: flex;
align-items: center;
gap: sage-spacing(md);
padding-top: sage-spacing(sm);
padding-bottom: sage-spacing(sm);
gap: sage-spacing(sm);
padding: sage-spacing(xs) rem(12px);
list-style: none;
border-top: sage-border(default);
border-radius: sage-border(radius-medium);

&:first-child {
.sage-list--hide-first-border & {
border-top: 0;
}
&:hover {
background-color: sage-color(grey, 200);
}

.sage-list--draggable-by-row & {
cursor: grab;
}
}

.sage-list__item--sortable {
cursor: grab;
.sage-list__item--sortable-active {
background-color: sage-color(white);

&.sage-list__item--sortable-active:active,
&:active {
.sage-list--draggable-by-row & {
cursor: grabbing;
}
}

.sage-list__item--sortable-drag {
background-color: sage-color(white);
box-shadow: sage-shadow(lg);
// NOTE: !important is added and lint-ignored here so that it can override
// inline opacity that the SortableJS utility we're using adds during sorting.
opacity: 1 !important; /* stylelint-disable-line declaration-no-important */
}

.sage-list__item--sortable-ghost {
opacity: 0.5;
background-color: sage-color(grey, 200);
}

.sage-list__item-content {
flex: 1;

.sage-list__item--sortable-ghost & {
opacity: 0;
}
}

.sage-list__item-more-actions,
.sage-list__item-sortable-handle {
.sage-list__item-more-actions {
width: auto;

.sage-list__item--sortable-ghost & {
opacity: 0;
}
}

.sage-list__item-sortable-handle {
color: sage-color(charcoal, 100);
display: none;

.sage-list--sortable & {
display: initial;
width: auto;
}

&:hover {
cursor: grab;
}

.sage-list__item--sortable-active & {
cursor: grabbing;
}

.sage-list__item:hover & {
color: sage-color(charcoal, 500);
.sage-list__item--sortable-ghost & {
opacity: 0;
}
}
5 changes: 3 additions & 2 deletions packages/sage-assets/lib/stylesheets/components/_lists.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
.sage-list {
padding-left: 0;
list-style: none;

&:not(.sage-list--inline-compact):not(.sage-list--inline-fit-compact) {

// TODO: These styles interfered with the new List component and should be deprecated.
&:not(.sage-list--inline-compact):not(.sage-list--inline-fit-compact):not(.sage-list__item) {
margin-right: -1 * sage-spacing(sm);
margin-left: -1 * sage-spacing(sm);

Expand Down
Loading

0 comments on commit 71a5a82

Please sign in to comment.