styles.rs

   1use proc_macro::TokenStream;
   2use proc_macro2::TokenStream as TokenStream2;
   3use quote::{format_ident, quote};
   4use syn::{
   5    braced,
   6    parse::{Parse, ParseStream, Result},
   7    parse_macro_input, Token, Visibility,
   8};
   9
  10#[derive(Debug)]
  11struct StyleableMacroInput {
  12    method_visibility: Visibility,
  13}
  14
  15impl Parse for StyleableMacroInput {
  16    fn parse(input: ParseStream) -> Result<Self> {
  17        if !input.peek(syn::token::Brace) {
  18            return Ok(Self {
  19                method_visibility: Visibility::Inherited,
  20            });
  21        }
  22
  23        let content;
  24        braced!(content in input);
  25
  26        let mut method_visibility = None;
  27
  28        let ident: syn::Ident = content.parse()?;
  29        if ident == "visibility" {
  30            let _colon: Token![:] = content.parse()?;
  31            method_visibility = Some(content.parse()?);
  32        }
  33
  34        Ok(Self {
  35            method_visibility: method_visibility.unwrap_or(Visibility::Inherited),
  36        })
  37    }
  38}
  39
  40pub fn style_helpers(input: TokenStream) -> TokenStream {
  41    let _ = parse_macro_input!(input as StyleableMacroInput);
  42    let methods = generate_methods();
  43    let output = quote! {
  44        #(#methods)*
  45    };
  46
  47    output.into()
  48}
  49
  50pub fn visibility_style_methods(input: TokenStream) -> TokenStream {
  51    let input = parse_macro_input!(input as StyleableMacroInput);
  52    let visibility = input.method_visibility;
  53    let output = quote! {
  54        /// Sets the visibility of the element to `visible`.
  55        /// [Docs](https://tailwindcss.com/docs/visibility)
  56        #visibility fn visible(mut self) -> Self {
  57            self.style().visibility = Some(gpui::Visibility::Visible);
  58            self
  59        }
  60
  61        /// Sets the visibility of the element to `hidden`.
  62        /// [Docs](https://tailwindcss.com/docs/visibility)
  63        #visibility fn invisible(mut self) -> Self {
  64            self.style().visibility = Some(gpui::Visibility::Hidden);
  65            self
  66        }
  67    };
  68
  69    output.into()
  70}
  71
  72pub fn margin_style_methods(input: TokenStream) -> TokenStream {
  73    let input = parse_macro_input!(input as StyleableMacroInput);
  74    let methods = generate_box_style_methods(
  75        margin_box_style_prefixes(),
  76        box_style_suffixes(),
  77        input.method_visibility,
  78    );
  79    let output = quote! {
  80        #(#methods)*
  81    };
  82
  83    output.into()
  84}
  85
  86pub fn padding_style_methods(input: TokenStream) -> TokenStream {
  87    let input = parse_macro_input!(input as StyleableMacroInput);
  88    let methods = generate_box_style_methods(
  89        padding_box_style_prefixes(),
  90        box_style_suffixes(),
  91        input.method_visibility,
  92    );
  93    let output = quote! {
  94        #(#methods)*
  95    };
  96
  97    output.into()
  98}
  99
 100pub fn position_style_methods(input: TokenStream) -> TokenStream {
 101    let input = parse_macro_input!(input as StyleableMacroInput);
 102    let visibility = input.method_visibility;
 103    let methods = generate_box_style_methods(
 104        position_box_style_prefixes(),
 105        box_style_suffixes(),
 106        visibility.clone(),
 107    );
 108    let output = quote! {
 109        /// Sets the position of the element to `relative`.
 110        /// [Docs](https://tailwindcss.com/docs/position)
 111        #visibility fn relative(mut self) -> Self {
 112            self.style().position = Some(gpui::Position::Relative);
 113            self
 114        }
 115
 116        /// Sets the position of the element to `absolute`.
 117        /// [Docs](https://tailwindcss.com/docs/position)
 118        #visibility fn absolute(mut self) -> Self {
 119            self.style().position = Some(gpui::Position::Absolute);
 120            self
 121        }
 122
 123        #(#methods)*
 124    };
 125
 126    output.into()
 127}
 128
 129pub fn overflow_style_methods(input: TokenStream) -> TokenStream {
 130    let input = parse_macro_input!(input as StyleableMacroInput);
 131    let visibility = input.method_visibility;
 132    let output = quote! {
 133        /// Sets the behavior of content that overflows the container to be hidden.
 134        /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
 135        #visibility fn overflow_hidden(mut self) -> Self {
 136            self.style().overflow.x = Some(gpui::Overflow::Hidden);
 137            self.style().overflow.y = Some(gpui::Overflow::Hidden);
 138            self
 139        }
 140
 141        /// Sets the behavior of content that overflows the container on the X axis to be hidden.
 142        /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
 143        #visibility fn overflow_x_hidden(mut self) -> Self {
 144            self.style().overflow.x = Some(gpui::Overflow::Hidden);
 145            self
 146        }
 147
 148        /// Sets the behavior of content that overflows the container on the Y axis to be hidden.
 149        /// [Docs](https://tailwindcss.com/docs/overflow#hiding-content-that-overflows)
 150        #visibility fn overflow_y_hidden(mut self) -> Self {
 151            self.style().overflow.y = Some(gpui::Overflow::Hidden);
 152            self
 153        }
 154    };
 155
 156    output.into()
 157}
 158
 159pub fn cursor_style_methods(input: TokenStream) -> TokenStream {
 160    let input = parse_macro_input!(input as StyleableMacroInput);
 161    let visibility = input.method_visibility;
 162    let output = quote! {
 163        /// Set the cursor style when hovering over this element
 164        #visibility fn cursor(mut self, cursor: CursorStyle) -> Self {
 165            self.style().mouse_cursor = Some(cursor);
 166            self
 167        }
 168
 169        /// Sets the cursor style when hovering an element to `default`.
 170        /// [Docs](https://tailwindcss.com/docs/cursor)
 171        #visibility fn cursor_default(mut self) -> Self {
 172            self.style().mouse_cursor = Some(gpui::CursorStyle::Arrow);
 173            self
 174        }
 175
 176        /// Sets the cursor style when hovering an element to `pointer`.
 177        /// [Docs](https://tailwindcss.com/docs/cursor)
 178        #visibility fn cursor_pointer(mut self) -> Self {
 179            self.style().mouse_cursor = Some(gpui::CursorStyle::PointingHand);
 180            self
 181        }
 182
 183        /// Sets cursor style when hovering over an element to `text`.
 184        /// [Docs](https://tailwindcss.com/docs/cursor)
 185        #visibility fn cursor_text(mut self) -> Self {
 186            self.style().mouse_cursor = Some(gpui::CursorStyle::IBeam);
 187            self
 188        }
 189
 190        /// Sets cursor style when hovering over an element to `move`.
 191        /// [Docs](https://tailwindcss.com/docs/cursor)
 192        #visibility fn cursor_move(mut self) -> Self {
 193            self.style().mouse_cursor = Some(gpui::CursorStyle::ClosedHand);
 194            self
 195        }
 196
 197        /// Sets cursor style when hovering over an element to `not-allowed`.
 198        /// [Docs](https://tailwindcss.com/docs/cursor)
 199        #visibility fn cursor_not_allowed(mut self) -> Self {
 200            self.style().mouse_cursor = Some(gpui::CursorStyle::OperationNotAllowed);
 201            self
 202        }
 203
 204        /// Sets cursor style when hovering over an element to `context-menu`.
 205        /// [Docs](https://tailwindcss.com/docs/cursor)
 206        #visibility fn cursor_context_menu(mut self) -> Self {
 207            self.style().mouse_cursor = Some(gpui::CursorStyle::ContextualMenu);
 208            self
 209        }
 210
 211        /// Sets cursor style when hovering over an element to `crosshair`.
 212        /// [Docs](https://tailwindcss.com/docs/cursor)
 213        #visibility fn cursor_crosshair(mut self) -> Self {
 214            self.style().mouse_cursor = Some(gpui::CursorStyle::Crosshair);
 215            self
 216        }
 217
 218        /// Sets cursor style when hovering over an element to `vertical-text`.
 219        /// [Docs](https://tailwindcss.com/docs/cursor)
 220        #visibility fn cursor_vertical_text(mut self) -> Self {
 221            self.style().mouse_cursor = Some(gpui::CursorStyle::IBeamCursorForVerticalLayout);
 222            self
 223        }
 224
 225        /// Sets cursor style when hovering over an element to `alias`.
 226        /// [Docs](https://tailwindcss.com/docs/cursor)
 227        #visibility fn cursor_alias(mut self) -> Self {
 228            self.style().mouse_cursor = Some(gpui::CursorStyle::DragLink);
 229            self
 230        }
 231
 232        /// Sets cursor style when hovering over an element to `copy`.
 233        /// [Docs](https://tailwindcss.com/docs/cursor)
 234        #visibility fn cursor_copy(mut self) -> Self {
 235            self.style().mouse_cursor = Some(gpui::CursorStyle::DragCopy);
 236            self
 237        }
 238
 239        /// Sets cursor style when hovering over an element to `no-drop`.
 240        /// [Docs](https://tailwindcss.com/docs/cursor)
 241        #visibility fn cursor_no_drop(mut self) -> Self {
 242            self.style().mouse_cursor = Some(gpui::CursorStyle::OperationNotAllowed);
 243            self
 244        }
 245
 246        /// Sets cursor style when hovering over an element to `grab`.
 247        /// [Docs](https://tailwindcss.com/docs/cursor)
 248        #visibility fn cursor_grab(mut self) -> Self {
 249            self.style().mouse_cursor = Some(gpui::CursorStyle::OpenHand);
 250            self
 251        }
 252
 253        /// Sets cursor style when hovering over an element to `grabbing`.
 254        /// [Docs](https://tailwindcss.com/docs/cursor)
 255        #visibility fn cursor_grabbing(mut self) -> Self {
 256            self.style().mouse_cursor = Some(gpui::CursorStyle::ClosedHand);
 257            self
 258        }
 259
 260        /// Sets cursor style when hovering over an element to `ew-resize`.
 261        /// [Docs](https://tailwindcss.com/docs/cursor)
 262        #visibility fn cursor_ew_resize(mut self) -> Self {
 263            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeLeftRight);
 264            self
 265        }
 266
 267        /// Sets cursor style when hovering over an element to `ns-resize`.
 268        /// [Docs](https://tailwindcss.com/docs/cursor)
 269        #visibility fn cursor_ns_resize(mut self) -> Self {
 270            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeUpDown);
 271            self
 272        }
 273
 274        /// Sets cursor style when hovering over an element to `nesw-resize`.
 275        /// [Docs](https://tailwindcss.com/docs/cursor)
 276        #visibility fn cursor_nesw_resize(mut self) -> Self {
 277            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeUpRightDownLeft);
 278            self
 279        }
 280
 281        /// Sets cursor style when hovering over an element to `nwse-resize`.
 282        /// [Docs](https://tailwindcss.com/docs/cursor)
 283        #visibility fn cursor_nwse_resize(mut self) -> Self {
 284            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeUpLeftDownRight);
 285            self
 286        }
 287
 288        /// Sets cursor style when hovering over an element to `col-resize`.
 289        /// [Docs](https://tailwindcss.com/docs/cursor)
 290        #visibility fn cursor_col_resize(mut self) -> Self {
 291            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeColumn);
 292            self
 293        }
 294
 295        /// Sets cursor style when hovering over an element to `row-resize`.
 296        /// [Docs](https://tailwindcss.com/docs/cursor)
 297        #visibility fn cursor_row_resize(mut self) -> Self {
 298            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeRow);
 299            self
 300        }
 301
 302        /// Sets cursor style when hovering over an element to `n-resize`.
 303        /// [Docs](https://tailwindcss.com/docs/cursor)
 304        #visibility fn cursor_n_resize(mut self) -> Self {
 305            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeUp);
 306            self
 307        }
 308
 309        /// Sets cursor style when hovering over an element to `e-resize`.
 310        /// [Docs](https://tailwindcss.com/docs/cursor)
 311        #visibility fn cursor_e_resize(mut self) -> Self {
 312            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeRight);
 313            self
 314        }
 315
 316        /// Sets cursor style when hovering over an element to `s-resize`.
 317        /// [Docs](https://tailwindcss.com/docs/cursor)
 318        #visibility fn cursor_s_resize(mut self) -> Self {
 319            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeDown);
 320            self
 321        }
 322
 323        /// Sets cursor style when hovering over an element to `w-resize`.
 324        /// [Docs](https://tailwindcss.com/docs/cursor)
 325        #visibility fn cursor_w_resize(mut self) -> Self {
 326            self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeLeft);
 327            self
 328        }
 329    };
 330
 331    output.into()
 332}
 333
 334pub fn border_style_methods(input: TokenStream) -> TokenStream {
 335    let input = parse_macro_input!(input as StyleableMacroInput);
 336    let visibility = input.method_visibility;
 337
 338    let mut methods = Vec::new();
 339
 340    for border_style_prefix in border_prefixes() {
 341        methods.push(generate_custom_value_setter(
 342            visibility.clone(),
 343            border_style_prefix.prefix,
 344            quote! { AbsoluteLength },
 345            &border_style_prefix.fields,
 346            border_style_prefix.doc_string_prefix,
 347        ));
 348
 349        for border_style_suffix in border_suffixes() {
 350            methods.push(generate_predefined_setter(
 351                visibility.clone(),
 352                border_style_prefix.prefix,
 353                border_style_suffix.suffix,
 354                &border_style_prefix.fields,
 355                &border_style_suffix.width_tokens,
 356                false,
 357                &format!(
 358                    "{prefix}\n\n{suffix}",
 359                    prefix = border_style_prefix.doc_string_prefix,
 360                    suffix = border_style_suffix.doc_string_suffix,
 361                ),
 362            ));
 363        }
 364    }
 365
 366    let output = quote! {
 367        /// Sets the border color of the element.
 368        #visibility fn border_color<C>(mut self, border_color: C) -> Self
 369        where
 370            C: Into<gpui::Hsla>,
 371            Self: Sized,
 372        {
 373            self.style().border_color = Some(border_color.into());
 374            self
 375        }
 376
 377        #(#methods)*
 378    };
 379
 380    output.into()
 381}
 382
 383pub fn box_shadow_style_methods(input: TokenStream) -> TokenStream {
 384    let input = parse_macro_input!(input as StyleableMacroInput);
 385    let visibility = input.method_visibility;
 386    let output = quote! {
 387        /// Sets the box shadow of the element.
 388        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 389        #visibility fn shadow(mut self, shadows: smallvec::SmallVec<[gpui::BoxShadow; 2]>) -> Self {
 390            self.style().box_shadow = Some(shadows);
 391            self
 392        }
 393
 394        /// Clears the box shadow of the element.
 395        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 396        #visibility fn shadow_none(mut self) -> Self {
 397            self.style().box_shadow = Some(Default::default());
 398            self
 399        }
 400
 401        /// Sets the box shadow of the element.
 402        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 403        #visibility fn shadow_sm(mut self) -> Self {
 404            use gpui::{BoxShadow, hsla, point, px};
 405            use smallvec::smallvec;
 406
 407            self.style().box_shadow = Some(smallvec![BoxShadow {
 408                color: hsla(0., 0., 0., 0.05),
 409                offset: point(px(0.), px(1.)),
 410                blur_radius: px(2.),
 411                spread_radius: px(0.),
 412            }]);
 413            self
 414        }
 415
 416        /// Sets the box shadow of the element.
 417        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 418        #visibility fn shadow_md(mut self) -> Self {
 419            use gpui::{BoxShadow, hsla, point, px};
 420            use smallvec::smallvec;
 421
 422            self.style().box_shadow = Some(smallvec![
 423                BoxShadow {
 424                    color: hsla(0.5, 0., 0., 0.1),
 425                    offset: point(px(0.), px(4.)),
 426                    blur_radius: px(6.),
 427                    spread_radius: px(-1.),
 428                },
 429                BoxShadow {
 430                    color: hsla(0., 0., 0., 0.1),
 431                    offset: point(px(0.), px(2.)),
 432                    blur_radius: px(4.),
 433                    spread_radius: px(-2.),
 434                }
 435            ]);
 436            self
 437        }
 438
 439        /// Sets the box shadow of the element.
 440        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 441        #visibility fn shadow_lg(mut self) -> Self {
 442            use gpui::{BoxShadow, hsla, point, px};
 443            use smallvec::smallvec;
 444
 445            self.style().box_shadow = Some(smallvec![
 446                BoxShadow {
 447                    color: hsla(0., 0., 0., 0.1),
 448                    offset: point(px(0.), px(10.)),
 449                    blur_radius: px(15.),
 450                    spread_radius: px(-3.),
 451                },
 452                BoxShadow {
 453                    color: hsla(0., 0., 0., 0.1),
 454                    offset: point(px(0.), px(4.)),
 455                    blur_radius: px(6.),
 456                    spread_radius: px(-4.),
 457                }
 458            ]);
 459            self
 460        }
 461
 462        /// Sets the box shadow of the element.
 463        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 464        #visibility fn shadow_xl(mut self) -> Self {
 465            use gpui::{BoxShadow, hsla, point, px};
 466            use smallvec::smallvec;
 467
 468            self.style().box_shadow = Some(smallvec![
 469                BoxShadow {
 470                    color: hsla(0., 0., 0., 0.1),
 471                    offset: point(px(0.), px(20.)),
 472                    blur_radius: px(25.),
 473                    spread_radius: px(-5.),
 474                },
 475                BoxShadow {
 476                    color: hsla(0., 0., 0., 0.1),
 477                    offset: point(px(0.), px(8.)),
 478                    blur_radius: px(10.),
 479                    spread_radius: px(-6.),
 480                }
 481            ]);
 482            self
 483        }
 484
 485        /// Sets the box shadow of the element.
 486        /// [Docs](https://tailwindcss.com/docs/box-shadow)
 487        #visibility fn shadow_2xl(mut self) -> Self {
 488            use gpui::{BoxShadow, hsla, point, px};
 489            use smallvec::smallvec;
 490
 491            self.style().box_shadow = Some(smallvec![BoxShadow {
 492                color: hsla(0., 0., 0., 0.25),
 493                offset: point(px(0.), px(25.)),
 494                blur_radius: px(50.),
 495                spread_radius: px(-12.),
 496            }]);
 497            self
 498        }
 499    };
 500
 501    output.into()
 502}
 503
 504struct BoxStylePrefix {
 505    prefix: &'static str,
 506    auto_allowed: bool,
 507    fields: Vec<TokenStream2>,
 508    doc_string_prefix: &'static str,
 509}
 510
 511struct BoxStyleSuffix {
 512    suffix: &'static str,
 513    length_tokens: TokenStream2,
 514    doc_string_suffix: &'static str,
 515}
 516
 517struct CornerStylePrefix {
 518    prefix: &'static str,
 519    fields: Vec<TokenStream2>,
 520    doc_string_prefix: &'static str,
 521}
 522
 523struct CornerStyleSuffix {
 524    suffix: &'static str,
 525    radius_tokens: TokenStream2,
 526    doc_string_suffix: &'static str,
 527}
 528
 529struct BorderStylePrefix {
 530    prefix: &'static str,
 531    fields: Vec<TokenStream2>,
 532    doc_string_prefix: &'static str,
 533}
 534
 535struct BorderStyleSuffix {
 536    suffix: &'static str,
 537    width_tokens: TokenStream2,
 538    doc_string_suffix: &'static str,
 539}
 540
 541fn generate_box_style_methods(
 542    prefixes: Vec<BoxStylePrefix>,
 543    suffixes: Vec<BoxStyleSuffix>,
 544    visibility: Visibility,
 545) -> Vec<TokenStream2> {
 546    let mut methods = Vec::new();
 547
 548    for box_style_prefix in prefixes {
 549        methods.push(generate_custom_value_setter(
 550            visibility.clone(),
 551            box_style_prefix.prefix,
 552            if box_style_prefix.auto_allowed {
 553                quote! { Length }
 554            } else {
 555                quote! { DefiniteLength }
 556            },
 557            &box_style_prefix.fields,
 558            box_style_prefix.doc_string_prefix,
 559        ));
 560
 561        for box_style_suffix in &suffixes {
 562            if box_style_suffix.suffix != "auto" || box_style_prefix.auto_allowed {
 563                methods.push(generate_predefined_setter(
 564                    visibility.clone(),
 565                    box_style_prefix.prefix,
 566                    box_style_suffix.suffix,
 567                    &box_style_prefix.fields,
 568                    &box_style_suffix.length_tokens,
 569                    false,
 570                    &format!(
 571                        "{prefix}\n\n{suffix}",
 572                        prefix = box_style_prefix.doc_string_prefix,
 573                        suffix = box_style_suffix.doc_string_suffix,
 574                    ),
 575                ));
 576            }
 577
 578            if box_style_suffix.suffix != "auto" {
 579                methods.push(generate_predefined_setter(
 580                    visibility.clone(),
 581                    box_style_prefix.prefix,
 582                    box_style_suffix.suffix,
 583                    &box_style_prefix.fields,
 584                    &box_style_suffix.length_tokens,
 585                    true,
 586                    &format!(
 587                        "{prefix}\n\n{suffix}",
 588                        prefix = box_style_prefix.doc_string_prefix,
 589                        suffix = box_style_suffix.doc_string_suffix,
 590                    ),
 591                ));
 592            }
 593        }
 594    }
 595
 596    methods
 597}
 598
 599fn generate_methods() -> Vec<TokenStream2> {
 600    let visibility = Visibility::Inherited;
 601    let mut methods =
 602        generate_box_style_methods(box_prefixes(), box_style_suffixes(), visibility.clone());
 603
 604    for corner_style_prefix in corner_prefixes() {
 605        methods.push(generate_custom_value_setter(
 606            visibility.clone(),
 607            corner_style_prefix.prefix,
 608            quote! { AbsoluteLength },
 609            &corner_style_prefix.fields,
 610            corner_style_prefix.doc_string_prefix,
 611        ));
 612
 613        for corner_style_suffix in corner_suffixes() {
 614            methods.push(generate_predefined_setter(
 615                visibility.clone(),
 616                corner_style_prefix.prefix,
 617                corner_style_suffix.suffix,
 618                &corner_style_prefix.fields,
 619                &corner_style_suffix.radius_tokens,
 620                false,
 621                &format!(
 622                    "{prefix}\n\n{suffix}",
 623                    prefix = corner_style_prefix.doc_string_prefix,
 624                    suffix = corner_style_suffix.doc_string_suffix,
 625                ),
 626            ));
 627        }
 628    }
 629
 630    methods
 631}
 632
 633fn generate_predefined_setter(
 634    visibility: Visibility,
 635    name: &'static str,
 636    length: &'static str,
 637    fields: &[TokenStream2],
 638    length_tokens: &TokenStream2,
 639    negate: bool,
 640    doc_string: &str,
 641) -> TokenStream2 {
 642    let (negation_qualifier, negation_token) = if negate {
 643        ("_neg", quote! { - })
 644    } else {
 645        ("", quote! {})
 646    };
 647
 648    let method_name = if length.is_empty() {
 649        format_ident!("{name}{negation_qualifier}")
 650    } else {
 651        format_ident!("{name}{negation_qualifier}_{length}")
 652    };
 653
 654    let field_assignments = fields
 655        .iter()
 656        .map(|field_tokens| {
 657            quote! {
 658                style.#field_tokens = Some((#negation_token gpui::#length_tokens).into());
 659            }
 660        })
 661        .collect::<Vec<_>>();
 662
 663    let method = quote! {
 664        #[doc = #doc_string]
 665        #visibility fn #method_name(mut self) -> Self {
 666            let style = self.style();
 667            #(#field_assignments)*
 668            self
 669        }
 670    };
 671
 672    method
 673}
 674
 675fn generate_custom_value_setter(
 676    visibility: Visibility,
 677    prefix: &str,
 678    length_type: TokenStream2,
 679    fields: &[TokenStream2],
 680    doc_string: &str,
 681) -> TokenStream2 {
 682    let method_name = format_ident!("{}", prefix);
 683
 684    let mut iter = fields.iter();
 685    let last = iter.next_back().unwrap();
 686    let field_assignments = iter
 687        .map(|field_tokens| {
 688            quote! {
 689                style.#field_tokens = Some(length.clone().into());
 690            }
 691        })
 692        .chain(std::iter::once(quote! {
 693            style.#last = Some(length.into());
 694        }))
 695        .collect::<Vec<_>>();
 696
 697    let method = quote! {
 698        #[doc = #doc_string]
 699        #visibility fn #method_name(mut self, length: impl std::clone::Clone + Into<gpui::#length_type>) -> Self {
 700            let style = self.style();
 701            #(#field_assignments)*
 702            self
 703        }
 704    };
 705
 706    method
 707}
 708
 709fn margin_box_style_prefixes() -> Vec<BoxStylePrefix> {
 710    vec![
 711        BoxStylePrefix {
 712            prefix: "m",
 713            auto_allowed: true,
 714            fields: vec![
 715                quote! { margin.top },
 716                quote! { margin.bottom },
 717                quote! { margin.left },
 718                quote! { margin.right },
 719            ],
 720            doc_string_prefix: "Sets the margin of the element. [Docs](https://tailwindcss.com/docs/margin)",
 721        },
 722        BoxStylePrefix {
 723            prefix: "mt",
 724            auto_allowed: true,
 725            fields: vec![quote! { margin.top }],
 726            doc_string_prefix: "Sets the top margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
 727        },
 728        BoxStylePrefix {
 729            prefix: "mb",
 730            auto_allowed: true,
 731            fields: vec![quote! { margin.bottom }],
 732            doc_string_prefix: "Sets the bottom margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
 733        },
 734        BoxStylePrefix {
 735            prefix: "my",
 736            auto_allowed: true,
 737            fields: vec![quote! { margin.top }, quote! { margin.bottom }],
 738            doc_string_prefix: "Sets the vertical margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-vertical-margin)",
 739        },
 740        BoxStylePrefix {
 741            prefix: "mx",
 742            auto_allowed: true,
 743            fields: vec![quote! { margin.left }, quote! { margin.right }],
 744            doc_string_prefix: "Sets the horizontal margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-horizontal-margin)",
 745        },
 746        BoxStylePrefix {
 747            prefix: "ml",
 748            auto_allowed: true,
 749            fields: vec![quote! { margin.left }],
 750            doc_string_prefix: "Sets the left margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
 751        },
 752        BoxStylePrefix {
 753            prefix: "mr",
 754            auto_allowed: true,
 755            fields: vec![quote! { margin.right }],
 756            doc_string_prefix: "Sets the right margin of the element. [Docs](https://tailwindcss.com/docs/margin#add-margin-to-a-single-side)",
 757        },
 758    ]
 759}
 760
 761fn padding_box_style_prefixes() -> Vec<BoxStylePrefix> {
 762    vec![
 763        BoxStylePrefix {
 764            prefix: "p",
 765            auto_allowed: false,
 766            fields: vec![
 767                quote! { padding.top },
 768                quote! { padding.bottom },
 769                quote! { padding.left },
 770                quote! { padding.right },
 771            ],
 772            doc_string_prefix: "Sets the padding of the element. [Docs](https://tailwindcss.com/docs/padding)",
 773        },
 774        BoxStylePrefix {
 775            prefix: "pt",
 776            auto_allowed: false,
 777            fields: vec![quote! { padding.top }],
 778            doc_string_prefix: "Sets the top padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
 779        },
 780        BoxStylePrefix {
 781            prefix: "pb",
 782            auto_allowed: false,
 783            fields: vec![quote! { padding.bottom }],
 784            doc_string_prefix: "Sets the bottom padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
 785        },
 786        BoxStylePrefix {
 787            prefix: "px",
 788            auto_allowed: false,
 789            fields: vec![quote! { padding.left }, quote! { padding.right }],
 790            doc_string_prefix: "Sets the horizontal padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-horizontal-padding)",
 791        },
 792        BoxStylePrefix {
 793            prefix: "py",
 794            auto_allowed: false,
 795            fields: vec![quote! { padding.top }, quote! { padding.bottom }],
 796            doc_string_prefix: "Sets the vertical padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-vertical-padding)",
 797        },
 798        BoxStylePrefix {
 799            prefix: "pl",
 800            auto_allowed: false,
 801            fields: vec![quote! { padding.left }],
 802            doc_string_prefix: "Sets the left padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
 803        },
 804        BoxStylePrefix {
 805            prefix: "pr",
 806            auto_allowed: false,
 807            fields: vec![quote! { padding.right }],
 808            doc_string_prefix: "Sets the right padding of the element. [Docs](https://tailwindcss.com/docs/padding#add-padding-to-a-single-side)",
 809        },
 810    ]
 811}
 812
 813fn position_box_style_prefixes() -> Vec<BoxStylePrefix> {
 814    vec![
 815        BoxStylePrefix {
 816            prefix: "inset",
 817            auto_allowed: true,
 818            fields: vec![
 819                quote! { inset.top },
 820                quote! { inset.right },
 821                quote! { inset.bottom },
 822                quote! { inset.left },
 823            ],
 824            doc_string_prefix: "Sets the top, right, bottom, and left values of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
 825        },
 826        BoxStylePrefix {
 827            prefix: "top",
 828            auto_allowed: true,
 829            fields: vec![quote! { inset.top }],
 830            doc_string_prefix: "Sets the top value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
 831        },
 832        BoxStylePrefix {
 833            prefix: "bottom",
 834            auto_allowed: true,
 835            fields: vec![quote! { inset.bottom }],
 836            doc_string_prefix: "Sets the bottom value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
 837        },
 838        BoxStylePrefix {
 839            prefix: "left",
 840            auto_allowed: true,
 841            fields: vec![quote! { inset.left }],
 842            doc_string_prefix: "Sets the left value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
 843        },
 844        BoxStylePrefix {
 845            prefix: "right",
 846            auto_allowed: true,
 847            fields: vec![quote! { inset.right }],
 848            doc_string_prefix: "Sets the right value of a positioned element. [Docs](https://tailwindcss.com/docs/top-right-bottom-left)",
 849        },
 850    ]
 851}
 852
 853fn box_prefixes() -> Vec<BoxStylePrefix> {
 854    vec![
 855        BoxStylePrefix {
 856            prefix: "w",
 857            auto_allowed: true,
 858            fields: vec![quote! { size.width }],
 859            doc_string_prefix: "Sets the width of the element. [Docs](https://tailwindcss.com/docs/width)",
 860        },
 861        BoxStylePrefix {
 862            prefix: "h",
 863            auto_allowed: true,
 864            fields: vec![quote! { size.height }],
 865            doc_string_prefix: "Sets the height of the element. [Docs](https://tailwindcss.com/docs/height)",
 866        },
 867        BoxStylePrefix {
 868            prefix: "size",
 869            auto_allowed: true,
 870            fields: vec![quote! {size.width}, quote! {size.height}],
 871            doc_string_prefix: "Sets the width and height of the element.",
 872        },
 873        // TODO: These don't use the same size ramp as the others
 874        // see https://tailwindcss.com/docs/max-width
 875        BoxStylePrefix {
 876            prefix: "min_w",
 877            auto_allowed: true,
 878            fields: vec![quote! { min_size.width }],
 879            doc_string_prefix: "Sets the minimum width of the element. [Docs](https://tailwindcss.com/docs/min-width)",
 880        },
 881        // TODO: These don't use the same size ramp as the others
 882        // see https://tailwindcss.com/docs/max-width
 883        BoxStylePrefix {
 884            prefix: "min_h",
 885            auto_allowed: true,
 886            fields: vec![quote! { min_size.height }],
 887            doc_string_prefix: "Sets the minimum height of the element. [Docs](https://tailwindcss.com/docs/min-height)",
 888        },
 889        // TODO: These don't use the same size ramp as the others
 890        // see https://tailwindcss.com/docs/max-width
 891        BoxStylePrefix {
 892            prefix: "max_w",
 893            auto_allowed: true,
 894            fields: vec![quote! { max_size.width }],
 895            doc_string_prefix: "Sets the maximum width of the element. [Docs](https://tailwindcss.com/docs/max-width)",
 896        },
 897        // TODO: These don't use the same size ramp as the others
 898        // see https://tailwindcss.com/docs/max-width
 899        BoxStylePrefix {
 900            prefix: "max_h",
 901            auto_allowed: true,
 902            fields: vec![quote! { max_size.height }],
 903            doc_string_prefix: "Sets the maximum height of the element. [Docs](https://tailwindcss.com/docs/max-height)",
 904        },
 905        BoxStylePrefix {
 906            prefix: "gap",
 907            auto_allowed: false,
 908            fields: vec![quote! { gap.width }, quote! { gap.height }],
 909            doc_string_prefix: "Sets the gap between rows and columns in flex layouts. [Docs](https://tailwindcss.com/docs/gap)",
 910        },
 911        BoxStylePrefix {
 912            prefix: "gap_x",
 913            auto_allowed: false,
 914            fields: vec![quote! { gap.width }],
 915            doc_string_prefix: "Sets the gap between columns in flex layouts. [Docs](https://tailwindcss.com/docs/gap#changing-row-and-column-gaps-independently)",
 916        },
 917        BoxStylePrefix {
 918            prefix: "gap_y",
 919            auto_allowed: false,
 920            fields: vec![quote! { gap.height }],
 921            doc_string_prefix: "Sets the gap between rows in flex layouts. [Docs](https://tailwindcss.com/docs/gap#changing-row-and-column-gaps-independently)",
 922        },
 923    ]
 924}
 925
 926fn box_style_suffixes() -> Vec<BoxStyleSuffix> {
 927    vec![
 928        BoxStyleSuffix {
 929            suffix: "0",
 930            length_tokens: quote! { px(0.) },
 931            doc_string_suffix: "0px",
 932        },
 933        BoxStyleSuffix {
 934            suffix: "0p5",
 935            length_tokens: quote! { rems(0.125) },
 936            doc_string_suffix: "2px (0.125rem)",
 937        },
 938        BoxStyleSuffix {
 939            suffix: "1",
 940            length_tokens: quote! { rems(0.25) },
 941            doc_string_suffix: "4px (0.25rem)",
 942        },
 943        BoxStyleSuffix {
 944            suffix: "1p5",
 945            length_tokens: quote! { rems(0.375) },
 946            doc_string_suffix: "6px (0.375rem)",
 947        },
 948        BoxStyleSuffix {
 949            suffix: "2",
 950            length_tokens: quote! { rems(0.5) },
 951            doc_string_suffix: "8px (0.5rem)",
 952        },
 953        BoxStyleSuffix {
 954            suffix: "2p5",
 955            length_tokens: quote! { rems(0.625) },
 956            doc_string_suffix: "10px (0.625rem)",
 957        },
 958        BoxStyleSuffix {
 959            suffix: "3",
 960            length_tokens: quote! { rems(0.75) },
 961            doc_string_suffix: "12px (0.75rem)",
 962        },
 963        BoxStyleSuffix {
 964            suffix: "3p5",
 965            length_tokens: quote! { rems(0.875) },
 966            doc_string_suffix: "14px (0.875rem)",
 967        },
 968        BoxStyleSuffix {
 969            suffix: "4",
 970            length_tokens: quote! { rems(1.) },
 971            doc_string_suffix: "16px (1rem)",
 972        },
 973        BoxStyleSuffix {
 974            suffix: "5",
 975            length_tokens: quote! { rems(1.25) },
 976            doc_string_suffix: "20px (1.25rem)",
 977        },
 978        BoxStyleSuffix {
 979            suffix: "6",
 980            length_tokens: quote! { rems(1.5) },
 981            doc_string_suffix: "24px (1.5rem)",
 982        },
 983        BoxStyleSuffix {
 984            suffix: "7",
 985            length_tokens: quote! { rems(1.75) },
 986            doc_string_suffix: "28px (1.75rem)",
 987        },
 988        BoxStyleSuffix {
 989            suffix: "8",
 990            length_tokens: quote! { rems(2.0) },
 991            doc_string_suffix: "32px (2rem)",
 992        },
 993        BoxStyleSuffix {
 994            suffix: "9",
 995            length_tokens: quote! { rems(2.25) },
 996            doc_string_suffix: "36px (2.25rem)",
 997        },
 998        BoxStyleSuffix {
 999            suffix: "10",
1000            length_tokens: quote! { rems(2.5) },
1001            doc_string_suffix: "40px (2.5rem)",
1002        },
1003        BoxStyleSuffix {
1004            suffix: "11",
1005            length_tokens: quote! { rems(2.75) },
1006            doc_string_suffix: "44px (2.75rem)",
1007        },
1008        BoxStyleSuffix {
1009            suffix: "12",
1010            length_tokens: quote! { rems(3.) },
1011            doc_string_suffix: "48px (3rem)",
1012        },
1013        BoxStyleSuffix {
1014            suffix: "16",
1015            length_tokens: quote! { rems(4.) },
1016            doc_string_suffix: "64px (4rem)",
1017        },
1018        BoxStyleSuffix {
1019            suffix: "20",
1020            length_tokens: quote! { rems(5.) },
1021            doc_string_suffix: "80px (5rem)",
1022        },
1023        BoxStyleSuffix {
1024            suffix: "24",
1025            length_tokens: quote! { rems(6.) },
1026            doc_string_suffix: "96px (6rem)",
1027        },
1028        BoxStyleSuffix {
1029            suffix: "32",
1030            length_tokens: quote! { rems(8.) },
1031            doc_string_suffix: "128px (8rem)",
1032        },
1033        BoxStyleSuffix {
1034            suffix: "40",
1035            length_tokens: quote! { rems(10.) },
1036            doc_string_suffix: "160px (10rem)",
1037        },
1038        BoxStyleSuffix {
1039            suffix: "48",
1040            length_tokens: quote! { rems(12.) },
1041            doc_string_suffix: "192px (12rem)",
1042        },
1043        BoxStyleSuffix {
1044            suffix: "56",
1045            length_tokens: quote! { rems(14.) },
1046            doc_string_suffix: "224px (14rem)",
1047        },
1048        BoxStyleSuffix {
1049            suffix: "64",
1050            length_tokens: quote! { rems(16.) },
1051            doc_string_suffix: "256px (16rem)",
1052        },
1053        BoxStyleSuffix {
1054            suffix: "72",
1055            length_tokens: quote! { rems(18.) },
1056            doc_string_suffix: "288px (18rem)",
1057        },
1058        BoxStyleSuffix {
1059            suffix: "80",
1060            length_tokens: quote! { rems(20.) },
1061            doc_string_suffix: "320px (20rem)",
1062        },
1063        BoxStyleSuffix {
1064            suffix: "96",
1065            length_tokens: quote! { rems(24.) },
1066            doc_string_suffix: "384px (24rem)",
1067        },
1068        BoxStyleSuffix {
1069            suffix: "112",
1070            length_tokens: quote! { rems(28.) },
1071            doc_string_suffix: "448px (28rem)",
1072        },
1073        BoxStyleSuffix {
1074            suffix: "128",
1075            length_tokens: quote! { rems(32.) },
1076            doc_string_suffix: "512px (32rem)",
1077        },
1078        BoxStyleSuffix {
1079            suffix: "auto",
1080            length_tokens: quote! { auto() },
1081            doc_string_suffix: "Auto",
1082        },
1083        BoxStyleSuffix {
1084            suffix: "px",
1085            length_tokens: quote! { px(1.) },
1086            doc_string_suffix: "1px",
1087        },
1088        BoxStyleSuffix {
1089            suffix: "full",
1090            length_tokens: quote! { relative(1.) },
1091            doc_string_suffix: "100%",
1092        },
1093        BoxStyleSuffix {
1094            suffix: "1_2",
1095            length_tokens: quote! { relative(0.5) },
1096            doc_string_suffix: "50% (1/2)",
1097        },
1098        BoxStyleSuffix {
1099            suffix: "1_3",
1100            length_tokens: quote! { relative(1./3.) },
1101            doc_string_suffix: "33% (1/3)",
1102        },
1103        BoxStyleSuffix {
1104            suffix: "2_3",
1105            length_tokens: quote! { relative(2./3.) },
1106            doc_string_suffix: "66% (2/3)",
1107        },
1108        BoxStyleSuffix {
1109            suffix: "1_4",
1110            length_tokens: quote! { relative(0.25) },
1111            doc_string_suffix: "25% (1/4)",
1112        },
1113        BoxStyleSuffix {
1114            suffix: "2_4",
1115            length_tokens: quote! { relative(0.5) },
1116            doc_string_suffix: "50% (2/4)",
1117        },
1118        BoxStyleSuffix {
1119            suffix: "3_4",
1120            length_tokens: quote! { relative(0.75) },
1121            doc_string_suffix: "75% (3/4)",
1122        },
1123        BoxStyleSuffix {
1124            suffix: "1_5",
1125            length_tokens: quote! { relative(0.2) },
1126            doc_string_suffix: "20% (1/5)",
1127        },
1128        BoxStyleSuffix {
1129            suffix: "2_5",
1130            length_tokens: quote! { relative(0.4) },
1131            doc_string_suffix: "40% (2/5)",
1132        },
1133        BoxStyleSuffix {
1134            suffix: "3_5",
1135            length_tokens: quote! { relative(0.6) },
1136            doc_string_suffix: "60% (3/5)",
1137        },
1138        BoxStyleSuffix {
1139            suffix: "4_5",
1140            length_tokens: quote! { relative(0.8) },
1141            doc_string_suffix: "80% (4/5)",
1142        },
1143        BoxStyleSuffix {
1144            suffix: "1_6",
1145            length_tokens: quote! { relative(1./6.) },
1146            doc_string_suffix: "16% (1/6)",
1147        },
1148        BoxStyleSuffix {
1149            suffix: "5_6",
1150            length_tokens: quote! { relative(5./6.) },
1151            doc_string_suffix: "80% (5/6)",
1152        },
1153        BoxStyleSuffix {
1154            suffix: "1_12",
1155            length_tokens: quote! { relative(1./12.) },
1156            doc_string_suffix: "8% (1/12)",
1157        },
1158    ]
1159}
1160
1161fn corner_prefixes() -> Vec<CornerStylePrefix> {
1162    vec![
1163        CornerStylePrefix {
1164            prefix: "rounded",
1165            fields: vec![
1166                quote! { corner_radii.top_left },
1167                quote! { corner_radii.top_right },
1168                quote! { corner_radii.bottom_right },
1169                quote! { corner_radii.bottom_left },
1170            ],
1171            doc_string_prefix: "Sets the border radius of the element. [Docs](https://tailwindcss.com/docs/border-radius)",
1172        },
1173        CornerStylePrefix {
1174            prefix: "rounded_t",
1175            fields: vec![
1176                quote! { corner_radii.top_left },
1177                quote! { corner_radii.top_right },
1178            ],
1179            doc_string_prefix: "Sets the border radius of the top side of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-sides-separately)",
1180        },
1181        CornerStylePrefix {
1182            prefix: "rounded_b",
1183            fields: vec![
1184                quote! { corner_radii.bottom_left },
1185                quote! { corner_radii.bottom_right },
1186            ],
1187            doc_string_prefix: "Sets the border radius of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-sides-separately)",
1188        },
1189        CornerStylePrefix {
1190            prefix: "rounded_r",
1191            fields: vec![
1192                quote! { corner_radii.top_right },
1193                quote! { corner_radii.bottom_right },
1194            ],
1195            doc_string_prefix: "Sets the border radius of the right side of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-sides-separately)",
1196        },
1197        CornerStylePrefix {
1198            prefix: "rounded_l",
1199            fields: vec![
1200                quote! { corner_radii.top_left },
1201                quote! { corner_radii.bottom_left },
1202            ],
1203            doc_string_prefix: "Sets the border radius of the left side of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-sides-separately)",
1204        },
1205        CornerStylePrefix {
1206            prefix: "rounded_tl",
1207            fields: vec![quote! { corner_radii.top_left }],
1208            doc_string_prefix: "Sets the border radius of the top left corner of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-corners-separately)",
1209        },
1210        CornerStylePrefix {
1211            prefix: "rounded_tr",
1212            fields: vec![quote! { corner_radii.top_right }],
1213            doc_string_prefix: "Sets the border radius of the top right corner of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-corners-separately)",
1214        },
1215        CornerStylePrefix {
1216            prefix: "rounded_bl",
1217            fields: vec![quote! { corner_radii.bottom_left }],
1218            doc_string_prefix: "Sets the border radius of the bottom left corner of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-corners-separately)",
1219        },
1220        CornerStylePrefix {
1221            prefix: "rounded_br",
1222            fields: vec![quote! { corner_radii.bottom_right }],
1223            doc_string_prefix: "Sets the border radius of the bottom right corner of the element. [Docs](https://tailwindcss.com/docs/border-radius#rounding-corners-separately)",
1224        },
1225    ]
1226}
1227
1228fn corner_suffixes() -> Vec<CornerStyleSuffix> {
1229    vec![
1230        CornerStyleSuffix {
1231            suffix: "none",
1232            radius_tokens: quote! { px(0.) },
1233            doc_string_suffix: "0px",
1234        },
1235        CornerStyleSuffix {
1236            suffix: "xs",
1237            radius_tokens: quote! { rems(0.125) },
1238            doc_string_suffix: "2px (0.125rem)",
1239        },
1240        CornerStyleSuffix {
1241            suffix: "sm",
1242            radius_tokens: quote! { rems(0.25) },
1243            doc_string_suffix: "4px (0.25rem)",
1244        },
1245        CornerStyleSuffix {
1246            suffix: "md",
1247            radius_tokens: quote! { rems(0.375) },
1248            doc_string_suffix: "6px (0.375rem)",
1249        },
1250        CornerStyleSuffix {
1251            suffix: "lg",
1252            radius_tokens: quote! { rems(0.5) },
1253            doc_string_suffix: "8px (0.5rem)",
1254        },
1255        CornerStyleSuffix {
1256            suffix: "xl",
1257            radius_tokens: quote! { rems(0.75) },
1258            doc_string_suffix: "12px (0.75rem)",
1259        },
1260        CornerStyleSuffix {
1261            suffix: "2xl",
1262            radius_tokens: quote! { rems(1.) },
1263            doc_string_suffix: "16px (1rem)",
1264        },
1265        CornerStyleSuffix {
1266            suffix: "3xl",
1267            radius_tokens: quote! { rems(1.5) },
1268            doc_string_suffix: "24px (1.5rem)",
1269        },
1270        CornerStyleSuffix {
1271            suffix: "full",
1272            radius_tokens: quote! {  px(9999.) },
1273            doc_string_suffix: "9999px",
1274        },
1275    ]
1276}
1277
1278fn border_prefixes() -> Vec<BorderStylePrefix> {
1279    vec![
1280        BorderStylePrefix {
1281            prefix: "border",
1282            fields: vec![
1283                quote! { border_widths.top },
1284                quote! { border_widths.right },
1285                quote! { border_widths.bottom },
1286                quote! { border_widths.left },
1287            ],
1288            doc_string_prefix: "Sets the border width of the element. [Docs](https://tailwindcss.com/docs/border-width)"
1289        },
1290        BorderStylePrefix {
1291            prefix: "border_t",
1292            fields: vec![quote! { border_widths.top }],
1293            doc_string_prefix: "Sets the border width of the top side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
1294        },
1295        BorderStylePrefix {
1296            prefix: "border_b",
1297            fields: vec![quote! { border_widths.bottom }],
1298            doc_string_prefix: "Sets the border width of the bottom side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
1299        },
1300        BorderStylePrefix {
1301            prefix: "border_r",
1302            fields: vec![quote! { border_widths.right }],
1303            doc_string_prefix: "Sets the border width of the right side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
1304        },
1305        BorderStylePrefix {
1306            prefix: "border_l",
1307            fields: vec![quote! { border_widths.left }],
1308            doc_string_prefix: "Sets the border width of the left side of the element. [Docs](https://tailwindcss.com/docs/border-width#individual-sides)"
1309        },
1310        BorderStylePrefix {
1311            prefix: "border_x",
1312            fields: vec![
1313                quote! { border_widths.left },
1314                quote! { border_widths.right },
1315            ],
1316            doc_string_prefix: "Sets the border width of the vertical sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
1317        },
1318        BorderStylePrefix {
1319            prefix: "border_y",
1320            fields: vec![
1321                quote! { border_widths.top },
1322                quote! { border_widths.bottom },
1323            ],
1324            doc_string_prefix: "Sets the border width of the horizontal sides of the element. [Docs](https://tailwindcss.com/docs/border-width#horizontal-and-vertical-sides)"
1325        },
1326    ]
1327}
1328
1329fn border_suffixes() -> Vec<BorderStyleSuffix> {
1330    vec![
1331        BorderStyleSuffix {
1332            suffix: "0",
1333            width_tokens: quote! { px(0.)},
1334            doc_string_suffix: "0px",
1335        },
1336        BorderStyleSuffix {
1337            suffix: "1",
1338            width_tokens: quote! { px(1.) },
1339            doc_string_suffix: "1px",
1340        },
1341        BorderStyleSuffix {
1342            suffix: "2",
1343            width_tokens: quote! { px(2.) },
1344            doc_string_suffix: "2px",
1345        },
1346        BorderStyleSuffix {
1347            suffix: "3",
1348            width_tokens: quote! { px(3.) },
1349            doc_string_suffix: "3px",
1350        },
1351        BorderStyleSuffix {
1352            suffix: "4",
1353            width_tokens: quote! { px(4.) },
1354            doc_string_suffix: "4px",
1355        },
1356        BorderStyleSuffix {
1357            suffix: "5",
1358            width_tokens: quote! { px(5.) },
1359            doc_string_suffix: "5px",
1360        },
1361        BorderStyleSuffix {
1362            suffix: "6",
1363            width_tokens: quote! { px(6.) },
1364            doc_string_suffix: "6px",
1365        },
1366        BorderStyleSuffix {
1367            suffix: "7",
1368            width_tokens: quote! { px(7.) },
1369            doc_string_suffix: "7px",
1370        },
1371        BorderStyleSuffix {
1372            suffix: "8",
1373            width_tokens: quote! { px(8.) },
1374            doc_string_suffix: "8px",
1375        },
1376        BorderStyleSuffix {
1377            suffix: "9",
1378            width_tokens: quote! { px(9.) },
1379            doc_string_suffix: "9px",
1380        },
1381        BorderStyleSuffix {
1382            suffix: "10",
1383            width_tokens: quote! { px(10.) },
1384            doc_string_suffix: "10px",
1385        },
1386        BorderStyleSuffix {
1387            suffix: "11",
1388            width_tokens: quote! { px(11.) },
1389            doc_string_suffix: "11px",
1390        },
1391        BorderStyleSuffix {
1392            suffix: "12",
1393            width_tokens: quote! { px(12.) },
1394            doc_string_suffix: "12px",
1395        },
1396        BorderStyleSuffix {
1397            suffix: "16",
1398            width_tokens: quote! { px(16.) },
1399            doc_string_suffix: "16px",
1400        },
1401        BorderStyleSuffix {
1402            suffix: "20",
1403            width_tokens: quote! { px(20.) },
1404            doc_string_suffix: "20px",
1405        },
1406        BorderStyleSuffix {
1407            suffix: "24",
1408            width_tokens: quote! { px(24.) },
1409            doc_string_suffix: "24px",
1410        },
1411        BorderStyleSuffix {
1412            suffix: "32",
1413            width_tokens: quote! { px(32.) },
1414            doc_string_suffix: "32px",
1415        },
1416    ]
1417}