Skip to content

Corner Shape (Squircle, bevel, etc) support #11428

Description

@NigelBreslaw

Feature Description

Slint supports setting a border-radius on a Rectangle. This style of rounded corners is now seen as old fashioned and ugly. The issue coming from the visible transition from the semi circle that forms the shape and the horizontal or vertical line it joins to. It's one of those things that once you see it, you cannot un-see it.

Image

In the above pic you can see that after iOS 6 Apple started to use what is known as a squricle. Its a seamless transition from the corner to the vertical or horizontal side.

Figma has also supported some of this for a few years as 'corner smoothing'.

Image

Basically the slide means 0% old style corner shape. 60% iOS look. There is even an NPM package so your web app can look the same https://github.com/phamfoo/figma-squircle#readme

Late last year Squircles and more came to CSS. No more special hacks of npm packages. Rectangles still have a border-radius but they now have an additional shape property that can be square (none), squircle, round (old style), bevel, scoop and notch. You can play with it here https://www.squircle.style/ and notice that as well as the quick 'convenience' shapes you can also set the value using a function called 'superellipse()' which can be set to -2 to 3 to get all the shapes and more.

Yes the default applies it to all corners, but it also supports different radius and shape for each corner.

Further write ups here: https://orgpad.info/blog/squircles
Official MDN docs here: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/corner-shape

First Slint needs this because on MacOS and iOS these are basically the default corner shape and anything else stands out and looks 'off'. Also as part of our mission to support translating Figma designs to Slint this is a missing feature that designers will notice.
Finally it would help apps made with Slint standout and look truly modern. It's part of the complaint that Qt apps have a certain 'look' in a non positive sense. The old style corner radius makes them stand out as old fashioned. I know we can avoid this!

Product Impact

No response

