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.
The SkeletonLoading component has a default and a white color
variant.
Use the stack
and gap
props in conjunction to layer multiple Skeleton loading bars on top of each other.
stack
accepts a number that correlates to the number of rows (1 is default), and gap
accepts a portion of our spacing props (xxs
as default, xs
, sm
, md
, lg
, xl
, xxl
) to set the pixel distance between each row. gap
will not do anything if there is no corresponding stack
prop set.
The border_radius
prop accepts all of our BorderRadius tokens, with sm
as default.
<%= 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 %>
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.
<%= 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" }) %>
<%= 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>
<%= 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>
Props | Type | Values |
---|---|---|
max_width |
array
|
0%
xs
sm
md
lg
xl
xxl
0
none
100%
|
min_width |
array
|
0%
xs
sm
md
lg
xl
xxl
0
none
100%
|
z_index |
array
|
1
2
3
4
5
6
7
8
9
10
|
number_spacing |
array
|
tabular
|
shadow |
array
|
none
deep
deeper
deepest
|
line_height |
array
|
tightest
tighter
tight
normal
loose
looser
loosest
|
display |
array
|
block
inline_block
inline
flex
inline_flex
none
|
cursor |
array
|
auto
default
none
contextMenu
help
pointer
progress
wait
cell
crosshair
text
verticalText
alias
copy
move
noDrop
notAllowed
grab
grabbing
eResize
nResize
neResize
nwResize
sResize
seResize
swResize
wResize
ewResize
nsResize
neswResize
nwseResize
colResize
rowResize
allScroll
zoomIn
zoomOut
|
flex_direction |
array
|
row
column
rowReverse
columnReverse
|
flex_wrap |
array
|
wrap
nowrap
wrapReverse
|
justify_content |
array
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
justify_self |
array
|
auto
start
end
center
stretch
|
align_items |
array
|
flexStart
flexEnd
start
end
center
baseline
stretch
|
align_content |
array
|
start
end
center
spaceBetween
spaceAround
spaceEvenly
|
align_self |
array
|
auto
start
end
center
stretch
baseline
|
flex |
array
|
auto
initial
0
1
2
3
4
5
6
7
8
9
10
11
12
none
|
flex_grow |
array
|
1
0
|
flex_shrink |
array
|
1
0
|
order |
array
|
1
2
3
4
5
6
7
8
9
10
11
12
|
position |
array
|
relative
absolute
fixed
sticky
|
hover |
array
|
|
text_align |
array
|
start
end
left
right
center
justify
justify-all
match-parent
|
overflow |
array
|
visible
hidden
scroll
auto
|
truncate |
array
|
1
2
3
4
5
|
left |
array
|
0
xxs
xs
sm
md
lg
xl
auto
initial
inherit
|
top |
array
|
0
xxs
xs
sm
md
lg
xl
auto
initial
inherit
|
right |
array
|
0
xxs
xs
sm
md
lg
xl
auto
initial
inherit
|
bottom |
array
|
0
xxs
xs
sm
md
lg
xl
auto
initial
inherit
|
vertical_align |
array
|
baseline
super
top
middle
bottom
sub
text-top
text-bottom
|
min_height |
array
|
auto
xs
sm
md
lg
xl
xxl
xxxl
|
max_height |
array
|
auto
xs
sm
md
lg
xl
xxl
xxxl
|
overflow_x |
array
|
visible
hidden
scroll
auto
|
overflow_y |
array
|
visible
hidden
scroll
auto
|
margin |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
margin_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_bottom |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_left |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_right |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_top |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_x |
array
|
none
xxs
xs
sm
md
lg
xl
|
padding_y |
array
|
none
xxs
xs
sm
md
lg
xl
|
classname |
string
|
|
group_hover |
boolean
|
|
id |
string
|
|
data |
hashprop
|
|
aria |
hashprop
|
|
html_options |
hashprop
|
|
children |
proc
|
|
style |
hashprop
|
Props | Type | Values | Default |
---|---|---|---|
dark |
boolean
|
false
|
|
gap |
enum
|
none
xxs
xs
sm
md
lg
xl
xxl
|
xxs
|
width |
string
|
100%
|
|
border_radius |
enum
|
none
xs
sm
md
lg
xl
rounded
|
sm
|
height |
string
|
16px
|
|
stack |
number
|
1
|
|
color |
enum
|
default
white
|
default
|