/neu

Flutter package.

Primary LanguageDartBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

πŸ†• neu

neu icon A Neumorphic, or new skeuomorphic, helper package and class with a variety of static and instance methods for the simple generation of shaded decorations conforming to the neumorphic design concept.

These designs are often solid in terms of color variety: generally a dominant color is used as a backdrop as well as the color of controls and elements. These items would typically appear on or "above" the surface with drop shadows in standard design systems but are intended in neumorphism to extrude from or "rise out" or into the surface.

This extrusion, which can be imagined as clay- or rubber-like, is achieved by a combination of same-color elements and background, contrasting shadows, slight variances in color shading and (potentially) gradients for the impression of natural lighting.


πŸ“š Table of Contents

neu logo

  1. Getting Started
  2. Example
    1. Depth
    2. Spread
    3. Curvature
    4. Swell
    5. Light Source
  3. Generating Text Styles
  4. Rapid Deploy with NeuContainer
  5. Permutations of Curvature X Swell
  6. πŸ›£οΈ Roadmap

Getting Started

Create a new Neu object. This default constructor has all manner of defaults in the cases where values are not provided.

const Neu({
  // Foundation
  Color color = lightWhite,
  int depth = defaultDepth, // 25
  double spread = defaultSpread, // 7.5

  // Fine-tuning
  Curvature curvature = Curvature.convex,
  Swell swell = Swell.emboss,
  Alignment lightSource = defaultLightSource, // Alignment.topLeft
  
  // For specific output method calls
  NeuTextSpec neuTextSpec = const NeuTextSpec(), // buildTextStyle()
  BorderRadius borderRadius = BorderRadius.zero, // buildBoxDecoration()
  ShapeBorder shape = defaultShape, // buildShapeDecoration()
})

This Neu object has obtainable properties that begin with "build". These getters call Neu's static methods with parameters filled from the object's properties.

Consider buildLinearGradient() and buildBoxShadows(); combinations thereof: buildBoxDecoration() and buildShapeDecoration(); or for typography, buildTextStyle().

Demonstration of `Neu.textStyle`

buildTextStyle() with varying depth values

transparent 600x1 pixel-pusher (ignore) πŸ“š

As mentioned, the above properties call static helper methods by similar names. These Neu static methods may be called at any time without instantiating an object, like so:

final BoxDecoration neuDecoration = Neu.boxDecoration(
  color: Colors.indigoAccent.shade700,
  depth: 25,
  spread: 10,
  curvature: Curvature.flat,
  swell: Swell.emboss,
);

vs.

final BoxDecoration neuDecoration = Neu(
  color: Colors.indigoAccent.shade700,
  . . .
).buildBoxDecoration();
transparent 600x1 pixel-pusher (ignore) πŸ“š

Example

Click any animation below to experience the 🌐 web demo, which is more or less equivalent to the source code in the Example, and is the source for the animations.

Depth

With all Neu design the basis of these decorations is a color and a depth. Color should ideally match or be similar to the color of the background behind the resulting decoration. The depth is the extent to which this decoration will appear extruded from its surface. A larger depth increases the contrast of the shading of colors on either side of the decoration.

Demonstration of `depth`

transparent 600x1 pixel-pusher (ignore) πŸ“š

Spread

In terms of shadows, the argument spread is responsible for determining how wide an area the effect covers and how blurry the shadows appear.

Not all methods consider spread, notably linearGradient() (and buildLinearGradient() by extension) create a decoration―LinearGradient―that does not have shadows. These gradients may be combined with shadows in other situations, where spread will then be considered.

Demonstration of `spread`

transparent 600x1 pixel-pusher (ignore) πŸ“š

Curvature

A Curvature is a description of the appearance of the actual surface of the decoration. A Curvature.flat decoration has no gradient (or rather, a solid-color Gradient), while Curvature.convex orders a light -> dark gradient in a way that inspires a "bubble"-like appearance.

Other options make the effect more extreme, such as Curvature.superconvex, or reverse the effect: Curvature.concave.

See the twenty permutations of Curvature X Swell.

Demonstration of `curvature`

transparent 600x1 pixel-pusher (ignore) πŸ“š

Swell

