gpui: Make style macros more composable (#14007)

This PR begins the process of breaking up the `style_helpers!` macro
into smaller macros that can be used to generate methods for a related
subset of styles.

The style method macros also now accept an optional `visibility`
parameter to control the visibility of the generated methods. This
allows for adding these methods to a struct instead of a just a trait.

For example, to expose just the padding styles on a `Facepile` we can do
this:

```rs
impl Facepile {
    fn style(&mut self) -> &mut StyleRefinement {
        self.base.style()
    }

    gpui::padding_style_methods!({
        visibility: pub
    });
}
```

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-07-09 13:52:52 -04:00 committed by GitHub
parent 8203b6875b
commit 3cdd465226
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 335 additions and 203 deletions

View File

@ -1,9 +1,10 @@
use crate::{
self as gpui, hsla, point, px, relative, rems, AbsoluteLength, AlignItems, CursorStyle,
DefiniteLength, Fill, FlexDirection, FlexWrap, Font, FontStyle, FontWeight, Hsla,
JustifyContent, Length, Position, SharedString, StyleRefinement, Visibility, WhiteSpace,
JustifyContent, Length, SharedString, StyleRefinement, Visibility, WhiteSpace,
};
use crate::{BoxShadow, TextStyleRefinement};
pub use gpui_macros::{margin_style_methods, padding_style_methods, position_style_methods};
use smallvec::{smallvec, SmallVec};
use taffy::style::{AlignContent, Display, Overflow};
@ -14,20 +15,9 @@ pub trait Styled: Sized {
fn style(&mut self) -> &mut StyleRefinement;
gpui_macros::style_helpers!();
/// Sets the position of the element to `relative`.
/// [Docs](https://tailwindcss.com/docs/position)
fn relative(mut self) -> Self {
self.style().position = Some(Position::Relative);
self
}
/// Sets the position of the element to `absolute`.
/// [Docs](https://tailwindcss.com/docs/position)
fn absolute(mut self) -> Self {
self.style().position = Some(Position::Absolute);
self
}
gpui_macros::margin_style_methods!();
gpui_macros::padding_style_methods!();
gpui_macros::position_style_methods!();
/// Sets the display type of the element to `block`.
/// [Docs](https://tailwindcss.com/docs/display)

View File

@ -27,13 +27,34 @@ pub fn derive_render(input: TokenStream) -> TokenStream {
derive_render::derive_render(input)
}
/// Used by gpui to generate the style helpers.
/// Used by GPUI to generate the style helpers.
#[proc_macro]
#[doc(hidden)]
pub fn style_helpers(input: TokenStream) -> TokenStream {
style_helpers::style_helpers(input)
}
/// Generates methods for margin styles.
#[proc_macro]
#[doc(hidden)]
pub fn margin_style_methods(input: TokenStream) -> TokenStream {
style_helpers::margin_style_methods(input)
}
/// Generates methods for padding styles.
#[proc_macro]
#[doc(hidden)]
pub fn padding_style_methods(input: TokenStream) -> TokenStream {
style_helpers::padding_style_methods(input)
}
/// Generates methods for position styles.
#[proc_macro]
#[doc(hidden)]
pub fn position_style_methods(input: TokenStream) -> TokenStream {
style_helpers::position_style_methods(input)
}
/// #[gpui::test] can be used to annotate test functions that run with GPUI support.
/// it supports both synchronous and asynchronous tests, and can provide you with
/// as many `TestAppContext` instances as you need.

View File

@ -2,15 +2,38 @@ use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use syn::{
braced,
parse::{Parse, ParseStream, Result},
parse_macro_input,
parse_macro_input, Token, Visibility,
};
struct StyleableMacroInput;
#[derive(Debug)]
struct StyleableMacroInput {
method_visibility: Visibility,
}
impl Parse for StyleableMacroInput {
fn parse(_input: ParseStream) -> Result<Self> {
Ok(StyleableMacroInput)
fn parse(input: ParseStream) -> Result<Self> {
if !input.peek(syn::token::Brace) {
return Ok(Self {
method_visibility: Visibility::Inherited,
});
}
let content;
braced!(content in input);
let mut method_visibility = None;
let ident: syn::Ident = content.parse()?;
if ident == "visibility" {
let _colon: Token![:] = content.parse()?;
method_visibility = Some(content.parse()?);
}
Ok(Self {
method_visibility: method_visibility.unwrap_or(Visibility::Inherited),
})
}
}
@ -24,11 +47,110 @@ pub fn style_helpers(input: TokenStream) -> TokenStream {
output.into()
}
fn generate_methods() -> Vec<TokenStream2> {
pub fn margin_style_methods(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as StyleableMacroInput);
let methods = generate_box_style_methods(
margin_box_style_prefixes(),
box_style_suffixes(),
input.method_visibility,
);
let output = quote! {
#(#methods)*
};
output.into()
}
pub fn padding_style_methods(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as StyleableMacroInput);
let methods = generate_box_style_methods(
padding_box_style_prefixes(),
box_style_suffixes(),
input.method_visibility,
);
let output = quote! {
#(#methods)*
};
output.into()
}
pub fn position_style_methods(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as StyleableMacroInput);
let visibility = input.method_visibility;
let methods = generate_box_style_methods(
position_box_style_prefixes(),
box_style_suffixes(),
visibility.clone(),
);
let output = quote! {
/// Sets the position of the element to `relative`.
/// [Docs](https://tailwindcss.com/docs/position)
#visibility fn relative(mut self) -> Self {
self.style().position = Some(gpui::Position::Relative);
self
}
/// Sets the position of the element to `absolute`.
/// [Docs](https://tailwindcss.com/docs/position)
#visibility fn absolute(mut self) -> Self {
self.style().position = Some(gpui::Position::Absolute);
self
}
#(#methods)*
};
output.into()
}
struct BoxStylePrefix {
prefix: &'static str,
auto_allowed: bool,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
}
struct BoxStyleSuffix {
suffix: &'static str,
length_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
struct CornerStylePrefix {
prefix: &'static str,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
}
struct CornerStyleSuffix {
suffix: &'static str,
radius_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
struct BorderStylePrefix {
prefix: &'static str,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
}
struct BorderStyleSuffix {
suffix: &'static str,
width_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
fn generate_box_style_methods(
prefixes: Vec<BoxStylePrefix>,
suffixes: Vec<BoxStyleSuffix>,
visibility: Visibility,
) -> Vec<TokenStream2> {
let mut methods = Vec::new();
for box_style_prefix in box_prefixes() {
for box_style_prefix in prefixes {
methods.push(generate_custom_value_setter(
visibility.clone(),
box_style_prefix.prefix,
if box_style_prefix.auto_allowed {
quote! { Length }
@ -39,9 +161,10 @@ fn generate_methods() -> Vec<TokenStream2> {
&box_style_prefix.doc_string_prefix,
));
for box_style_suffix in box_suffixes() {
for box_style_suffix in &suffixes {
if box_style_suffix.suffix != "auto" || box_style_prefix.auto_allowed {
methods.push(generate_predefined_setter(
visibility.clone(),
box_style_prefix.prefix,
box_style_suffix.suffix,
&box_style_prefix.fields,
@ -57,6 +180,7 @@ fn generate_methods() -> Vec<TokenStream2> {
if box_style_suffix.suffix != "auto" {
methods.push(generate_predefined_setter(
visibility.clone(),
box_style_prefix.prefix,
box_style_suffix.suffix,
&box_style_prefix.fields,
@ -72,8 +196,17 @@ fn generate_methods() -> Vec<TokenStream2> {
}
}
methods
}
fn generate_methods() -> Vec<TokenStream2> {
let visibility = Visibility::Inherited;
let mut methods =
generate_box_style_methods(box_prefixes(), box_style_suffixes(), visibility.clone());
for corner_style_prefix in corner_prefixes() {
methods.push(generate_custom_value_setter(
visibility.clone(),
corner_style_prefix.prefix,
quote! { AbsoluteLength },
&corner_style_prefix.fields,
@ -82,6 +215,7 @@ fn generate_methods() -> Vec<TokenStream2> {
for corner_style_suffix in corner_suffixes() {
methods.push(generate_predefined_setter(
visibility.clone(),
corner_style_prefix.prefix,
corner_style_suffix.suffix,
&corner_style_prefix.fields,
@ -98,6 +232,7 @@ fn generate_methods() -> Vec<TokenStream2> {
for border_style_prefix in border_prefixes() {
methods.push(generate_custom_value_setter(
visibility.clone(),
border_style_prefix.prefix,
quote! { AbsoluteLength },
&border_style_prefix.fields,
@ -106,6 +241,7 @@ fn generate_methods() -> Vec<TokenStream2> {
for border_style_suffix in border_suffixes() {
methods.push(generate_predefined_setter(
visibility.clone(),
border_style_prefix.prefix,
border_style_suffix.suffix,
&border_style_prefix.fields,
@ -123,6 +259,7 @@ fn generate_methods() -> Vec<TokenStream2> {
}
fn generate_predefined_setter(
visibility: Visibility,
name: &'static str,
length: &'static str,
fields: &[TokenStream2],
@ -153,7 +290,7 @@ fn generate_predefined_setter(
let method = quote! {
#[doc = #doc_string]
fn #method_name(mut self) -> Self {
#visibility fn #method_name(mut self) -> Self {
let style = self.style();
#(#field_assignments)*
self
@ -164,6 +301,7 @@ fn generate_predefined_setter(
}
fn generate_custom_value_setter(
visibility: Visibility,
prefix: &str,
length_type: TokenStream2,
fields: &[TokenStream2],
@ -186,7 +324,7 @@ fn generate_custom_value_setter(
let method = quote! {
#[doc = #doc_string]
fn #method_name(mut self, length: impl std::clone::Clone + Into<gpui::#length_type>) -> Self {
#visibility fn #method_name(mut self, length: impl std::clone::Clone + Into<gpui::#length_type>) -> Self {
let style = self.style();
#(#field_assignments)*
self
@ -196,11 +334,148 @@ fn generate_custom_value_setter(
method
}
struct BoxStylePrefix {
prefix: &'static str,
auto_allowed: bool,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
fn margin_box_style_prefixes() -> Vec<BoxStylePrefix> {
vec![
BoxStylePrefix {
prefix: "m",
auto_allowed: true,
fields: vec![
quote! { margin.top },
quote! { margin.bottom },
quote! { margin.left },
quote! { margin.right },
],
doc_string_prefix: "Sets the margin of the element. [Docs](https://tailwindcss.com/docs/margin)",
},
BoxStylePrefix {
prefix: "mt",
auto_allowed: true,
fields: vec![quote! { margin.top }],
doc_string_prefix: "Sets the top margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "mb",
auto_allowed: true,
fields: vec![quote! { margin.bottom }],
doc_string_prefix: "Sets the bottom margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "my",
auto_allowed: true,
fields: vec![quote! { margin.top }, quote! { margin.bottom }],
doc_string_prefix: "Sets the vertical margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-vertical-margin)",
},
BoxStylePrefix {
prefix: "mx",
auto_allowed: true,
fields: vec![quote! { margin.left }, quote! { margin.right }],
doc_string_prefix: "Sets the horizontal margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-horizontal-margin)",
},
BoxStylePrefix {
prefix: "ml",
auto_allowed: true,
fields: vec![quote! { margin.left }],
doc_string_prefix: "Sets the left margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "mr",
auto_allowed: true,
fields: vec![quote! { margin.right }],
doc_string_prefix: "Sets the right margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
]
}
fn padding_box_style_prefixes() -> Vec<BoxStylePrefix> {
vec![
BoxStylePrefix {
prefix: "p",
auto_allowed: false,
fields: vec![
quote! { padding.top },
quote! { padding.bottom },
quote! { padding.left },
quote! { padding.right },
],
doc_string_prefix: "Sets the padding of the element. [Docs](https://tailwindcss.com/docs/padding)",
},
BoxStylePrefix {
prefix: "pt",
auto_allowed: false,
fields: vec![quote! { padding.top }],
doc_string_prefix: "Sets the top padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "pb",
auto_allowed: false,
fields: vec![quote! { padding.bottom }],
doc_string_prefix: "Sets the bottom padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "px",
auto_allowed: false,
fields: vec![quote! { padding.left }, quote! { padding.right }],
doc_string_prefix: "Sets the horizontal padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-horizontal-padding)",
},
BoxStylePrefix {
prefix: "py",
auto_allowed: false,
fields: vec![quote! { padding.top }, quote! { padding.bottom }],
doc_string_prefix: "Sets the vertical padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-vertical-padding)",
},
BoxStylePrefix {
prefix: "pl",
auto_allowed: false,
fields: vec![quote! { padding.left }],
doc_string_prefix: "Sets the left padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "pr",
auto_allowed: false,
fields: vec![quote! { padding.right }],
doc_string_prefix: "Sets the right padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
]
}
fn position_box_style_prefixes() -> Vec<BoxStylePrefix> {
vec![
BoxStylePrefix {
prefix: "inset",
auto_allowed: true,
fields: vec![
quote! { inset.top },
quote! { inset.right },
quote! { inset.bottom },
quote! { inset.left },
],
doc_string_prefix: "Sets the top, right, bottom, and left values of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "top",
auto_allowed: true,
fields: vec![quote! { inset.top }],
doc_string_prefix: "Sets the top value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "bottom",
auto_allowed: true,
fields: vec![quote! { inset.bottom }],
doc_string_prefix: "Sets the bottom value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "left",
auto_allowed: true,
fields: vec![quote! { inset.left }],
doc_string_prefix: "Sets the left value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "right",
auto_allowed: true,
fields: vec![quote! { inset.right }],
doc_string_prefix: "Sets the right value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
]
}
fn box_prefixes() -> Vec<BoxStylePrefix> {
@ -255,135 +530,6 @@ fn box_prefixes() -> Vec<BoxStylePrefix> {
fields: vec![quote! { max_size.height }],
doc_string_prefix: "Sets the maximum height of the element. [Docs](https://tailwindcss.com/docs/max-height)",
},
BoxStylePrefix {
prefix: "m",
auto_allowed: true,
fields: vec![
quote! { margin.top },
quote! { margin.bottom },
quote! { margin.left },
quote! { margin.right },
],
doc_string_prefix: "Sets the margin of the element. [Docs](https://tailwindcss.com/docs/margin)",
},
BoxStylePrefix {
prefix: "mt",
auto_allowed: true,
fields: vec![quote! { margin.top }],
doc_string_prefix: "Sets the top margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "mb",
auto_allowed: true,
fields: vec![quote! { margin.bottom }],
doc_string_prefix: "Sets the bottom margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "my",
auto_allowed: true,
fields: vec![quote! { margin.top }, quote! { margin.bottom }],
doc_string_prefix: "Sets the vertical margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-vertical-margin)",
},
BoxStylePrefix {
prefix: "mx",
auto_allowed: true,
fields: vec![quote! { margin.left }, quote! { margin.right }],
doc_string_prefix: "Sets the horizontal margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-horizontal-margin)",
},
BoxStylePrefix {
prefix: "ml",
auto_allowed: true,
fields: vec![quote! { margin.left }],
doc_string_prefix: "Sets the left margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "mr",
auto_allowed: true,
fields: vec![quote! { margin.right }],
doc_string_prefix: "Sets the right margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
},
BoxStylePrefix {
prefix: "p",
auto_allowed: false,
fields: vec![
quote! { padding.top },
quote! { padding.bottom },
quote! { padding.left },
quote! { padding.right },
],
doc_string_prefix: "Sets the padding of the element. [Docs](https://tailwindcss.com/docs/padding)",
},
BoxStylePrefix {
prefix: "pt",
auto_allowed: false,
fields: vec![quote! { padding.top }],
doc_string_prefix: "Sets the top padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "pb",
auto_allowed: false,
fields: vec![quote! { padding.bottom }],
doc_string_prefix: "Sets the bottom padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "px",
auto_allowed: false,
fields: vec![quote! { padding.left }, quote! { padding.right }],
doc_string_prefix: "Sets the horizontal padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-horizontal-padding)",
},
BoxStylePrefix {
prefix: "py",
auto_allowed: false,
fields: vec![quote! { padding.top }, quote! { padding.bottom }],
doc_string_prefix: "Sets the vertical padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-vertical-padding)",
},
BoxStylePrefix {
prefix: "pl",
auto_allowed: false,
fields: vec![quote! { padding.left }],
doc_string_prefix: "Sets the left padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "pr",
auto_allowed: false,
fields: vec![quote! { padding.right }],
doc_string_prefix: "Sets the right padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
},
BoxStylePrefix {
prefix: "inset",
auto_allowed: true,
fields: vec![
quote! { inset.top },
quote! { inset.right },
quote! { inset.bottom },
quote! { inset.left },
],
doc_string_prefix: "Sets the top, right, bottom, and left values of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "top",
auto_allowed: true,
fields: vec![quote! { inset.top }],
doc_string_prefix: "Sets the top value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "bottom",
auto_allowed: true,
fields: vec![quote! { inset.bottom }],
doc_string_prefix: "Sets the bottom value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "left",
auto_allowed: true,
fields: vec![quote! { inset.left }],
doc_string_prefix: "Sets the left value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "right",
auto_allowed: true,
fields: vec![quote! { inset.right }],
doc_string_prefix: "Sets the right value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
},
BoxStylePrefix {
prefix: "gap",
auto_allowed: false,
@ -405,13 +551,7 @@ fn box_prefixes() -> Vec<BoxStylePrefix> {
]
}
struct BoxStyleSuffix {
suffix: &'static str,
length_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
fn box_suffixes() -> Vec<BoxStyleSuffix> {
fn box_style_suffixes() -> Vec<BoxStyleSuffix> {
vec![
BoxStyleSuffix {
suffix: "0",
@ -646,12 +786,6 @@ fn box_suffixes() -> Vec<BoxStyleSuffix> {
]
}
struct CornerStylePrefix {
prefix: &'static str,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
}
fn corner_prefixes() -> Vec<CornerStylePrefix> {
vec![
CornerStylePrefix {
@ -719,12 +853,6 @@ fn corner_prefixes() -> Vec<CornerStylePrefix> {
]
}
struct CornerStyleSuffix {
suffix: &'static str,
radius_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
fn corner_suffixes() -> Vec<CornerStyleSuffix> {
vec![
CornerStyleSuffix {
@ -770,12 +898,6 @@ fn corner_suffixes() -> Vec<CornerStyleSuffix> {
]
}
struct BorderStylePrefix {
prefix: &'static str,
fields: Vec<TokenStream2>,
doc_string_prefix: &'static str,
}
fn border_prefixes() -> Vec<BorderStylePrefix> {
vec![
BorderStylePrefix {
@ -827,12 +949,6 @@ fn border_prefixes() -> Vec<BorderStylePrefix> {
]
}
struct BorderStyleSuffix {
suffix: &'static str,
width_tokens: TokenStream2,
doc_string_suffix: &'static str,
}
fn border_suffixes() -> Vec<BorderStyleSuffix> {
vec![
BorderStyleSuffix {

View File

@ -1,5 +1,5 @@
use crate::prelude::*;
use gpui::AnyElement;
use gpui::{AnyElement, StyleRefinement};
use smallvec::SmallVec;
/// A facepile is a collection of faces stacked horizontally
@ -23,6 +23,23 @@ impl Facepile {
}
}
impl ParentElement for Facepile {
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
self.faces.extend(elements);
}
}
// Style methods.
impl Facepile {
fn style(&mut self) -> &mut StyleRefinement {
self.base.style()
}
gpui::padding_style_methods!({
visibility: pub
});
}
impl RenderOnce for Facepile {
fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
// Lay the faces out in reverse so they overlap in the desired order (left to right, front to back)
@ -40,15 +57,3 @@ impl RenderOnce for Facepile {
)
}
}
impl ParentElement for Facepile {
fn extend(&mut self, elements: impl IntoIterator<Item = AnyElement>) {
self.faces.extend(elements);
}
}
impl Styled for Facepile {
fn style(&mut self) -> &mut gpui::StyleRefinement {
self.base.style()
}
}