Giter VIP home page Giter VIP logo

Comments (7)

TravisSpomer avatar TravisSpomer commented on May 19, 2024

Here's how you'd define a gradient brush using a fixed-pixel-size stop in XAML:

<LinearGradientBrush MappingMode="Absolute" StartPoint="0,0" EndPoint="0,4">
    <LinearGradientBrush.RelativeTransform>
        <RotateTransform Angle="180" CenterX="0.5" CenterY="0.5" />
        <!-- OR -->
        <ScaleTransform ScaleY="-1" CenterX="0.5" CenterY="0.5" />
    </LinearGradientBrush.RelativeTransform>
    <LinearGradientBrush.GradientStops>
        <GradientStop Offset="0" Color="Black" />
        <GradientStop Offset="1.0" Color="#c0c0c0" />
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

And here's how you'd do a fixed gradient border in CSS:

.gradient-border
{
    position: relative;

    border-radius: 4px;
    background: linear-gradient(to top, black 0%, #c0c0c0 4px);
}

.gradient-inner
{
    position: absolute;
    left: 1px;
    top: 1px;
    right: 1px;
    bottom: 1px;

    border-radius: 3px;
    background-color: white;
}

In CSS, you need to use a set of nested elements: border-image can support a gradient, but not rounded corners, so the corners of the element are missing if you try to apply a rounded corner.

.gradient-border-image
{
    position: relative;

    border: 1px solid #c0c0c0;
    border-image: linear-gradient(to top, black 0%, #c0c0c0 4px);
    border-image-slice: 1;
    /* border-radius: 4px; does not help here */
    clip-path: inset(0 round 4px);
}

An alternative is to use a pseudo-element, which has the drawbacks of putting the border outside of the element, and also introduces potential z-index and layout problems.

.gradient-border-pseudo
{
    position: relative;

    border-radius: 3px;
    background-color: white;
}

.gradient-border-pseudo::before
{
    content: "";
    z-index: -1;
    position: absolute;
    left: -1px;
    top: -1px;
    right: -1px;
    bottom: -1px;

    border-radius: 4px;
    background: linear-gradient(to top, black 0%, #c0c0c0 4px);
}

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

Examples of potential JSON syntax:

"RegularGradient": { "value": {
  "start": [0, 1],
  "end": [0, 0],
  "stops": [
    { "position": 0, "color": "black" },
    { "position": 1, "color": "#c0c0c0" }
  ]
}},
"FixedGradient": { "value": {
  "start": [0, 1],
  "end": [0, 0],
  "stops": [
    { "position": 0, "color": "black" },
    { "position": 4, "color": "#c0c0c0" }
  ],
  "stopsUnits": "pixels"
}}

That syntax would translate to CSS trivially, with stopsUnits: "pixels" indicating that the stops.position values are in pixels rather than 0-1.

To translate the pixel stops to WinUI, when stopsUnits === "pixels": let scale be the maximum position of any gradient stop, and then divide every gradient stop by scale and add the appropriate transform to the brush.

At first, we could limit gradient support to 90-degree angles, and then arbitrary angles that would require some trig to export to CSS could come later.

Direction CSS start end
Left to right to right / 270deg 0,y 1,y
Right to left to left / 90deg 1,y 0,y
Top to bottom to bottom / 0deg x,0 x,1
Bottom to top to top / 180deg x,1 x,0

(x and y can be any number 0-1 but must be the same in both start and end)

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

It might be easier to decide how to represent token references once implementation starts—we'll want to be able to reuse as much of the regular alias token infrastructure as possible. color might turn into value or even an object that contains a value if that allows for more code reuse.

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

It's also possible that it might work better with the Figma data model if start and end are just expressed as a single angle; I'm not sure yet. The Figma API for gradients uses a matrix transform which isn't super useful on its own, but QR matrix decomposition can extract the rotation angle.

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

If we imagine the start and end points are on a circle, you could calculate the start and end points from an angle like this:

FromX = (sin(angle) + 1) / 2
FromY = -(cos(angle - 1) / 2
ToX = 1 - FromX
ToY = 1 - FromY

But, after some more thinking, I don't think that's what they'd expect. For a 45-degree angle, the start point would be roughly (0.85, 0.15), but it seems more likely that a person would expect (1, 0).

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

In general, storing the From and To points rather than just the angle seems like the most expressive way of handling things, since that captures more nuance when the angle isn't a right angle. SVG gradients do it this way as well; CSS seems to be the outlier. To get the angle from two points:

Angle = atan2(ToY - FromY, FromX - ToX) mod 360

// Or, if atan2 is not available:
Angle =
  (FromX === ToX) ?
    ((ToY > FromY) ? 0 : 180) :
    (atan((ToY - FromY) / (ToX - FromX)) + (ToX > FromX ? 270 + 90))

from fluentui-token-pipeline.

TravisSpomer avatar TravisSpomer commented on May 19, 2024

As always, I made a few subtle changes from my notes here in the final implementation—check the docs for the final design.

from fluentui-token-pipeline.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.