A Swell is an overall depiction of how the decoration appears in terms of being inset into the surface or extruded from it.

  • Combining [Swell.emboss] with [Curvature.convex], the decoration will appear like a bubble lifting out of the background.

  • Combining [Swell.deboss] with [Curvature.concave], the decoration will appear like a bubble popped and depressed into the background.

This property, especially when combined with varying Curvatures can really "sell" the pressed or unpressed effect.

Demonstration of `swell`

transparent 600x1 pixel-pusher (ignore) πŸ“š

Light Source

The lightSource is always set by default as defaultLightSource, which is Alignment.topLeft. This gives the illusion of lighting the entire neumorphic decoration from the top-left corner. All descriptions of gradient and shadow directionality and the illusion of being toggled or not toggled are based on this default light source. An overriding Alignment may be provided, however, to dynamically "relight" the decorations.

  • Consider this lighting entirely artificial. Aspects of real light physics are not recreated. Simply put, this value is used to offset/shift the light and dark shadows.

Demonstration of `lightSource`

transparent 600x1 pixel-pusher (ignore) πŸ“š

Generating Text Styles

When using a Neu object and its buildTextStyle() property to generate neumorphic text decorations as opposed to the static method Neu.textStyle(), then instantiate and customize a NeuTextSpec object as well. This secondary parameter container object cleans up the Neu constructor's arguments.

Other secondary constructor arguments borderRadius and shape apply to instance methods buildBoxDecoration() and buildShapeDecoration() respectively.

transparent 600x1 pixel-pusher (ignore) πŸ“š

Rapid Deploy with NeuContainer

In some circumstances one may want to place a neumorphic element that does not already have a solid-matching-color background; or perhaps one would simply prefer to deploy Neumorphic decorations with ease and animation support; in either situation a NeuContainer may come in handy.

This glorified two-layer AnimatedContainer has a special EdgeInsets property called insets that adds additional padding beyond padding with the same color as color.

transparent 600x1 pixel-pusher (ignore) πŸ“š

Permutations of Curvature X Swell

Twenty permutations of `curvature` X `swell`

This is the fifth page (by swiping) in the Example app.

transparent 600x1 pixel-pusher (ignore) πŸ“š

πŸ›£οΈ Roadmap

  • Bespoke NeuFoo pre-built Widgets

Imagine a NeuAppBar and tab bar, NeuScrollbar or NeuSlider.

At the moment consider Neu.toggle named constructor which simplifies the customization of neumorphic appearance down to a few bool flags. These toggles mesh well with the existing paradigm for buttons to appear pressed or not pressed.

Furthermore new NeuToggle may be appropriate for some situations as a StatefulWidget that manages its own Neu.toggle and GestureDetector, rendering like an AnimatedContainer.

Large Widget Small Widget
Demonstration of `NeuToggle`, large widget Demonstration of `NeuToggle`, small widget

Each NeuToggle includes a providesFeedback flag as a convenience shortcut for HapticFeedback.vibrate() which is false by default.

Pressing-and-holding (versus a single tap) will call the onToggle callback, in void Function(bool isToggled) format, twice: once when the long-press is triggered and again when the long-press is released. The status of the toggle, with default normal value of false, is the boolean delivered with the callback.

  • Debug Props, hash, equality checks, etc.

  • Demo / Example app

Is already as good as it needs to be, but could be beefed up just a tad to make it handy, say, as a generator for decoration code without needing the package.

  • Integration with surface

  • Integration with sensors data for responsive light source

Planned integration with upcoming package sense (around the time existing packages xl and foil are transitioned to it).

  • Inner Shadows (may just be achieved through surface)

  • Custom Neu Painter

  • Interpolation

Already works pretty well through the nature of these decorations, but bespoke tweenage and lerping could be written if it seems helpful at some point.

transparent 600x1 pixel-pusher (ignore) πŸ“š


More by Zaba

Wrappers | Widgets that surround other widgets with functionality


Container Widget | Wraps many functionalities in one, very customizable


Succinct Utility | Work great alone or employed above

  • πŸ†• neu header

  • πŸ™‹β€β™‚οΈ img

  • πŸ™‹β€β™‚οΈ icon

  • πŸ“ ball

  • πŸ‘β€πŸ—¨ sense

  • πŸ‘₯ shadows

  • 🎨 spectrum header