Activity

  1. tronical commented on Apr 17, 2026

    @tronical
    Member

    I think this makes sense to have. Do you have any suggestions for what you think would be a good syntax in Slint for this? something like corner-shape as a property and that combines with border-radius?

  2. NigelBreslaw commented on Apr 17, 2026

    @NigelBreslaw
    MemberAuthor

    In the short term border-shape: superellipse(2); to hit every corner and then border-top-left-shape: superellipse(2), etc for the individual corners? Wish the language had a magic can be an enum or something else so you could have border-shape: squircle; as a shortcut for specific superellipse values. Much like I would love to have enum shortcuts for the transform-origin to be topLeft, center etc instead of the less intuitive (but more fine grain controllable) {x: 0, y: 0};

  3. LeonMatthes commented on Apr 17, 2026

    @LeonMatthes
    Member

    In the short term border-shape: superellipse(2); to hit every corner and then border-top-left-shape: superellipse(2), etc for the individual corners? Wish the language had a magic can be an enum or something else so you could have border-shape: squircle; as a shortcut for specific superellipse values. Much like I would love to have enum shortcuts for the transform-origin to be topLeft, center etc instead of the less intuitive (but more fine grain controllable) {x: 0, y: 0};

    This is basically named constants, right?
    Similar to:

    global BorderShape {
        out property <...> squircle: superellipse(2);
    }
    

    But would indeed be cool if you could associate some named constants with a type directly 🤔

  4. NigelBreslaw commented on Apr 17, 2026

    @NigelBreslaw
    MemberAuthor

    Isn't that also what match could do 😁

  5. ogoffart commented on Apr 17, 2026

    @ogoffart
    Member

    Another idea: just change the renderer to render all border rectangle as "superellipse".
    Or is there still case where you want the "old and ugly" rendering?

  6. added
    a:language-slintCompiler for the .slint language (mO,bF)
    and removed
    need triagingIssue that the owner of the area still need to triage
    on Apr 17, 2026
  7. NigelBreslaw commented on Apr 17, 2026

    @NigelBreslaw
    MemberAuthor

    How do you mean with just superellipse? Like a single hardcoded value you cannot change? Because there is no single value that just works without the need to be able to tweak it

  8. ogoffart commented on Apr 17, 2026

    @ogoffart
    Member

    Yeah, i mean you would just do

    Rectangle {
      background: nice-color;
      border-radius: 8px;
    }

    And it would not do a round shape, but the fancy shape with the optimal smoothing.

    But from your comment, i understand that's not a thing and that the designer really want to customize every Rectangle separately, and that you still sometimes want actual round rectangle.

    So let's assume we add a corner-shape property, what should be the default?

    1. rounded because that's what most people want
    2. rounded because that's the current behavior and changing it would break existing design in atrocious ways.
    3. squircle because that's what most people want.
  9. NigelBreslaw commented on Apr 20, 2026

    @NigelBreslaw
    MemberAuthor

    I think it has to be rounded because we would visually change everyones app. I had what was probably a similar thought, which is wouldn't it be great if the default make apps look better in Slint. However there are cases where rounded is what was intended. This isn't like font rendering where there is an objective better. It can be the design intent to use rounded (such as on smaller buttons).

  10. LeonMatthes commented on Jun 1, 2026

    @LeonMatthes
    Member

    Note: https://www.squircle.style/ does not work for me in firefox, but it does in Chrome.

    API-wise, if we want to be close to the CSS style, we should add a corner-shape type with associated constants for square, squircle, etc. and an associated squircle() function.

    If we then apply the same lookup rules as we do for enums, where functions on the property type are immediately in scope within the property binding, the API would just become:

    // basic type of the corner-shape would have to be a corner-shape type or builtin struct with
    // associated constants for rounded, etc., and a superellipse() associated function
    property <corner-shape> corner-shape-top-left: corner-shape.rounded;
    property <corner-shape> corner-shape-top-right: corner-shape.superellipse(0.5);
    // etc.
    
    // apply the same name lookup rules as we do for enums (e.g. horizontal-alignment: center), so that at use-site we can write:
    corner-shape: rounded;
    corner-shape-top-left: superellipse(0.5);
    corner-shape-top-right: superellipse(-0.5);

    Or with the proposed struct properties (#11925)

    border.shape: {
        top-left: superellipse(0.5),
    };
    
    border.shape.top-left: rounded;

    Note: Maybe we should name it border-shape instead of corner-shape? We also use border-radius, not corner-radius!

  11. ogoffart commented on Jun 5, 2026

    @ogoffart
    Member

    I feel it is strange to have a special type (corner-shape) for this.

    Just to recap what the CSS API looks like, it is a corner-shape property that takes either pre-defined keywords, or a superellipse(N) function.
    The keywords are just a shorthand for a specific value of N

    • square = Inf
    • squircle = 2
    • round = 1 (the current default)
    • bevel = 0
    • scoop = -1
    • notch = -Inf

    So i'd like to suggest something much simpler:

    element Rectangle {
        property <float> border-corner-curvature: 1.0
    }

    The reason to depart from the CSS API: the keyword/function mix doesn't fit Slint's grammar nicely. We'd need a dedicated type just to carry either an enum or superellipse(N), which is a lot of machinery for what is, in the end, one number.
    A plain float matches the math, animates cleanly.
    (Even if we don't have infinity in slint, it don't really matter in practice: at N≈20 the corner is already visually square, and you usually never want that anyway)

    I'm not even sure it is valuable to offer default values. But we could put constants in CornerCurvature.squircle if we wanted.

  12. LeonMatthes commented on Jun 5, 2026

    @LeonMatthes
    Member

    Right, that would work as well.
    The biggest downside there is that the API would be less open.
    It basically enshrines the actual shape to be a superelllipse function with this given value.

    Unsure if this is something we should care about...

  13. ogoffart commented on Jun 5, 2026

    @ogoffart
    Member

    For comparison, here is how other frameworks and design tools handle this:

    • CSS (corner-shape): keywords (round, squircle, bevel, scoop, notch, square) or superellipse(N).
    • SwiftUI / UIKit: RoundedRectangle(cornerRadius:, style: .circular | .continuous). Binary choice. .continuous is Apple's squircle and the exact curve is not exposed.
    • Jetpack Compose: RoundedCornerShape, CutCornerShape, or a custom Shape. No squircle primitive.
    • Flutter: RoundedRectangleBorder, ContinuousRectangleBorder (squircle), BeveledRectangleBorder, custom borders. One class per shape.
    • Figma: a "corner smoothing" slider from 0 to 100%. Note that this is not a superellipse — Figma uses a Bezier-based smoothing that mimics iOS.

    As you can see, CSS is the only one that exposes the superellipse exponent. Everyone else picks a handful of named shapes and hides the math.
    And there isn't really any other curve family in widespread use — it's "circular", "squircle/continuous", "bevel", maybe "cut", and that is more or less it.

    So a few options for Slint:

    1. Enum only.
      Rectangle {
          border-radius: 12px;
          border-corner-shape: CornerShape.squircle; // or: round
      }   
    1. Float only.
      Rectangle {
          border-radius: 12px;
          border-corner-curvature: 2.0; // 1 = round (default), 2 = squircle, 0 = bevel, …
      } 

    More flexible, but do we need it? Commits to superelipse.

    1. Enum + escape hatch.
      As proposed by Leon Corner Shape (Squircle, bevel, etc) support #11428 (comment)
      Similar to easing-curve and the future mouse-cursor.
      But in my opinion is a bit over-complicated as it requires a special type in the language just for that.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    a:language-slintCompiler for the .slint language (mO,bF)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions