Skip to content

Commit

Permalink
[PBNTR-762] Skeleton Loading Component Build - Rails (#4068)
Browse files Browse the repository at this point in the history
**What does this PR do?** A clear and concise description with your
runway ticket url.
[PBNTR-762](https://runway.powerhrg.com/backlog_items/PBNTR-762) creates
the Rails version of the Skeleton Loading component (in follow up to
[PBNTR-485](https://runway.powerhrg.com/backlog_items/PBNTR-485) which
made the React version).

This PR achieves the following:

- Creates the Rails version of the kit using the same shimmering
skeleton scss properties created in PBNTR-485.
- 5 base doc examples: Default, Color, Layout, Border Radius, Height and
Width.
- 2 "example component" doc examples: User kit and Filter kit.
- Adds a description (`_description.md`) to the top of the kit page
explaining how the kit is intended to be used.
- Adds rspec tests.
- Adds a loading toggle to the React "User example component" and
"Filter example component" doc examples (discussed as a follow up to
[PBNTR-694](https://runway.powerhrg.com/backlog_items/PBNTR-694)).

**Screenshots:** Screenshots to visualize your addition/change
5 Base Doc examples:
<img width="1371" alt="desc and default"
src="https://github.com/user-attachments/assets/5a614b06-27e1-470c-9c6b-866115a33c57"
/>
<img width="1331" alt="color layout"
src="https://github.com/user-attachments/assets/bd0589e6-fc5a-4cd7-a3ae-24b3d19b9c0a"
/>
<img width="1320" alt="border and hw 1"
src="https://github.com/user-attachments/assets/ece74510-bace-4426-ab54-140ca5c85cab"
/>
<img width="1320" alt="hw 2"
src="https://github.com/user-attachments/assets/63619b5f-5be9-4f9b-92fe-036b127b9bfe"
/>
Component example doc examples - Rails
<img width="1326" alt="component ex 1"
src="https://github.com/user-attachments/assets/00bac06e-7c9d-45a5-8150-db6148764026"
/>
<img width="1321" alt="component ex 2"
src="https://github.com/user-attachments/assets/0341e450-8d5e-4edc-acab-d379a2288eda"
/>
Component example doc examples - React now toggle-able
<img width="1350" alt="component ex react"
src="https://github.com/user-attachments/assets/44bed417-b03e-4d87-94fa-b533d1bca854"
/>


**How to test?** Steps to confirm the desired behavior:
1. Go to the skeleton loading rails [kit page on the milano
env](https://pr4068.playbook.beta.gm.powerapp.cloud/kits/skeleton_loading).
2. Scroll down and see 7 doc examples for the new Rails Skeleton kit.
The last two (User Component Example and Filter Component Example)
should be toggle-able via the button.
3. Go to the last two doc examples on the React Skeleton Loading [kit
page on the milano
env](https://pr4068.playbook.beta.gm.powerapp.cloud/kits/skeleton_loading/react#user-component-example)
- React's User Component Example and Filter Component Example doc
examples should now be toggle-able via the button.


#### Checklist:
- [x] **LABELS** Add a label: `enhancement`, `bug`, `improvement`, `new
kit`, `deprecated`, or `breaking`. See [Changelog &
Labels](https://github.com/powerhome/playbook/wiki/Changelog-&-Labels)
for details.
- [x] **DEPLOY** I have added the `milano` label to show I'm ready for a
review.
- [x] **TESTS** I have added test coverage to my code.
  • Loading branch information
ElisaShapiro authored Jan 3, 2025
1 parent 4b98e80 commit 80aea95
Show file tree
Hide file tree
Showing 21 changed files with 365 additions and 32 deletions.
2 changes: 1 addition & 1 deletion playbook-website/config/menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ kits:
enhanced_element_used: false
- name: skeleton_loading
platforms: *1
status: beta
status: stable
icons_used: false
react_rendered: false
enhanced_element_used: false
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
@import 'skeleton_loading_mixins';

.pb_skeleton_loading {
display: "flex";
flex-direction: "column";
display: flex;
flex-direction: column;
height: 100%;
.color_default {
@include skeleton-shimmer($silver);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The Skeleton Loading kit can be used an intermediate loading state to give users a visual indication that content is loading.

**Please Note**: this kit is not meant to be integrated interally within other Playbook kits as a loading prop; rather, it can be used to create a composite of the section/kit/page with loading intermediataries, as demonstrated in the the "example component" doc examples.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<%= pb_rails("flex", props: { justify: "evenly" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "rounded", height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { border_radius: "xl", height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { border_radius: "lg", height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { border_radius: "md", height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { border_radius: "xs", height: "50px", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { border_radius: "none", height: "50px", width: "100px"}) %>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The `border_radius` prop accepts all of our [BorderRadius](https://playbook.powerapp.cloud/visual_guidelines/border_radius) tokens, with `sm` as default.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<%= pb_rails("card", props: { border_none: true }) do %>
<%= pb_rails("skeleton_loading") %>
<% end %>

<%= pb_rails("card", props: { background: "light", border_none: true }) do %>
<%= pb_rails("skeleton_loading", props: { color: "white" }) %>
<% end %>
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<%= pb_rails("skeleton_loading") %>
<%= pb_rails("skeleton_loading") %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<%= pb_rails("button", props: { id: "toggle-filter-button", margin_bottom: "md", text: "Show Filter", variant: "secondary" }) %>

<div id="skeleton-loading-filter-content">
<%= pb_rails("card", props: { margin_bottom: "lg" }) do %>
<%= pb_rails("flex", props: { align_items: "center", justify: "between", orientation: "row" }) do %>
<%= pb_rails("flex", props: { align_items: "center", justify: "start", orientation: "row" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "rounded", height: "40px", margin_right: "sm", width: "40px" }) %>
<%= pb_rails("skeleton_loading", props: { height: "16px", margin_right: "md", width: "80px" }) %>
<% end %>
<%= pb_rails("flex", props: { align_items: "center", justify: "end", orientation: "row" }) do %>
<%= pb_rails("skeleton_loading", props: { height: "18px", width: "120px" }) %>
<% end %>
<% end %>
<% end %>

<%= pb_rails("skeleton_loading", props: { height: "127px", width: "100%" }) %>
</div>

<div id="filter-content" style="display: none;">
<%= pb_rails("filter", props: {
margin_bottom: "xl",
min_width: "360px",
id: "2",
filters: [
{ name: "name", value: "John Wick" }
],
sort_menu: [
{ item: "Popularity", link: "?q[sorts]=managers_popularity+asc", active: true, direction: "desc" },
{ item: "Mananger's Title", link: "?q[sorts]=managers_title+asc", active: false },
{ item: "Manager's Name", link: "?q[sorts]=managers_name+asc", active: false },
],
results: 546,
template: "single"
}) do %>
<% example_collection = [
OpenStruct.new(name: "USA", value: 1),
OpenStruct.new(name: "Canada", value: 2),
OpenStruct.new(name: "Brazil", value: 3),
OpenStruct.new(name: "Philippines", value: 4),
OpenStruct.new(name: "A galaxy far far away...", value: 5)
] %>

<%= pb_rails("form", props: { form_system_options: { scope: :example, method: :get } }) do |form| %>
<%= form.text_field :example_text_field, props: { label: true } %>
<%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true } %>

<%= form.actions do |action| %>
<%= action.submit props: {
text: "Apply",
data: {
disable_with: "pb_rails('icon', props: { icon: 'spinner', spin: true, fixed_width: true })Searching...".html_safe
},}%>
<%= action.button props: { type: "reset", text: "Clear", variant: "secondary" } %>
<% end %>
<% end %>
<% end %>

<%= pb_rails("filter", props: {
min_width: "360px",
id: "1",
filters: [
{ name: "name", value: "John Wick" },
{ name: "city", value: "San Francisco"}
],
sort_menu: [
{ item: "Popularity", link: "?q[sorts]=managers_popularity+asc", active: true, direction: "desc" },
{ item: "Mananger's Title", link: "?q[sorts]=managers_title+asc", active: false },
{ item: "Manager's Name", link: "?q[sorts]=managers_name+asc", active: false },
],
template: "default",
results: 1,
}) do %>
<% example_collection = [
OpenStruct.new(name: "USA", value: 1),
OpenStruct.new(name: "Canada", value: 2),
OpenStruct.new(name: "Brazil", value: 3),
OpenStruct.new(name: "Philippines", value: 4),
OpenStruct.new(name: "A galaxy far far away...", value: 5)
] %>
<%= pb_rails("form", props: { form_system_options: { scope: :example, method: :get } }) do |form| %>
<%= form.text_field :example_text_field, props: { label: true } %>
<%= form.collection_select :example_collection_select, example_collection, :value, :name, props: { label: true } %>

<%= form.actions do |action| %>
<%= action.submit props: {
text: "Apply",
data: {
disable_with: "pb_rails('icon', props: { icon: 'spinner', spin: true, fixed_width: true })Searching...".html_safe
},}%>
<%= action.button props: { type: "reset", text: "Clear", variant: "secondary" } %>
<% end %>
<% end %>
<% end %>
</div>

<script>
document.addEventListener("DOMContentLoaded", function() {
const toggleButton = document.getElementById('toggle-filter-button')
const skeletonFilterContentDiv = document.getElementById('skeleton-loading-filter-content')
const filterContentDiv = document.getElementById('filter-content')
const secondFilterContentDiv = document.getElementById('second-filter-content')

let isLoading = true

toggleButton.addEventListener('click', function() {
isLoading = !isLoading

if (isLoading) {
skeletonFilterContentDiv.style.display = 'block'
filterContentDiv.style.display = 'none'
toggleButton.textContent = 'Show Filter'
} else {
skeletonFilterContentDiv.style.display = 'none'
filterContentDiv.style.display = 'block'
toggleButton.textContent = 'Show Skeleton Loading'
}
})
})
</script>
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react';
import React, { useState } from 'react';
import { Button, Card, Filter, Flex, Select, SkeletonLoading, TextInput } from "playbook-ui";

const SortingChangeCallback = (sortOptions) => {
alert(JSON.stringify(sortOptions[0]))
}

const SkeletonLoadingFilter = (props) => {
const isLoading = true
const [isLoading, setIsLoading] = useState(true)
const toggleLoading = () => setIsLoading((prev) => !prev)

const options = [
{ value: 'USA' },
Expand All @@ -18,6 +19,13 @@ const SkeletonLoadingFilter = (props) => {

return (
<div>
<Button
marginBottom="md"
onClick={toggleLoading}
variant="secondary"
>
{isLoading ? "Show Filter" : "Show Skeleton Loading"}
</Button>
<div>
{isLoading ? (
<Card
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<%= pb_rails("skeleton_loading", props: { height: "100px", width: "50%" }) %>

<%= pb_rails("skeleton_loading", props: { gap: "md", height: "20px", margin_y: "md", stack: 3, width: "50px" }) %>

<%= pb_rails("card", props: { height: "200px", margin_bottom: "md", padding: "none", width: "100%" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "md", gap: "xl", height: "50%", width: "300px" }) %>
<% end %>

<%= pb_rails("card", props: { height: "200px", margin_bottom: "md", padding: "none", width: "100%" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "md", gap: "xl", height: "30%", stack: 2, width: "70%" }) %>
<% end %>

<%= pb_rails("skeleton_loading", props: { height: "150px", margin_y: "md", width: "150px" }) %>

<%= pb_rails("skeleton_loading", props: { border_radius: "rounded", height: "150px", width: "150px" }) %>
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ const SkeletonLoadingHeightWidth = (props) => (
width="50px"
{...props}
/>
<Card htmlOptions={{ style: { height: '200px', width: '100%' }}}
<Card
height='200px'
marginBottom="md"
padding="none"
width='100%'
{...props}
>
<SkeletonLoading
Expand All @@ -30,8 +32,10 @@ const SkeletonLoadingHeightWidth = (props) => (
{...props}
/>
</Card>
<Card htmlOptions={{ style: { height: '200px', width: '100%' }}}
<Card
height='200px'
padding="none"
width='100%'
{...props}
>
<SkeletonLoading
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The `height` and `width` props accept pixel and percentage values. If using a percentage for `height`, the parent container must have a set height.

Set the `height` and `width` props to the same value to make a square. A `rounded` border_radius will make a square a circle. If using percentages to make a square, your parent container must also be a square.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<%= pb_rails("skeleton_loading", props: { stack: 5 }) %>

<%= pb_rails("skeleton_loading", props: { gap: "md", padding_top: "xl", stack: 3 }) %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<%= pb_rails("button", props: { id: "toggle-user-button", margin_bottom: "md", text: "Show User", variant: "secondary" }) %>

<div id="skeleton-loading-user-content">
<%= pb_rails("flex", props: { align_items: "center" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "rounded", height: "38px", padding_right: "sm", width: "38px"}) %>
<%= pb_rails("skeleton_loading", props: { gap: "xxs", height: "18px", stack: 2, width: "161px"}) %>
<% end %>
<%= pb_rails("flex", props: { align_items: "start", padding_top: "md" }) do %>
<%= pb_rails("flex", props: { align_items: "center", flex_direction: "column" }) do %>
<%= pb_rails("skeleton_loading", props: { border_radius: "rounded", height: "100px", padding_bottom: "xs", width: "100px"}) %>
<%= pb_rails("skeleton_loading", props: { height: "32px", padding_bottom: "xxs", width: "144px"}) %>
<%= pb_rails("skeleton_loading", props: { height: "21px", width: "164px"}) %>
<% end %>
<% end %>
</div>

<div id="user-content" style="display: none;">
<div>
<%= pb_rails("user", props: {
name: "Anna Black",
title: "Remodeling Consultant",
orientation: "horizontal",
align: "left",
avatar_url: "https://randomuser.me/api/portraits/women/44.jpg"
}) %>
</div>
<div>
<%= pb_rails("flex", props: { align_items: "start", padding_top: "md" }) do %>
<%= pb_rails("user", props: {
name: "Anna Black",
title: "Remodeling Consultant",
orientation: "vertical",
align: "center",
size: "lg",
avatar_url: "https://randomuser.me/api/portraits/women/44.jpg"
}) %>
<% end %>
</div>
</div>

<script>
document.addEventListener("DOMContentLoaded", function() {
const toggleButton = document.getElementById('toggle-user-button')
const skeletonUserContentDiv = document.getElementById('skeleton-loading-user-content')
const userContentDiv = document.getElementById('user-content')

let isLoading = true

toggleButton.addEventListener('click', function() {
isLoading = !isLoading

if (isLoading) {
skeletonUserContentDiv.style.display = 'block'
userContentDiv.style.display = 'none'
toggleButton.textContent = 'Show User'
} else {
skeletonUserContentDiv.style.display = 'none'
userContentDiv.style.display = 'block'
toggleButton.textContent = 'Show Skeleton Loading'
}
})
})
</script>
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import React from 'react';
import { Flex, SkeletonLoading, User } from "playbook-ui";
import React, { useState } from 'react';
import { Button, Flex, SkeletonLoading, User } from "playbook-ui";

const SkeletonLoadingUser = (props) => {
const isLoading = true
const [isLoading, setIsLoading] = useState(true)
const toggleLoading = () => setIsLoading((prev) => !prev)

return (
<div>
<Button
marginBottom="md"
onClick={toggleLoading}
variant="secondary"
>
{isLoading ? "Show User" : "Show Skeleton Loading"}
</Button>
<div>
{isLoading ? (
<Flex alignItems="center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
examples:

rails:
# - skeleton_loading_default: Default

- skeleton_loading_default: Default
- skeleton_loading_color: Color
- skeleton_loading_layout: Layout
- skeleton_loading_border_radius: Border Radius
- skeleton_loading_height_width: Height & Width
- skeleton_loading_user: User Component Example
- skeleton_loading_filter: Filter Component Example

react:
- skeleton_loading_default: Default
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
<!-- Go to pb_content_tag definition in kit_base.rb for usage information. Commented out options are default (showing the default shape), and each can be deleted if not customizing that param. -->
<!-- If using nonstandard params please un-comment out and replace with your custom params. -->
<%= pb_content_tag(
# :div,
# aria: object.aria,
# class: object.classname,
# data: object.data,
# id: object.id,
# **combined_html_options
) do %>
<span>SKELETON_LOADING CONTENT</span>
<% end %>
<%= pb_content_tag do %>
<% stack.times do |index| %>
<div
class="<%= item_classname(index) %>"
style="<%= item_inline_styles %>"
></div>
<% end %>
<% end %>
Loading

0 comments on commit 80aea95

Please sign in to comment.